diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index 051209e96c8d..7bda2f3f0d1b 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -149,8 +149,8 @@ binding.setVariable("generateLicensesTable", {String filePath, Set usedM notifyArtifactBuilt(filePath) }) -libraryLicense(name: "aether-api-0.9.0.M2.jar", version: "0.9.0.M2", libraryNames: ["aether-api-0.9.0.M2.jar"], license: "Eclipse Public License v1.0", url: "http://nexus.sonatype.org/", licenseUrl: "http://www.eclipse.org/org/documents/epl-v10.html") -libraryLicense(name: "aether-api", version: "1.13.1", libraryNames: ["aether-api-1.13.1.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html") +libraryLicense(name: "aether-api-0.9.0.M2.jar", version: "0.9.0.M2", libraryNames: ["aether-api-0.9.0.M2.jar"], license: "Eclipse Public License v1.0", url: "http://www.eclipse.org/aether/", licenseUrl: "http://www.eclipse.org/org/documents/epl-v10.html") +libraryLicense(name: "aether-api", version: "1.13.1", libraryNames: ["aether-api-1.13.1.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "Alloy L&F", libraryName: "alloy.jar", version: "1.4.4", license: "link (company license)", url: "http://lookandfeel.incors.com/", licenseUrl: "http://lookandfeel.incors.com/display_licence.php?back=purchase.php&selMenu=Purchase") libraryLicense(name: "Android Builder Model", libraryName: "builder-model", license: "Apache 2.0", url: "http://source.android.com/") libraryLicense(name: "Android Builder", libraryName: "android-builder", license: "Apache 2.0", url: "http://source.android.com/") @@ -161,9 +161,9 @@ libraryLicense(name: "Ant", version: "1.9", license: "Apache 2.0", url: "http:// libraryLicense(name: "ANTLR 4 Runtime", libraryName: "antlr-runtime-4.1.jar", version: "4.1", license: "BSD", url: "http://www.antlr.org", licenseUrl: "http://www.antlr.org/license.html") libraryLicense(name: "Antlr", libraryName: "antlr.jar", version: "3.4", license: "BSD", url: "http://www.antlr.org", licenseUrl: "http://www.antlr.org/license.html") libraryLicense(name: "Apache Commons BeanUtils", libraryName: "commons-beanutils.jar", version: "1.6", license: "Apache 2.0", url: "http://commons.apache.org/beanutils/") -libraryLicense(name: "Apache Commons Codec", libraryName: "commons-codec", version: "1.8", license: "Apache 2.0", url: "http://commons.apache.org/codec/", licenseUrl: "http://commons.apache.org/license.html") +libraryLicense(name: "Apache Commons Codec", libraryName: "commons-codec", version: "1.8", license: "Apache 2.0", url: "http://commons.apache.org/codec/", licenseUrl: "http://www.apache.org/licenses/") libraryLicense(name: "Apache Commons Compress", libraryName: "commons-compress-android", version: "1.0", license: "Apache 2.0", url: "http://commons.apache.org/proper/commons-compress/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") -libraryLicense(name: "Apache Commons Discovery", libraryName: "commons-discovery-0.4.jar", version: "0.4", license: "Apache 2.0", url: "http://jakarta.apache.org/commons/discovery/", licenseUrl: "http://commons.apache.org/license.html") +libraryLicense(name: "Apache Commons Discovery", libraryName: "commons-discovery-0.4.jar", version: "0.4", license: "Apache 2.0", url: "http://jakarta.apache.org/commons/discovery/", licenseUrl: "http://www.apache.org/licenses/") libraryLicense(name: "Apache Commons HTTPClient", libraryName: "http-client-3.1", version: "3.1  (with patch by JetBrains)", license: "Apache 2.0", url: "http://hc.apache.org/httpclient-3.x") libraryLicense(name: "Apache Commons IO", libraryName: "commons-io-1.4.jar", version: "1.4", license: "Apache 2.0", url: "http://commons.apache.org/io/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt") libraryLicense(name: "Apache Commons Logging", libraryName: "commons-logging", version: "1.1.1", license: "Apache 2.0", url: "http://commons.apache.org/logging/") @@ -178,15 +178,15 @@ libraryLicense(name: "ASM Bytecode Manipulation Framework", libraryName: "asm4", libraryLicense(name: "ASM Bytecode Manipulation Framework", libraryName: "asm5", version: "5.0.3 (with patches by JetBrains)", license: "BSD", url: "http://asm.objectweb.org/", licenseUrl: "http://asm.objectweb.org/license.html") libraryLicense(name: "assertJ", version: "3", license: "Apache 2.0", url: "https://github.com/joel-costigliola/assertj-core") libraryLicense(name: "Automaton", libraryName: "automaton.jar", version: "1.11", license: "BSD", url: "http://www.brics.dk/automaton/", licenseUrl: "http://www.opensource.org/licenses/bsd-license.php") -libraryLicense(name: "Axis", libraryName: "axis-1.4", version: "1.4", license: "Apache 2.0", url: "http://ws.apache.org/axis/", licenseUrl: "http://svn.jetbrains.org/idea/Trunk/bundled/WebServices/resources/lib/axis-1.4.0/axis.LICENSE") +libraryLicense(name: "Axis", libraryName: "axis-1.4", version: "1.4", license: "Apache 2.0", url: "http://ws.apache.org/axis/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.html") libraryLicense(name: "bouncy-castle", version: "1.48", license: "MIT License", url: "http://bouncycastle.org", licenseUrl: "http://bouncycastle.org/licence.html") libraryLicense(name: "CGLib", libraryName: "CGLIB", version: "2.2.2", license: "Apache", url: "http://cglib.sourceforge.net/", licenseUrl: "http://www.apache.org/foundation/licence-FAQ.html") -libraryLicense(name: "classworlds", libraryName: "classworlds-1.1.jar", version: "1.1", license: "codehaus", url: "http://classworlds.codehaus.org/", licenseUrl: "http://classworlds.codehaus.org/license.html") +libraryLicense(name: "classworlds", libraryName: "classworlds-1.1.jar", version: "1.1", license: "codehaus", url: "https://github.com/codehaus/classworlds", licenseUrl: "https://github.com/codehaus/classworlds/blob/master/classworlds/LICENSE.txt") libraryLicense(name: "coverage.py", attachedTo: "python-helpers", version: "3.7.1", license: "Apache 2.0", url: "http://coverage.readthedocs.org/") libraryLicense(name: "Cucumber-Core", libraryName: "cucumber-core", version: "1.2.4", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html") libraryLicense(name: "Cucumber-Groovy", libraryName: "cucumber-groovy", version: "1.2.4", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html") libraryLicense(name: "Cucumber-Java", libraryName: "cucumber-java", version: "1.2.4", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html") -libraryLicense(name: "Diffutils", libraryName: "Diffutils", version: "1.2.1", license: "The Apache Software License, Version 2.0", url: "http://www.apache.org/licenses/LICENSE-2.0", licenseUrl: "http://xstream.codehaus.org/license.html") +libraryLicense(name: "Diffutils", libraryName: "Diffutils", version: "1.2.1", license: "The Apache Software License, Version 2.0", url: "https://code.google.com/archive/p/java-diff-utils/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "docutils", attachedTo: "python-helpers", version: "0.8", license: "BSD", url: "http://docutils.sourceforge.net/") libraryLicense(name: "DTDParser", version: "1.13", license: "LGPL", url: "http://sourceforge.net/projects/dtdparser/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1") libraryLicense(name: "Eclipse JDT Core", libraryName: "Eclipse", version: "4.2.1", license: "CPL 1.0", url: "http://www.eclipse.org/jdt/core/index.php") @@ -196,7 +196,7 @@ libraryLicense(name: "Fest", libraryName: "fest", version: "", license: "Apache libraryLicense(name: "FreeMarker", attachedTo: "coverage", version: "2.3.15", license: "BSD", url: "http://freemarker.sourceforge.net/") libraryLicense(name: "FreeMarker", libraryName: "freemarker-2.3.20", version: "2.3.20", license: "BSD", url: "http://freemarker.sourceforge.net/") libraryLicense(name: "fxg-utils", libraryName: "fxg-utils", version: "4.9.1", license: "Apache 2.0", url: "http://flex.apache.org", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") -libraryLicense(name: "Gant", version: "1.9.8", libraryName: "gant-1.9.11_groovy-2.3.0.jar", license: "Apache 2.0", url: "http://gant.codehaus.org/", licenseUrl: "http://gant.codehaus.org/Licence") +libraryLicense(name: "Gant", version: "1.9.8", libraryName: "gant-1.9.11_groovy-2.3.0.jar", license: "Apache 2.0", url: "https://github.com/codehaus/gant", licenseUrl: "https://github.com/codehaus/gant/blob/master/LICENCE.txt") libraryLicense(name: "Gherkin", libraryName: "Gherkin", version: "2.12.2", license: "MIT", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "https://github.com/cucumber/gherkin") libraryLicense(name: "Google Feedback", libraryName: "GoogleFeedback.jar", version: "", license: "TBD") libraryLicense(name: "gradle-tooling-api-2.9.jar", version: "2.9", license: "Apache 2.0", url: "http://gradle.org/", licenseUrl: "http://gradle.org/license") @@ -210,7 +210,7 @@ libraryLicense(name: "Guava", version: "17.0", license: "Apache 2.0", url: "http libraryLicense(name: "hamcrest", version: "1.3", license: "BSD", url: "http://hamcrest.org/", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause") libraryLicense(name: "HttpComponents HttpClient", libraryName: "http-client", version: "4.3.2", license: "Apache 2.0", url: "http://hc.apache.org/httpcomponents-client-ga/index.html") libraryLicense(name: "imgscalr", libraryName: "imgscalr", version: "4.2", license: "Apache 2.0", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "https://github.com/thebuzzmedia/imgscalr") -libraryLicense(name: "batik", libraryName: "batik", version: "1.7.1", license: "Apache 2.0", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "https://svn.apache.org/repos/asf/xmlgraphics/batik") +libraryLicense(name: "batik", libraryName: "batik", version: "1.7.1", license: "Apache 2.0", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "https://xmlgraphics.apache.org/batik/") libraryLicense(name: "xmlgraphics-commons", libraryName: "xmlgraphics-commons", version: "1.5", license: "Apache 2.0", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "https://xmlgraphics.apache.org/commons/") libraryLicense(name: "xml-apis-ext", libraryName: "xml-apis-ext", version: "1.3", license: "Apache 2.0", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "http://xerces.apache.org/xml-commons/components/external") libraryLicense(name: "ImageIO", libraryName: "com.twelvemonkeys.imageio:imageio-tiff:3.2.1", version: "3.2.1", license: "BSD", url: "https://github.com/haraldk/TwelveMonkeys", licenseUrl: "https://github.com/haraldk/TwelveMonkeys#license") @@ -218,7 +218,7 @@ libraryLicense(name: "ini4j", libraryName: "ini4j-0.5.2-patched", version: "0.5. libraryLicense(name: "ISO RELAX", libraryName: "isorelax.jar", license: "MIT License", url: "http://sourceforge.net/projects/iso-relax/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html") libraryLicense(name: "Jakarta ORO", libraryName: "OroMatcher", version: "2.0.8", license: "Apache", url: "http://jakarta.apache.org/oro/", licenseUrl: "http://svn.apache.org/repos/asf/jakarta/oro/trunk/LICENSE") libraryLicense(name: "Java-WebSocket", libraryName: "java_websocket.jar", version: "1.4.0 Trunk", license: "MIT", url: "https://github.com/TooTallNate/Java-WebSocket", licenseUrl:"https://github.com/TooTallNate/Java-WebSocket/blob/master/LICENSE") -libraryLicense(name: "JavaCVS", attachedTo: "javacvs-src", version: "no version number available (with patches by JetBrains)", license: "Sun Public License", url: "https://versioncontrol.netbeans.org/javacvs/library/", licenseUrl: "http://www.netbeans.org/about/legal/spl.html") +libraryLicense(name: "JavaCVS", attachedTo: "javacvs-src", version: "no version number available (with patches by JetBrains)", license: "Sun Public License", url: "https://versioncontrol.netbeans.org/javacvs/library/", licenseUrl: "https://netbeans.org/about/legal/license.html") libraryLicense(name: "JavaHelp", version: "2.0_02", license: "included as license/javahelp_license.html in IntelliJ IDEA distribution", url: "http://java.sun.com/products/javahelp/") libraryLicense(name: "javawriter", libraryName: "javawriter", license: "Apache 2.0", url: "https://github.com/square/javawriter") libraryLicense(name: "JAXB", libraryName: "JAXB", version: "2.2.4-1", license: "CDDL 1.1", url: "http://jaxb.java.net/", licenseUrl: "http://glassfish.java.net/public/CDDL+GPL_1_1.html") @@ -230,9 +230,9 @@ libraryLicense(name: "JediTerm", libraryName: "jediterm-pty", version: "0.2", li libraryLicense(name: "JEuclid", libraryName: "jeuclid-core-3.1.9.jar", version: "3.1.9", license: "Apache 2.0", url: "http://jeuclid.sourceforge.net", licenseUrl:"http://sourceforge.net/p/jeuclid/code/ci/default/tree/LICENSE.txt") libraryLicense(name: "JGit", libraryName: "jackson", version: "2.5.1", license: "Apache 2.0", licenseUrl: "http://www.eclipse.org/org/documents/edl-v10.php", url: "https://github.com/FasterXML/jackson") libraryLicense(name: "JGit", libraryName: "jgit", version: "4.0", license: "Eclipse Distribution License 1.0", licenseUrl: "http://www.eclipse.org/org/documents/edl-v10.php", url: "https://eclipse.org/jgit/") -libraryLicense(name: "JGoodies Common", libraryName: "jgoodies-common", version: "1.2.1", license: "BSD ", url: "http://www.jgoodies.com/freeware/libraries/looks/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html") -libraryLicense(name: "JGoodies Forms", libraryName: "jgoodies-forms", version: "1.1-preview 2006-05-04 11:55:37", license: "BSD ", url: "http://www.jgoodies.com/freeware/libraries/forms/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html") -libraryLicense(name: "JGoodies Looks", libraryName: "jgoodies-looks", version: "2.4.2", license: "BSD ", url: "http://www.jgoodies.com/freeware/libraries/looks/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html") +libraryLicense(name: "JGoodies Common", libraryName: "jgoodies-common", version: "1.2.1", license: "BSD ", url: "http://www.jgoodies.com/freeware/libraries/looks/", licenseUrl: "https://opensource.org/licenses/bsd-license.html") +libraryLicense(name: "JGoodies Forms", libraryName: "jgoodies-forms", version: "1.1-preview 2006-05-04 11:55:37", license: "BSD ", url: "http://www.jgoodies.com/freeware/libraries/forms/", licenseUrl: "https://opensource.org/licenses/bsd-license.html") +libraryLicense(name: "JGoodies Looks", libraryName: "jgoodies-looks", version: "2.4.2", license: "BSD ", url: "http://www.jgoodies.com/freeware/libraries/looks/", licenseUrl: "https://opensource.org/licenses/bsd-license.html") libraryLicense(name: "JNA", libraryName: "jna", version: "4.1.0", license: "LGPL 2.1", url: "https://github.com/java-native-access/jna", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1.php") libraryLicense(name: "jsch-agent-proxy for svnkit trilead", libraryName: "jsch.agentproxy.svnkit-trilead-ssh2.jar", version: "0.0.7", license: "BSD", url: "https://github.com/ymnk/jsch-agent-proxy", licenseUrl: "https://github.com/ymnk/jsch-agent-proxy/blob/master/LICENSE.txt") libraryLicense(name: "jsch-agent-proxy", libraryName: "jsch-agent-proxy", version: "0.0.7", license: "BSD", url: "https://github.com/ymnk/jsch-agent-proxy", licenseUrl: "https://github.com/ymnk/jsch-agent-proxy/blob/master/LICENSE.txt") @@ -248,16 +248,16 @@ libraryLicense(name: "jzlib", libraryName: "jzlib", version: "1.1.1", license: " libraryLicense(name: "Kryo", libraryName: "Kryo", version: "2.22", license: "New BSD License", url: "https://github.com/EsotericSoftware/kryo", licenseUrl: "https://github.com/EsotericSoftware/kryo/blob/master/license.txt") libraryLicense(name: "kXML2", libraryName: "kxml2", version: "2.3.0", license: "BSD", url: "http://sourceforge.net/projects/kxml/") libraryLicense(name: "Lobo evolution", libraryName: "Loboevolution.jar", version: "0.98.6 (with patches by JetBrains)", license: "MIT", url: "http://sourceforge.net/projects/loboevolution/", licenseUrl: "http://opensource.org/licenses/mit-license.php") -libraryLicense(name: "Log4j", libraryName: "Log4J", version: "1.2.17", license: "Apache 2.0", url: "http://logging.apache.org/log4j/1.2/index.html", licenseUrl: "http://logging.apache.org/license.html") +libraryLicense(name: "Log4j", libraryName: "Log4J", version: "1.2.17", license: "Apache 2.0", url: "http://logging.apache.org/log4j/1.2/index.html", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "Lombok AST", libraryName: "lombok-ast", version: "0.2.1", license: "MIT", url: "http://projectlombok.org/", licenseUrl: "http://opensource.org/licenses/mit-license.php") libraryLicense(name: "markdown4j", libraryName: "markdown4j-2.2", version: "2.2", license: "New BSD", url: "https://code.google.com/p/markdown4j/", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause") -libraryLicense(name: "markdownj", attachedTo: "tasks-core", version: "", license: "BSD", url: "http://markdownj.org/", licenseUrl: "http://www.opensource.org/licenses/bsd-license.php") -libraryLicense(name: "markdownj", libraryName: "markdownj", version: "0.4.2", license: "New BSD", url: "https://code.google.com/p/markdownj/", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause") -libraryLicense(name: "maven-2.2.1-uber", version: "2.2.1", libraryNames: ["maven-2.2.1-uber.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html") -libraryLicense(name: "maven-artifact", version: "3.0.5", libraryNames: ["maven-artifact-3.0.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html") -libraryLicense(name: "maven-core", version: "3.0.5", libraryNames: ["maven-core-3.0.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html") -libraryLicense(name: "Maven", version: "2.2.1", license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html") -libraryLicense(name: "Maven3", libraryNames: ["Maven3", "maven-dependency-tree-1.2.jar", "archetype-catalog-2.2.jar", "archetype-common-2.2.jar"], version: "3.0.5", license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html") +libraryLicense(name: "markdownj", attachedTo: "tasks-core", version: "", license: "BSD", url: "https://github.com/myabc/markdownj", licenseUrl: "http://www.opensource.org/licenses/bsd-license.php") +libraryLicense(name: "markdownj", libraryName: "markdownj", version: "0.4.2", license: "New BSD", url: "https://github.com/myabc/markdownj", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause") +libraryLicense(name: "maven-2.2.1-uber", version: "2.2.1", libraryNames: ["maven-2.2.1-uber.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") +libraryLicense(name: "maven-artifact", version: "3.0.5", libraryNames: ["maven-artifact-3.0.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") +libraryLicense(name: "maven-core", version: "3.0.5", libraryNames: ["maven-core-3.0.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") +libraryLicense(name: "Maven", version: "2.2.1", license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") +libraryLicense(name: "Maven3", libraryNames: ["Maven3", "maven-dependency-tree-1.2.jar", "archetype-catalog-2.2.jar", "archetype-common-2.2.jar"], version: "3.0.5", license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "mercurial_prompthooks", attachedTo: "hg4idea", version: "", license: "GPLv2 (used as hg extension called from hg executable)", url: "https://github.com/willemv/mercurial_prompthooks", licenseUrl: "https://github.com/willemv/mercurial_prompthooks/blob/master/LICENSE.txt") libraryLicense(name: "Microba", libraryName: "microba", version: "0.4.2", license: "BSD", url: "http://microba.sourceforge.net/", licenseUrl: "http://microba.sourceforge.net/license.txt") libraryLicense(name: "MigLayout", libraryName: "miglayout-swing", version: "3.7.1", license: "BSD", url: "http://www.miglayout.com/", licenseUrl: "http://www.miglayout.com/mavensite/license.html") @@ -268,14 +268,14 @@ libraryLicense(name: "Netty", libraryName: "Netty", version: "4.1.0.Beta3", lice libraryLicense(name: "Objenesis", libraryName: "objenesis-1.2.jar", version: "1.2", license: "Apache 2.0", url: "http://objenesis.org/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0") libraryLicense(name: "opentest4j", libraryName: "opentest4j", version: "1.0.0", license: "Apache 2.0", url: "https://github.com/ota4j-team/opentest4j", licenseUrl: "http://apache.org/licenses/LICENSE-2.0") libraryLicense(name: "pep8.py", attachedTo: "python-helpers", version: "1.6.2", license: "MIT", url: "http://pep8.readthedocs.org/") -libraryLicense(name: "PicoContainer", libraryName: "picocontainer", version: "1.2", license: "BSD", url: "http://www.picocontainer.org/", licenseUrl: "http://docs.codehaus.org/display/PICO/License") +libraryLicense(name: "PicoContainer", libraryName: "picocontainer", version: "1.2", license: "BSD", url: "https://github.com/codehaus/picocontainer", licenseUrl: "https://opensource.org/licenses/bsd-license.php") libraryLicense(name: "plexus-archiver", libraryName: "plexus-archiver-2.4.4.jar", version: "2.4.4", license: "Apache 2.0", url: "https://github.com/codehaus-plexus/plexus-archiver", licenseUrl: "http://apache.org/licenses/LICENSE-2.0") libraryLicense(name: "plexus-classworlds", libraryName: "plexus-classworlds-2.4.jar", version: "2.4", license: "Apache 2.0", url: "https://github.com/codehaus-plexus/plexus-classworlds", licenseUrl: "http://apache.org/licenses/LICENSE-2.0") -libraryLicense(name: "plexus-component-annotations", version: "1.5.5", libraryNames: ["plexus-component-annotations-1.5.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html") +libraryLicense(name: "plexus-component-annotations", version: "1.5.5", libraryNames: ["plexus-component-annotations-1.5.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0") libraryLicense(name: "plexus-util", version: "2.0.6", license: "Apache 2.0", url: "http://maven.apache.org/", libraryNames:['plexus-utils-2.0.6.jar'], licenseUrl: "http://apache.org/licenses/LICENSE-2.0") libraryLicense(name: "Plexus Utils", libraryName: "plexus-utils-1.5.5.jar", version: "1.5.5", license: "Apache 2.0", url: "http://plexus.codehaus.org/plexus-utils") libraryLicense(name: "pockets", attachedTo: "python-helpers", version: "0.2.4", license: "BSD", url: "http://pockets.readthedocs.org/") -libraryLicense(name: "protobuf", version: "2.5.0", license: "New BSD", url: "http://code.google.com/p/protobuf/", licenseUrl: "http://code.google.com/p/protobuf/source/browse/trunk/COPYING.txt?r=367") +libraryLicense(name: "protobuf", version: "2.5.0", license: "New BSD", url: "http://code.google.com/p/protobuf/", licenseUrl: "https://github.com/google/protobuf/blob/master/LICENSE") libraryLicense(name: "proxy-vole", libraryName: "proxy-vole", version: "20131209", license: "New BSD License", url: "http://code.google.com/p/proxy-vole/", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause") libraryLicense(name: "pty4j", libraryName: "pty4j", version: "0.6", license: "Eclipse Public License v1.0", url: "https://github.com/traff/pty4j") libraryLicense(name: "PureJavaComm", libraryName: "purejavacomm", version: "0.0.16", license: "BSD", url: "http://www.sparetimelabs.com/purejavacomm") @@ -300,19 +300,19 @@ libraryLicense(name: "sqljet", version: "bundled with SVNKit", libraryName: "sql libraryLicense(name: "svnkit-javahl", version: "bundled with SVNKit", libraryName: "svnkit-javahl.jar", license: "link (commercial license)", url: "http://www.svnkit.com/", licenseUrl: "http://svnkit.com/license.html") libraryLicense(name: "SVNKit", libraryName: "svnkit.jar", version: "1.8.7", license: "link (commercial license)", url: "http://www.svnkit.com/", licenseUrl: "http://svnkit.com/license.html") libraryLicense(name: "swingx", libraryName: "swingx", version: "1.6.2", license: "LGPL 2.1", url: "http://java.net/downloads/swingx/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1.php") -libraryLicense(name: "TestNG", version: "6.9 snapshot", license: "Apache 2.0", url: "http://testng.org/doc/", licenseUrl: "http://code.google.com/p/testng/") +libraryLicense(name: "TestNG", version: "6.9 snapshot", license: "Apache 2.0", url: "http://testng.org/doc/", licenseUrl: "https://github.com/cbeust/testng/blob/master/LICENSE.txt") libraryLicense(name: "Trilead SSH", libraryName: "trilead-ssh2", version: "build 213 and 217", license: "BSD style (see LICENSE.txt in trilead.jar)", url: "http://www.trilead.com/SSH_Library/") libraryLicense(name: "Twitter4J", libraryName: "twitter4j-core-4.0.4.jar", version: "4.0.4", license: "Apache 2.0", url: "http://twitter4j.org/", licenseUrl: "http://twitter4j.org/en/index.html#license") 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: "Velocity", version: "1.7", license: "Apache 2.0", url: "http://velocity.apache.org/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt") libraryLicense(name: "winp", version: "1.23", 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.11", license: "Apache 2.0", url: "http://xerces.apache.org/xerces2-j/", licenseUrl: "http://xerces.apache.org/xerces2-j/") libraryLicense(name: "XML-RPC", libraryName: "XmlRPC", version: "2.0", license: "Apache 2.0", url: "http://ws.apache.org/xmlrpc/xmlrpc2/", licenseUrl: "http://ws.apache.org/xmlrpc/xmlrpc2/license.html") 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") libraryLicense(name: "XMLBeans", libraryName: "XmlBeans", version: "2.3.0", license: "Apache 2.0", url: "http://xmlbeans.apache.org/", licenseUrl: "http://svn.jetbrains.org/idea/Trunk/bundled/WebServices/resources/lib/xmlbeans-2.3.0/xmlbeans.LICENSE") -libraryLicense(name: "XStream", libraryName: "XStream", version: "1.4.2", license: "BSD License", url: "https://github.com/codehaus/xstream", licenseUrl: "http://xstream.codehaus.org/license.html") -libraryLicense(name: "XStream", version: "1.4.3", license: "BSD", url: "https://github.com/codehaus/xstream", licenseUrl: "http://xstream.codehaus.org/license.html") +libraryLicense(name: "XStream", libraryName: "XStream", version: "1.4.2", license: "BSD License", url: "https://github.com/codehaus/xstream", licenseUrl: "https://github.com/codehaus/xstream/blob/master/LICENSE.txt") +libraryLicense(name: "XStream", version: "1.4.3", license: "BSD", url: "https://github.com/codehaus/xstream", licenseUrl: "https://github.com/codehaus/xstream/blob/master/LICENSE.txt") libraryLicense(name: "YourKit Java Profiler", libraryName: "yjp-controller-api-redist.jar", version: "8.0.x", license: "link (commercial license)", url: "http://yourkit.com/", licenseUrl: "http://www.yourkit.com/purchase/license.html") jetbrainsLibrary("Coverage") diff --git a/build/scripts/unpackJdks.gant b/build/scripts/unpackJdks.gant index 209c57cd131a..3b71c7e0acda 100644 --- a/build/scripts/unpackJdks.gant +++ b/build/scripts/unpackJdks.gant @@ -4,7 +4,7 @@ import com.intellij.openapi.util.io.FileUtil import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/requests/MethodReturnValueWatcher.java b/java/debugger/impl/src/com/intellij/debugger/engine/requests/MethodReturnValueWatcher.java index 213dae83cf4a..5f7915741d8d 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/requests/MethodReturnValueWatcher.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/requests/MethodReturnValueWatcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -21,10 +21,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.ArrayUtil; -import com.sun.jdi.Method; -import com.sun.jdi.ObjectCollectedException; -import com.sun.jdi.ThreadReference; -import com.sun.jdi.Value; +import com.sun.jdi.*; import com.sun.jdi.event.Event; import com.sun.jdi.event.MethodEntryEvent; import com.sun.jdi.event.MethodExitEvent; @@ -118,6 +115,9 @@ public class MethodReturnValueWatcher { enableEntryWatching(false); } } + catch (VMDisconnectedException e) { + throw e; + } catch (Exception e) { LOG.error(e); } diff --git a/java/execution/impl/src/com/intellij/execution/stacktrace/StackTraceLine.java b/java/execution/impl/src/com/intellij/execution/stacktrace/StackTraceLine.java index c85686c80b5c..5d956fabdfb3 100644 --- a/java/execution/impl/src/com/intellij/execution/stacktrace/StackTraceLine.java +++ b/java/execution/impl/src/com/intellij/execution/stacktrace/StackTraceLine.java @@ -103,24 +103,26 @@ public class StackTraceLine { final int dollarIndex = className.indexOf('$'); if (dollarIndex != -1) className = className.substring(0, dollarIndex); PsiClass psiClass = findClass(project, className, lineNumber); - if (psiClass == null || (psiClass.getNavigationElement() instanceof PsiCompiledElement)) return null; - psiClass = (PsiClass)psiClass.getNavigationElement(); - final PsiMethod psiMethod = getMethodAtLine(psiClass, methodName, lineNumber); - if (psiMethod != null) { - return new MethodLineLocation(project, psiMethod, PsiLocation.fromPsiElement(psiClass), lineNumber); - } - else { - return null; + PsiElement navElement = psiClass == null ? null : psiClass.getNavigationElement(); + if (psiClass == null || navElement instanceof PsiCompiledElement) return null; + + if (navElement instanceof PsiClass) { + final PsiMethod psiMethod = getMethodAtLine((PsiClass)navElement, methodName, lineNumber); + if (psiMethod != null) { + return new MethodLineLocation(project, psiMethod, PsiLocation.fromPsiElement((PsiClass)navElement), lineNumber); + } } + return null; } private static PsiClass findClass(final Project project, final String className, final int lineNumber) { if (project == null) return null; final PsiManager psiManager = PsiManager.getInstance(project); PsiClass psiClass = JavaPsiFacade.getInstance(psiManager.getProject()).findClass(className, GlobalSearchScope.allScope(project)); - if (psiClass == null || (psiClass.getNavigationElement() instanceof PsiCompiledElement)) return null; - psiClass = (PsiClass)psiClass.getNavigationElement(); - final PsiFile psiFile = psiClass.getContainingFile(); + PsiElement navElement = psiClass == null ? null : psiClass.getNavigationElement(); + if (psiClass == null || navElement instanceof PsiCompiledElement) return null; + + final PsiFile psiFile = navElement.getContainingFile(); return PsiTreeUtil.getParentOfType(psiFile.findElementAt(offsetOfLine(psiFile, lineNumber)), PsiClass.class, false); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 0729b89613ce..0a4661824460 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -35,7 +35,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.impl.PsiClassImplUtil; -import com.intellij.psi.impl.PsiSuperMethodImplUtil; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.search.searches.ReferencesSearch; @@ -442,36 +441,7 @@ public class GenericsHighlightUtil { static HighlightInfo checkUnrelatedDefaultMethods(@NotNull PsiClass aClass, @NotNull PsiIdentifier classIdentifier) { - final Map> overrideEquivalent = - new THashMap>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY); - PsiClass[] supers = aClass.getSupers(); - for (int i = 0; i < supers.length; i++) { - PsiClass superClass = supers[i]; - boolean subType = false; - for (int j = 0; j < supers.length; j++) { - if (j == i) continue; - subType |= supers[j].isInheritor(supers[i], true); - } - if (subType) continue; - final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); - for (HierarchicalMethodSignature hms : superClass.getVisibleSignatures()) { - final PsiMethod method = hms.getMethod(); - if (MethodSignatureUtil.findMethodBySignature(aClass, method.getSignature(superClassSubstitutor), false) != null) continue; - final PsiClass containingClass = method.getContainingClass(); - if (containingClass == null) continue; - final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY); - if (containingClassSubstitutor == null) continue; - final PsiSubstitutor finalSubstitutor = - PsiSuperMethodImplUtil.obtainFinalSubstitutor(containingClass, containingClassSubstitutor, hms.getSubstitutor(), false); - final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, finalSubstitutor, false); - Set methods = overrideEquivalent.get(signature); - if (methods == null) { - methods = new LinkedHashSet(); - overrideEquivalent.put(signature, methods); - } - methods.add(method); - } - } + final Map> overrideEquivalent = PsiSuperMethodUtil.collectOverrideEquivalents(aClass); final boolean isInterface = aClass.isInterface(); for (Set overrideEquivalentMethods : overrideEquivalent.values()) { @@ -550,7 +520,8 @@ public class GenericsHighlightUtil { final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) continue; final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(containingClass, psiClass, PsiSubstitutor.EMPTY); - final PsiSubstitutor finalSubstitutor = PsiSuperMethodImplUtil.obtainFinalSubstitutor(containingClass, containingClassSubstitutor, hms.getSubstitutor(), false); + final PsiSubstitutor finalSubstitutor = PsiSuperMethodUtil + .obtainFinalSubstitutor(containingClass, containingClassSubstitutor, hms.getSubstitutor(), false); final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, finalSubstitutor, false); final PsiMethod foundMethod = overrideEquivalent.get(signature); PsiClass foundMethodContainingClass; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java index 4fec55781590..ddbc38ac6337 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/StreamApiMigrationInspection.java @@ -32,10 +32,7 @@ import com.intellij.psi.controlFlow.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; -import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.RedundantCastUtil; +import com.intellij.psi.util.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.IntArrayList; import org.jetbrains.annotations.Nls; @@ -103,9 +100,9 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo final PsiStatement body = statement.getBody(); if (iteratedValue != null && body != null) { final PsiType iteratedValueType = iteratedValue.getType(); - if (InheritanceUtil.isInheritor(iteratedValueType, CommonClassNames.JAVA_UTIL_COLLECTION)) { - final PsiClass iteratorClass = PsiUtil.resolveClassInType(iteratedValueType); - LOG.assertTrue(iteratorClass != null); + final PsiClass iteratorClass = PsiUtil.resolveClassInType(iteratedValueType); + final PsiClass collectionClass = JavaPsiFacade.getInstance(body.getProject()).findClass(CommonClassNames.JAVA_UTIL_COLLECTION, statement.getResolveScope()); + if (collectionClass != null && InheritanceUtil.isInheritorOrSelf(iteratorClass, collectionClass, true)) { try { final ControlFlow controlFlow = ControlFlowFactory.getInstance(holder.getProject()) .getControlFlow(body, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance()); @@ -124,8 +121,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo } if (ExceptionUtil.getThrownCheckedExceptions(new PsiElement[] {body}).isEmpty()) { - if (!(iteratedValueType instanceof PsiClassType && ((PsiClassType)iteratedValueType).isRaw()) && - isCollectCall(body, statement.getIterationParameter())) { + if (!isRawSubstitution(iteratedValueType, collectionClass) && isCollectCall(body, statement.getIterationParameter())) { boolean addAll = isAddAllCall(statement, body); holder.registerProblem(iteratedValue, "Can be replaced with " + (addAll ? "addAll call" : "collect call"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, @@ -151,6 +147,11 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo } } } + + private boolean isRawSubstitution(PsiType iteratedValueType, PsiClass collectionClass) { + return iteratedValueType instanceof PsiClassType && PsiUtil + .isRawSubstitutor(collectionClass, TypeConversionUtil.getSuperClassSubstitutor(collectionClass, (PsiClassType)iteratedValueType)); + } }; } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/miscGenerics/SuspiciousMethodCallUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/miscGenerics/SuspiciousMethodCallUtil.java index d725158a5201..9197cf6145e6 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/miscGenerics/SuspiciousMethodCallUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/miscGenerics/SuspiciousMethodCallUtil.java @@ -115,7 +115,7 @@ public class SuspiciousMethodCallUtil { argType = ((PsiPrimitiveType)argType).getBoxedType(methodCall); } - if (!(argType instanceof PsiClassType)) return null; + if (argType == null) return null; final JavaResolveResult resolveResult = methodExpression.advancedResolve(false); PsiMethod calleeMethod = (PsiMethod)resolveResult.getElement(); diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index 3aa98a200e69..503e95c702ea 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -216,11 +216,23 @@ public class LambdaUtil { public static List findFunctionCandidates(PsiClass psiClass) { if (psiClass != null && psiClass.isInterface() && !psiClass.isAnnotationType()) { final List methods = new ArrayList(); + final Map> overrideEquivalents = PsiSuperMethodUtil.collectOverrideEquivalents(psiClass); final Collection visibleSignatures = psiClass.getVisibleSignatures(); for (HierarchicalMethodSignature signature : visibleSignatures) { final PsiMethod psiMethod = signature.getMethod(); if (!psiMethod.hasModifierProperty(PsiModifier.ABSTRACT)) continue; if (psiMethod.hasModifierProperty(PsiModifier.STATIC)) continue; + final Set equivalentMethods = overrideEquivalents.get(signature); + if (equivalentMethods != null && equivalentMethods.size() > 1) { + boolean hasNonAbstractOverrideEquivalent = false; + for (PsiMethod method : equivalentMethods) { + if (!method.hasModifierProperty(PsiModifier.ABSTRACT) && !MethodSignatureUtil.isSuperMethod(method, psiMethod)) { + hasNonAbstractOverrideEquivalent = true; + break; + } + } + if (hasNonAbstractOverrideEquivalent) continue; + } if (!overridesPublicObjectMethod(signature)) { methods.add(signature); } diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java index bdc77c57a86b..2148bd45b3cb 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java @@ -17,10 +17,13 @@ package com.intellij.psi.util; import com.intellij.psi.*; import com.intellij.util.containers.HashSet; +import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.Set; public class PsiSuperMethodUtil { @@ -80,4 +83,62 @@ public class PsiSuperMethodUtil { return false; } + + @NotNull + public static PsiSubstitutor obtainFinalSubstitutor(@NotNull PsiClass superClass, + @NotNull PsiSubstitutor superSubstitutor, + @NotNull PsiSubstitutor derivedSubstitutor, + boolean inRawContext) { + if (inRawContext) { + Set typeParams = superSubstitutor.getSubstitutionMap().keySet(); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(superClass.getProject()); + superSubstitutor = factory.createRawSubstitutor(derivedSubstitutor, typeParams.toArray(new PsiTypeParameter[typeParams.size()])); + } + Map map = null; + for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(superClass)) { + PsiType type = superSubstitutor.substitute(typeParameter); + final PsiType t = derivedSubstitutor.substitute(type); + if (map == null) { + map = new THashMap(); + } + map.put(typeParameter, t); + } + + return map == null ? PsiSubstitutor.EMPTY : JavaPsiFacade.getInstance(superClass.getProject()).getElementFactory().createSubstitutor(map); + } + + @NotNull + public static Map> collectOverrideEquivalents(@NotNull PsiClass aClass) { + final Map> overrideEquivalent = + new THashMap>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY); + PsiClass[] supers = aClass.getSupers(); + for (int i = 0; i < supers.length; i++) { + PsiClass superClass = supers[i]; + boolean subType = false; + for (int j = 0; j < supers.length; j++) { + if (j == i) continue; + subType |= supers[j].isInheritor(supers[i], true); + } + if (subType) continue; + final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); + for (HierarchicalMethodSignature hms : superClass.getVisibleSignatures()) { + final PsiMethod method = hms.getMethod(); + if (MethodSignatureUtil.findMethodBySignature(aClass, method.getSignature(superClassSubstitutor), false) != null) continue; + final PsiClass containingClass = method.getContainingClass(); + if (containingClass == null) continue; + final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY); + if (containingClassSubstitutor == null) continue; + final PsiSubstitutor finalSubstitutor = + obtainFinalSubstitutor(containingClass, containingClassSubstitutor, hms.getSubstitutor(), false); + final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, finalSubstitutor, false); + Set methods = overrideEquivalent.get(signature); + if (methods == null) { + methods = new LinkedHashSet(); + overrideEquivalent.put(signature, methods); + } + methods.add(method); + } + } + return overrideEquivalent; + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java index 66421a109e0a..0c8f93252fd8 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java @@ -229,7 +229,7 @@ public class PsiSuperMethodImplUtil { if (superClass == null) continue; if (!visited.add(superClass)) continue; // cyclic inheritance final PsiSubstitutor superSubstitutor = superTypeResolveResult.getSubstitutor(); - PsiSubstitutor finalSubstitutor = obtainFinalSubstitutor(superClass, superSubstitutor, substitutor, isInRawContext); + PsiSubstitutor finalSubstitutor = PsiSuperMethodUtil.obtainFinalSubstitutor(superClass, superSubstitutor, substitutor, isInRawContext); final boolean isInRawContextSuper = (isInRawContext || PsiUtil.isRawSubstitutor(superClass, superSubstitutor)) && superClass.getTypeParameters().length != 0; Map superResult = buildMethodHierarchy(superClass, nameHint, finalSubstitutor, false, visited, isInRawContextSuper, resolveScope); @@ -373,29 +373,6 @@ public class PsiSuperMethodImplUtil { return hierarchicalMethodSignature; } - @NotNull - public static PsiSubstitutor obtainFinalSubstitutor(@NotNull PsiClass superClass, - @NotNull PsiSubstitutor superSubstitutor, - @NotNull PsiSubstitutor derivedSubstitutor, - boolean inRawContext) { - if (inRawContext) { - Set typeParams = superSubstitutor.getSubstitutionMap().keySet(); - PsiElementFactory factory = JavaPsiFacade.getElementFactory(superClass.getProject()); - superSubstitutor = factory.createRawSubstitutor(derivedSubstitutor, typeParams.toArray(new PsiTypeParameter[typeParams.size()])); - } - Map map = null; - for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(superClass)) { - PsiType type = superSubstitutor.substitute(typeParameter); - final PsiType t = derivedSubstitutor.substitute(type); - if (map == null) { - map = new THashMap(); - } - map.put(typeParameter, t); - } - - return map == null ? PsiSubstitutor.EMPTY : JavaPsiFacade.getInstance(superClass.getProject()).getElementFactory().createSubstitutor(map); - } - @NotNull public static Collection getVisibleSignatures(@NotNull PsiClass aClass) { Map map = getSignaturesMap(aClass); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java index 4c2957e7b6c1..15823d067a90 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImmediateClassType.java @@ -130,6 +130,9 @@ public class PsiImmediateClassType extends PsiClassType.Stub { if (substituted != null) { lst.add(substituted); } + else { + return PsiType.EMPTY_ARRAY; + } } return lst.toArray(createArray(lst.size())); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/CheckForFunctionalInterfaceCandidatesWhenOverrideEquivalentMethodsAreFoundInSuperInterfaces.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/CheckForFunctionalInterfaceCandidatesWhenOverrideEquivalentMethodsAreFoundInSuperInterfaces.java new file mode 100644 index 000000000000..44ac61ff8a91 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/CheckForFunctionalInterfaceCandidatesWhenOverrideEquivalentMethodsAreFoundInSuperInterfaces.java @@ -0,0 +1,12 @@ +import java.util.*; + +@FunctionalInterface +interface InfiniteIntIterator extends InfiniteIterator, PrimitiveIterator.OfInt {} + +@FunctionalInterface +interface InfiniteIterator extends Iterator { + @Override + default boolean hasNext() { + return true; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA153284.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA153284.java new file mode 100644 index 000000000000..2efeebfe6745 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA153284.java @@ -0,0 +1,19 @@ +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class Test { + public void validRedSquiggles(Stream> stream) { + final Iterator x = concat(stream + .map(cs -> cs.iterator()) + .collect(Collectors.toList()).iterator()); + final Iterator x1 = concat(stream + .map(List::iterator) + .collect(Collectors.toList()).iterator()); + } + + public static Iterator concat(final Iterator> inputs) { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeRawCollectionSubstitution.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeRawCollectionSubstitution.java new file mode 100644 index 000000000000..fdb4d9617ef5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/streamApiMigration/beforeRawCollectionSubstitution.java @@ -0,0 +1,20 @@ +// "Replace with collect" "false" + +import java.util.ArrayList; +import java.util.List; + +class Main2 { + public static void main(String[] args) { + MyList list = new MyList(); + List integerList = new ArrayList<>(); + for (Object element : list) { + if (element instanceof Integer) { + integerList.add((Integer) element); + } + } + } + + public static class MyList extends ArrayList { + + } +} diff --git a/java/java-tests/testData/inspection/suspiciousCalls/NonClassArgTypes.java b/java/java-tests/testData/inspection/suspiciousCalls/NonClassArgTypes.java new file mode 100644 index 000000000000..f3270c74262f --- /dev/null +++ b/java/java-tests/testData/inspection/suspiciousCalls/NonClassArgTypes.java @@ -0,0 +1,31 @@ +import java.util.ArrayList; +import java.util.List; + +class Main { + void suspicious(Object[][] data) { + List stringList = new ArrayList<>(); + + stringList.remove(data); + stringList.remove(data[0]); + stringList.remove(data[0][0]); + + stringList.contains(data); + stringList.contains(data[0]); + stringList.contains(data[0][0]); + + M m = new M<>(); + stringList.contains(m.get()); + + M m1 = new M<>(); + stringList.contains(m1.get()); + + M m2 = new M<>(); + stringList.contains(m2.get()); + } + + class M { + public T get() { + return null; + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java index 74c56a435b23..365fdbf30fc9 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java @@ -30,6 +30,7 @@ public class Interface8MethodsHighlightingTest extends LightCodeInsightFixtureTe public void testInheritUnrelatedDefaults() { doTest(true, false); } public void testExtensionMethods() { doTest(false, false); } public void testInheritDefaultMethodInInterface() { doTest(false, false); } + public void testCheckForFunctionalInterfaceCandidatesWhenOverrideEquivalentMethodsAreFoundInSuperInterfaces() { doTest(false, false);} public void testStaticMethodsInFunctionalInterface() { doTest(false, false); } public void testCyclicSubstitutor() { doTest(false, false); } public void testThisAccessibility() { doTest(false, false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index fce1622b589c..f68c93acfc70 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -284,6 +284,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testIDEA153284() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/SuspiciousCollectionMethodCallsTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/SuspiciousCollectionMethodCallsTest.java index 4d3ef19d9828..58c96b5562a1 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/SuspiciousCollectionMethodCallsTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/SuspiciousCollectionMethodCallsTest.java @@ -29,6 +29,10 @@ public class SuspiciousCollectionMethodCallsTest extends LightCodeInsightFixture doTest(); } + public void testNonClassArgTypes() throws Exception { + doTest(); + } + @NotNull @Override protected LightProjectDescriptor getProjectDescriptor() { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java index 93e5c9f2f5ea..fe74298cb857 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java @@ -384,13 +384,15 @@ public class JavaBuilder extends ModuleLevelBuilder { } final boolean rc; - if (!shouldForkCompilerProcess(context, chunkSdkVersion)) { + if (!shouldForkCompilerProcess(context, chunkSdkVersion, convertToNumber(getLanguageLevel(chunk.getModules().iterator().next())))) { rc = JavacMain.compile( options, files, classpath, _platformCp, sourcePath, outs, diagnosticSink, classesConsumer, context.getCancelStatus(), compilingTool ); } else { - // fork external javac + // fork external javac, compilers from SDK 1.6+ are supported + // todo: If chunkSDK is older than 1.6, we have to ask the user to specify a path to javac6+ to be used for compilation. + // todo: Add setting in compiler configuration for this. final String sdkHome = getChunkSdkHome(chunk); if (sdkHome == null) { diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, "Cannot start javac process for " + chunk.getName() + ": unknown JDK home path.\nPlease check project configuration.")); @@ -449,7 +451,7 @@ public class JavaBuilder extends ModuleLevelBuilder { return null; } - private static boolean shouldForkCompilerProcess(CompileContext context, final int chunkSdkVersion) { + private static boolean shouldForkCompilerProcess(CompileContext context, final int chunkSdkVersion, int chunkLanguageLevel) { final int compilerSdkVersion = getCompilerSdkVersion(context); if (compilerSdkVersion < 9 || chunkSdkVersion < 0) { // javac up to version 9 supports all previous releases @@ -461,10 +463,13 @@ public class JavaBuilder extends ModuleLevelBuilder { // there is no way to specify full platform classpath for cross-compilation purposes. // We have for fork compiler process with corresponding SDK runtime to ensure that compiler resolves platform classes // against the SDK version specified for the given chunk. + // todo: if chunkSdkVersion complies to "one plus three back" rule, and "-release" option is supported, return false return true; } - // according to JEP 182: Retiring javac "one plus three back" policy - return Math.abs(compilerSdkVersion - chunkSdkVersion) > 3; + + // compilerSdkVersion is 9+ here, so applying JEP 182 "Retiring javac 'one plus three back'" policy + final int requestedTargetPlatformVersion = chunkLanguageLevel > 0 ? chunkLanguageLevel : Math.min(chunkLanguageLevel, chunkSdkVersion); + return Math.abs(compilerSdkVersion - requestedTargetPlatformVersion) > 3; } // If platformCp of the build process is the same as the target plafform, do not specify platformCp explicitly diff --git a/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java b/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java index 2b304ae3f440..3153ee035154 100644 --- a/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java +++ b/platform/core-api/src/com/intellij/openapi/application/TransactionGuard.java @@ -19,6 +19,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Ref; +import com.intellij.util.ThrowableRunnable; import org.jetbrains.annotations.NotNull; /** @@ -30,7 +31,9 @@ import org.jetbrains.annotations.NotNull; * and process UI events in other ways: it's guaranteed that no one will be able to sneak in with an unexpected model change using * {@link javax.swing.SwingUtilities#invokeLater(Runnable)} or analogs.

* - * Transactions are run on UI thread. They have read access by default. All write actions should be performed inside a transaction.

+ * Transactions are run on UI thread. They have read access by default. All write actions that don't happen as the result of direct user input + * should be performed inside a transaction. No write action should be performed from within an {@code invokeLater}-like call + * unless wrapped into a transaction.

* * The recommended way to perform a transaction is to invoke {@link #submitTransaction(Runnable)}. It either runs the transaction immediately * (if on UI thread and there's no other transaction running) or queues it to invoke at some later moment, when it becomes possible.

@@ -192,4 +195,13 @@ public abstract class TransactionGuard { * @param errorMessage the message that will be logged if current transaction status differs from the expected one */ public abstract void assertInsideTransaction(boolean transactionRequired, @NotNull String errorMessage); + + /** + * Executes the given code and marks it as a user activity, to allow write actions to be run without requiring transactions. + * Please note that only direct keyboard/mouse event processing can be wrapped in such calls. If you wish to invoke some actionPerformed, + * please consider using {@code ActionManager.tryToExecute()} instead, or ensure in some other way that the action is enabled + * and can be invoked in the current modality state. + */ + public abstract void performUserActivity(ThrowableRunnable activity) throws T; + } diff --git a/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java b/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java index 620fc91fca6e..53e26bf6c5a1 100644 --- a/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/application/TransactionGuardImpl.java @@ -18,7 +18,9 @@ package com.intellij.openapi.application; import com.intellij.openapi.diagnostic.Attachment; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.impl.DebugUtil; +import com.intellij.util.ThrowableRunnable; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -37,13 +39,14 @@ public class TransactionGuardImpl extends TransactionGuard { private final Set myMergeableKinds = ContainerUtil.newHashSet(); private String myTransactionStartTrace; private ModalityState myTransactionModality; + private boolean myUserActivity; @Override @NotNull public AccessToken startSynchronousTransaction(@NotNull TransactionKind kind) throws IllegalStateException { ModalityState modality = ModalityState.current(); if (isInsideTransaction()) { - if (modality.equals(myTransactionModality)) { + if (modality.equals(myTransactionModality) || myUserActivity) { return AccessToken.EMPTY_ACCESS_TOKEN; } @@ -200,4 +203,39 @@ public class TransactionGuardImpl extends TransactionGuard { throw new RuntimeException(exception[0]); } } + + @Override + public void performUserActivity(ThrowableRunnable activity) throws T { + ApplicationManager.getApplication().assertIsDispatchThread(); + AccessToken token = startActivity(true); + try { + activity.run(); + } + finally { + token.finish(); + } + } + + /** + * An absolutely guru method, only intended to be used from Swing event processing. Please consult Peter if you think you need to invoke this. + */ + @NotNull + public AccessToken startActivity(boolean userActivity) { + if (myUserActivity == userActivity) { + return AccessToken.EMPTY_ACCESS_TOKEN; + } + + final boolean prev = myUserActivity; + myUserActivity = userActivity; + return new AccessToken() { + @Override + public void finish() { + myUserActivity = prev; + } + }; + } + + public boolean isWriteActionAllowed() { + return !Registry.is("ide.require.transaction.for.model.changes", false) || isInsideTransaction() || myUserActivity; + } } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java index fccd126640ad..bc69178dc9ab 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffViewer.java @@ -385,7 +385,11 @@ public class UnifiedDiffViewer extends ListenerDiffViewerBase { myFoldingModel.updateContext(myRequest, getFoldingModelSettings()); clearDiffPresentation(); - if (isContentsEqual) myPanel.addNotification(DiffNotifications.createEqualContents()); + if (isContentsEqual) { + boolean equalCharsets = TextDiffViewerUtil.areEqualCharsets(getContents()); + boolean equalSeparators = TextDiffViewerUtil.areEqualLineSeparators(getContents()); + myPanel.addNotification(DiffNotifications.createEqualContents(equalCharsets, equalSeparators)); + } TIntFunction separatorLines = myFoldingModel.getLineNumberConvertor(); myEditor.getGutterComponentEx().setLineNumberConvertor(mergeConverters(data.getLineConvertor1(), separatorLines), diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java index f3fcf63c4237..f1ffaaafb92c 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java @@ -19,6 +19,7 @@ import com.intellij.diff.DiffContext; import com.intellij.diff.actions.BufferedLineIterator; import com.intellij.diff.actions.NavigationContextChecker; import com.intellij.diff.comparison.DiffTooBigException; +import com.intellij.diff.contents.DocumentContent; import com.intellij.diff.fragments.LineFragment; import com.intellij.diff.requests.ContentDiffRequest; import com.intellij.diff.requests.DiffRequest; @@ -52,6 +53,7 @@ import org.jetbrains.annotations.*; import javax.swing.*; import java.awt.*; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.BitSet; import java.util.Iterator; @@ -237,7 +239,11 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer { clearDiffPresentation(); myIsContentsEqual = data.isContentsEqual(); - if (data.isContentsEqual()) myPanel.addNotification(DiffNotifications.createEqualContents()); + if (data.isContentsEqual()) { + boolean equalCharsets = TextDiffViewerUtil.areEqualCharsets(getContents()); + boolean equalSeparators = TextDiffViewerUtil.areEqualLineSeparators(getContents()); + myPanel.addNotification(DiffNotifications.createEqualContents(equalCharsets, equalSeparators)); + } if (data.getFragments() != null) { for (LineFragment fragment : data.getFragments()) { diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffNotifications.java b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffNotifications.java index 7681a2c5bae9..8421fdce6a9d 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/DiffNotifications.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/DiffNotifications.java @@ -26,13 +26,6 @@ import javax.swing.*; import java.awt.*; public class DiffNotifications { - @Deprecated @NotNull public static final JPanel INSERTED_CONTENT = createInsertedContent(); - @Deprecated @NotNull public static final JPanel REMOVED_CONTENT = createRemovedContent(); - @Deprecated @NotNull public static final JPanel EQUAL_CONTENTS = createEqualContents(); - @Deprecated @NotNull public static final JPanel ERROR = createError(); - @Deprecated @NotNull public static final JPanel OPERATION_CANCELED = createOperationCanceled(); - @Deprecated @NotNull public static final JPanel DIFF_TOO_BIG = createDiffTooBig(); - @NotNull public static JPanel createInsertedContent() { return createNotification("Content added", TextDiffType.INSERTED.getColor(null)); @@ -45,6 +38,20 @@ public class DiffNotifications { @NotNull public static JPanel createEqualContents() { + return createEqualContents(true, true); + } + + @NotNull + public static JPanel createEqualContents(boolean equalCharsets, boolean equalSeparators) { + if (!equalCharsets && !equalSeparators) { + return createNotification(DiffBundle.message("diff.contents.have.differences.only.in.charset.and.line.separators.message.text")); + } + if (!equalSeparators) { + return createNotification(DiffBundle.message("diff.contents.have.differences.only.in.line.separators.message.text")); + } + if (!equalCharsets) { + return createNotification(DiffBundle.message("diff.contents.have.differences.only.in.charset.message.text")); + } return createNotification(DiffBundle.message("diff.contents.are.identical.message.text")); } diff --git a/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffViewerUtil.java b/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffViewerUtil.java index f0be1ed3a70a..acb6f14a902e 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffViewerUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/util/base/TextDiffViewerUtil.java @@ -18,6 +18,7 @@ package com.intellij.diff.tools.util.base; import com.intellij.diff.DiffContext; import com.intellij.diff.contents.DiffContent; import com.intellij.diff.contents.DocumentContent; +import com.intellij.diff.contents.EmptyContent; import com.intellij.diff.requests.ContentDiffRequest; import com.intellij.diff.tools.util.FoldingModelSupport; import com.intellij.diff.tools.util.base.TextDiffSettingsHolder.TextDiffSettings; @@ -38,6 +39,7 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; import com.intellij.ui.ToggleActionButton; import com.intellij.util.EditorPopupHandler; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -127,6 +129,25 @@ public class TextDiffViewerUtil { } } + public static boolean areEqualLineSeparators(@NotNull List contents) { + return areEqualDocumentContentProperties(contents, DocumentContent::getLineSeparator); + } + + public static boolean areEqualCharsets(@NotNull List contents) { + return areEqualDocumentContentProperties(contents, DocumentContent::getCharset); + } + + private static boolean areEqualDocumentContentProperties(@NotNull List contents, + @NotNull Function propertyGetter) { + List properties = ContainerUtil.mapNotNull(contents, (content) -> { + if (content instanceof EmptyContent) return null; + return propertyGetter.fun((DocumentContent)content); + }); + + if (properties.size() < 2) return true; + return ContainerUtil.newHashSet(properties).size() == 1; + } + // // Actions // diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java index fbd81919c2e6..d93881d78e88 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java @@ -36,6 +36,7 @@ import com.intellij.diff.requests.ContentDiffRequest; import com.intellij.diff.requests.DiffRequest; import com.intellij.diff.tools.util.base.HighlightPolicy; import com.intellij.diff.tools.util.base.IgnorePolicy; +import com.intellij.diff.tools.util.base.TextDiffViewerUtil; import com.intellij.icons.AllIcons; import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.AnAction; @@ -98,6 +99,8 @@ import java.util.BitSet; import java.util.Collections; import java.util.List; +import static com.intellij.diff.tools.util.base.TextDiffViewerUtil.areEqualLineSeparators; + public class DiffUtil { private static final Logger LOG = Logger.getInstance(DiffUtil.class); @@ -376,23 +379,8 @@ public class DiffUtil { List contents = request.getContents(); List titles = request.getContentTitles(); - List charsets = ContainerUtil.map(contents, new Function() { - @Override - public Charset fun(DiffContent content) { - if (content instanceof EmptyContent) return null; - return ((DocumentContent)content).getCharset(); - } - }); - List separators = ContainerUtil.map(contents, new Function() { - @Override - public LineSeparator fun(DiffContent content) { - if (content instanceof EmptyContent) return null; - return ((DocumentContent)content).getLineSeparator(); - } - }); - - boolean equalCharsets = isEqualElements(charsets); - boolean equalSeparators = isEqualElements(separators); + boolean equalCharsets = TextDiffViewerUtil.areEqualCharsets(contents); + boolean equalSeparators = TextDiffViewerUtil.areEqualLineSeparators(contents); List result = new ArrayList(contents.size()); @@ -421,20 +409,6 @@ public class DiffUtil { return createStackedComponents(components, TITLE_GAP); } - private static boolean isEqualElements(@NotNull List elements) { - for (int i = 0; i < elements.size(); i++) { - for (int j = i + 1; j < elements.size(); j++) { - if (!isEqualElements(elements.get(i), elements.get(j))) return false; - } - } - return true; - } - - private static boolean isEqualElements(@Nullable Object element1, @Nullable Object element2) { - if (element1 == null || element2 == null) return true; - return element1.equals(element2); - } - @Nullable private static JComponent createTitle(@NotNull String title, @NotNull DiffContent content, diff --git a/platform/dvcs-impl/dvcs-impl.iml b/platform/dvcs-impl/dvcs-impl.iml index aebe42866489..3b75b42d7d51 100644 --- a/platform/dvcs-impl/dvcs-impl.iml +++ b/platform/dvcs-impl/dvcs-impl.iml @@ -20,6 +20,6 @@ - + \ No newline at end of file diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/MultiRootMessage.kt b/platform/dvcs-impl/src/com/intellij/dvcs/MultiRootMessage.kt index 424e19654706..b8034d1764b0 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/MultiRootMessage.kt +++ b/platform/dvcs-impl/src/com/intellij/dvcs/MultiRootMessage.kt @@ -22,37 +22,38 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.containers.ContainerUtil import com.intellij.vcsUtil.VcsImplUtil.getShortVcsRootName -class MultiRootMessage(private val myProject: Project, private val myAllRoots: Collection) { +class MultiRootMessage(private val project: Project, private val allRoots: Collection, html: Boolean) { private val LOG = Logger.getInstance(MultiRootMessage::class.java) - private val myMessages = ContainerUtil.newLinkedHashMap() + private val messages = ContainerUtil.newLinkedHashMap() + private val lineSeparator = if (html) "
\n" else "\n" fun append(root: VirtualFile, message: String): MultiRootMessage { - if (!myAllRoots.contains(root)) { - LOG.error("The root ${root.path} is unexpected: $myAllRoots") + if (!allRoots.contains(root)) { + LOG.error("The root ${root.path} is unexpected: $allRoots") return this } - if (myMessages.containsKey(root)) { + if (messages.containsKey(root)) { LOG.error("Duplicate root ${root.path} reporting message [$message]") } - myMessages.put(root, message) + messages.put(root, message) return this } fun asString(): String { - if (myMessages.isEmpty()) return ""; - if (myAllRoots.size == 1) return myMessages.values.first() - if (myMessages.size == 1) { - val (root, message) = myMessages.entries.first() - return "$message in ${getShortVcsRootName(myProject, root)}" + if (messages.isEmpty()) return ""; + if (allRoots.size == 1) return messages.values.first() + if (messages.size == 1) { + val (root, message) = messages.entries.first() + return "$message in ${getShortVcsRootName(project, root)}" } - val grouped = myMessages.keys.groupBy { myMessages[it]!!.trim() } - if (grouped.size == 1 && myAllRoots.size == myMessages.size) return myMessages.values.first() - return grouped.keys.joinToString("\n") { - val shortRootNames = grouped[it]!!.map { getShortVcsRootName(myProject, it) } + val grouped = messages.keys.groupBy { messages[it]!!.trim() } + if (grouped.size == 1 && allRoots.size == messages.size) return messages.values.first() + return grouped.keys.joinToString(lineSeparator) { + val shortRootNames = grouped[it]!!.map { getShortVcsRootName(project, it) } "$it in ${joinWithAnd(shortRootNames, 5)}" } } override fun toString(): String { - return myMessages.toString() + return messages.toString() } } diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushTargetTextField.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushTargetTextField.java index 5571c7e5df51..25686eb20781 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushTargetTextField.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushTargetTextField.java @@ -15,24 +15,23 @@ */ package com.intellij.dvcs.push.ui; -import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; -import com.intellij.ui.EditorCustomization; -import com.intellij.ui.TextFieldWithAutoCompletion; -import com.intellij.ui.TextFieldWithAutoCompletionListProvider; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.textCompletion.DefaultTextCompletionValueDescriptor; +import com.intellij.util.textCompletion.TextCompletionProvider; +import com.intellij.util.textCompletion.TextFieldWithCompletion; +import com.intellij.util.textCompletion.ValuesCompletionProvider; +import com.intellij.util.textCompletion.ValuesCompletionProvider.ValuesCompletionProviderDumbAware; import org.jetbrains.annotations.NotNull; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.util.List; -public class PushTargetTextField extends TextFieldWithAutoCompletion { - - public PushTargetTextField(@NotNull Project project, @NotNull final List targetVariants, @NotNull String defaultTargetName) { - super(project, getCompletionProvider(targetVariants), true, defaultTargetName); - setOneLineMode(true); +public class PushTargetTextField extends TextFieldWithCompletion { + public PushTargetTextField(@NotNull Project project, @NotNull List targetVariants, @NotNull String defaultTargetName) { + super(project, getCompletionProvider(targetVariants), defaultTargetName, true, true, true); addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { @@ -46,28 +45,17 @@ public class PushTargetTextField extends TextFieldWithAutoCompletion { }); } - @Override - protected EditorEx createEditor() { - // editor created lazy, so we need to update editor customization after initialization - EditorEx editorEx = super.createEditor(); - EditorCustomization customization = SpellCheckingEditorCustomizationProvider.getInstance().getDisabledCustomization(); - if (customization != null) { - customization.customize(editorEx); - } - return editorEx; - } - @Override protected void updateBorder(@NotNull final EditorEx editor) { } @NotNull - private static TextFieldWithAutoCompletionListProvider getCompletionProvider(@NotNull final List targetVariants) { - return new StringsCompletionProvider(targetVariants, null) { + private static TextCompletionProvider getCompletionProvider(@NotNull final List targetVariants) { + return new ValuesCompletionProviderDumbAware<>(new DefaultTextCompletionValueDescriptor.StringValueDescriptor() { @Override public int compare(String item1, String item2) { return Integer.valueOf(ContainerUtil.indexOf(targetVariants, item1)).compareTo(ContainerUtil.indexOf(targetVariants, item2)); } - }; + }, targetVariants); } } diff --git a/platform/dvcs-impl/testSrc/com.intellij.dvcs/MultiRootMessageTest.kt b/platform/dvcs-impl/testSrc/com.intellij.dvcs/MultiRootMessageTest.kt index 8aa186959111..4dc1da754747 100644 --- a/platform/dvcs-impl/testSrc/com.intellij.dvcs/MultiRootMessageTest.kt +++ b/platform/dvcs-impl/testSrc/com.intellij.dvcs/MultiRootMessageTest.kt @@ -24,48 +24,49 @@ import org.junit.Before import org.junit.Test import org.mockito.Mockito import org.mockito.Mockito.mock +import java.io.File class MultiRootMessageTest { - private lateinit var myProject : Project + private lateinit var project: Project @Before fun setUp() { - myProject = mock(Project::class.java) - Mockito.`when`(myProject.baseDir).thenReturn(MockVirtualFile(true, "idea")) + project = mock(Project::class.java) + Mockito.`when`(project.baseDir).thenReturn(MockVirtualFile(true, "idea")) } @Test fun `test empty message`() { - val root = myProject.baseDir - val multiRootMessage = MultiRootMessage(myProject, setOf(root)) + val root = project.baseDir + val multiRootMessage = multiRootMessage(root) assertTrue(multiRootMessage.asString().isEmpty()) } @Test fun `test single repository`() { - val root = myProject.baseDir - val multiRootMessage = MultiRootMessage(myProject, setOf(root)) + val root = project.baseDir + val multiRootMessage = multiRootMessage(root) multiRootMessage.append(root, "Pruned obsolete remote references: origin/fix1, origin/fix2") assertEquals("Pruned obsolete remote references: origin/fix1, origin/fix2", multiRootMessage.asString()) } @Test fun `test single root message in multi-root project`() { - val idea = myProject.baseDir + val idea = project.baseDir val community = createSubDir(idea, "community") - val multiRootMessage = MultiRootMessage(myProject, setOf(idea, community)) + val multiRootMessage = multiRootMessage(idea, community) multiRootMessage.append(idea, "Pruned obsolete remote references: origin/fix1, origin/fix2") assertEquals("Pruned obsolete remote references: origin/fix1, origin/fix2 in idea", multiRootMessage.asString()) } @Test fun `test two roots with same messages`() { - val idea = myProject.baseDir + val idea = project.baseDir val community = createSubDir(idea, "community") - val multiRootMessage = MultiRootMessage(myProject, setOf(idea, community)) + val multiRootMessage = multiRootMessage(idea, community) multiRootMessage.append(idea, "Pruned obsolete remote references: origin/fix1, origin/fix2") multiRootMessage.append(community, "Pruned obsolete remote references: origin/fix1, origin/fix2") assertEquals("Pruned obsolete remote references: origin/fix1, origin/fix2", multiRootMessage.asString()) @@ -73,10 +74,10 @@ class MultiRootMessageTest { @Test fun `test two roots with different messages`() { - val idea = myProject.baseDir + val idea = project.baseDir val community = createSubDir(idea, "community") - val multiRootMessage = MultiRootMessage(myProject, setOf(idea, community)) + val multiRootMessage = multiRootMessage(idea, community) multiRootMessage.append(idea, "Pruned obsolete remote references: origin/fix1, origin/fix2") multiRootMessage.append(community, "Pruned obsolete remote references: origin/fix3") assertEquals( @@ -87,24 +88,26 @@ class MultiRootMessageTest { } @Test - fun `test three roots with same message, and one root with another`() { - val idea = myProject.baseDir + fun `test html message for three roots with same message, and one root with another`() { + val idea = project.baseDir val community = createSubDir(idea, "community") val contrib = createSubDir(idea, "contrib") val android = createSubDir(community, "android") - val multiRootMessage = MultiRootMessage(myProject, setOf(idea, community, contrib, android)) + val multiRootMessage = MultiRootMessage(project, setOf(idea, community, contrib, android), true) multiRootMessage.append(idea, "Pruned obsolete remote references: origin/fix1, origin/fix2") multiRootMessage.append(community, "Pruned obsolete remote references: origin/fix3") multiRootMessage.append(contrib, "Pruned obsolete remote references: origin/fix3") multiRootMessage.append(android, "Pruned obsolete remote references: origin/fix3") assertEquals( """ - Pruned obsolete remote references: origin/fix1, origin/fix2 in idea - Pruned obsolete remote references: origin/fix3 in community, contrib and community/android + Pruned obsolete remote references: origin/fix1, origin/fix2 in idea
+ Pruned obsolete remote references: origin/fix3 in community, contrib and community${File.separator}android """.trimIndent(), multiRootMessage.asString()) } + private fun multiRootMessage(vararg roots : VirtualFile) = MultiRootMessage(project, roots.asList(), false) + private fun createSubDir(parent: VirtualFile, name: String): VirtualFile { val vf = MockVirtualFile(true, name) vf.parent = parent diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/DaltonizationFilter.java b/platform/editor-ui-api/src/com/intellij/ide/ui/DaltonizationFilter.java index ced72d726d5c..d05917088c67 100644 --- a/platform/editor-ui-api/src/com/intellij/ide/ui/DaltonizationFilter.java +++ b/platform/editor-ui-api/src/com/intellij/ide/ui/DaltonizationFilter.java @@ -8,21 +8,21 @@ final class DaltonizationFilter extends WeightFilter { public static final ImageFilter tritanopia = forTritanopia(null); public static ImageFilter forProtanopia(Double weight) { - return new DaltonizationFilter(weight, 0, 2.02344, -2.52581, 0, 1, 0, 0, 0, 1); + return new DaltonizationFilter("Protanopia", weight, 0, 2.02344, -2.52581, 0, 1, 0, 0, 0, 1); } public static ImageFilter forDeuteranopia(Double weight) { - return new DaltonizationFilter(weight, 1, 0, 0, 0.494207, 0, 1.24827, 0, 0, 1); + return new DaltonizationFilter("Deuteranopia", weight, 1, 0, 0, 0.494207, 0, 1.24827, 0, 0, 1); } public static ImageFilter forTritanopia(Double weight) { - return new DaltonizationFilter(weight, 1, 0, 0, 0, 1, 0, -0.395913, 0.801109, 0); + return new DaltonizationFilter("Tritanopia", weight, 1, 0, 0, 0, 1, 0, -0.395913, 0.801109, 0); } private final double[] myMatrix; - private DaltonizationFilter(Double weight, double... matrix) { - super(weight); + private DaltonizationFilter(String name, Double weight, double... matrix) { + super(name + " (daltonization)", weight); myMatrix = matrix; } @@ -46,12 +46,9 @@ final class DaltonizationFilter extends WeightFilter { B = srcB - B; // Shift colors towards visible spectrum (apply error modifications) // and add compensation to original values - double dstR = srcR + (0.0 * R) + (0.0 * G) + (0.0 * B); - double dstG = srcG + (0.7 * R) + (1.0 * G) + (0.0 * B); - double dstB = srcB + (0.7 * R) + (0.0 * G) + (1.0 * B); - return toRGB(srcR, srcG, srcB, - dstR < 0 ? 0 : dstR > 255 ? 255 : dstR, - dstR < 0 ? 0 : dstR > 255 ? 255 : dstG, - dstR < 0 ? 0 : dstR > 255 ? 255 : dstB); + double dstR = fix(srcR + (0.0 * R) + (0.0 * G) + (0.0 * B)); + double dstG = fix(srcG + (0.7 * R) + (1.0 * G) + (0.0 * B)); + double dstB = fix(srcB + (0.7 * R) + (0.0 * G) + (1.0 * B)); + return toRGB(srcR, srcG, srcB, dstR, dstG, dstB); } } diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/SimulationFilter.java b/platform/editor-ui-api/src/com/intellij/ide/ui/SimulationFilter.java index 86137be69739..f2b3d6942480 100644 --- a/platform/editor-ui-api/src/com/intellij/ide/ui/SimulationFilter.java +++ b/platform/editor-ui-api/src/com/intellij/ide/ui/SimulationFilter.java @@ -9,19 +9,19 @@ final class SimulationFilter extends WeightFilter { public static final ImageFilter achromatopsia = forAchromatopsia(null); public static ImageFilter forProtanopia(Double weight) { - return new SimulationFilter(weight, 0.7465, 0.2535, 1.273463, -0.073894); + return new SimulationFilter("Protanopia", weight, 0.7465, 0.2535, 1.273463, -0.073894); } - + public static ImageFilter forDeuteranopia(Double weight) { - return new SimulationFilter(weight, 1.4, -0.4, 0.968437, 0.003331); + return new SimulationFilter("Deuteranopia", weight, 1.4, -0.4, 0.968437, 0.003331); } public static ImageFilter forTritanopia(Double weight) { - return new SimulationFilter(weight, 0.1748, 0, 0.062921, 0.292119); + return new SimulationFilter("Tritanopia", weight, 0.1748, 0, 0.062921, 0.292119); } public static ImageFilter forAchromatopsia(Double weight) { - return new WeightFilter(weight) { + return new WeightFilter("Achromatopsia (simulation)", weight) { @Override int toRGB(int srcR, int srcG, int srcB) { double gray = 0.212656 * srcR + 0.715158 * srcG + 0.072186 * srcB; @@ -35,8 +35,8 @@ final class SimulationFilter extends WeightFilter { private final double myConfuseM; private final double myConfuseYint; - private SimulationFilter(Double weight, double x, double y, double m, double yint) { - super(weight); + private SimulationFilter(String name, Double weight, double x, double y, double m, double yint) { + super(name + " (simulation)", weight); myConfuseX = x; myConfuseY = y; myConfuseM = m; @@ -85,9 +85,9 @@ final class SimulationFilter extends WeightFilter { double fitG = ((dstG < 0 ? 0 : 1) - dstG) / diffG; double fitB = ((dstB < 0 ? 0 : 1) - dstB) / diffB; double adjust = Math.max(Math.max( // highest value - (fitR < 0 || 1 < fitR) ? 0 : fitR, - (fitG < 0 || 1 < fitG) ? 0 : fitG), - (fitB < 0 || 1 < fitB) ? 0 : fitB); + (fitR < 0 || 1 < fitR) ? 0 : fitR, + (fitG < 0 || 1 < fitG) ? 0 : fitG), + (fitB < 0 || 1 < fitB) ? 0 : fitB); // Shift proportional to the greatest shift dstR += adjust * diffR; dstG += adjust * diffG; diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/WeightFilter.java b/platform/editor-ui-api/src/com/intellij/ide/ui/WeightFilter.java index 8e00effef346..14a369e6e1c7 100644 --- a/platform/editor-ui-api/src/com/intellij/ide/ui/WeightFilter.java +++ b/platform/editor-ui-api/src/com/intellij/ide/ui/WeightFilter.java @@ -3,16 +3,26 @@ package com.intellij.ide.ui; import java.awt.image.RGBImageFilter; abstract class WeightFilter extends RGBImageFilter { + private final String myName; private final Double myWeight; - WeightFilter(Double weight) { - if (weight != null && (weight < 0 || 1 < weight)) { - throw new IllegalArgumentException("weight " + weight + " out of [0..1]"); + WeightFilter(String name, Double weight) { + if (weight != null) { + if (weight < 0 || 1 < weight) { + throw new IllegalArgumentException("weight " + weight + " out of [0..1]"); + } + name = name + " weight: " + weight; } + myName = name; myWeight = weight; canFilterIndexColorModel = true; } + @Override + public String toString() { + return myName; + } + @Override public final int filterRGB(int x, int y, int rgb) { return (0xFF000000 & rgb) | toRGB(0xFF & (rgb >> 16), 0xFF & (rgb >> 8), 0xFF & rgb); @@ -34,4 +44,8 @@ abstract class WeightFilter extends RGBImageFilter { srcB = (int)dstB; return (srcR << 16) | (srcG << 8) | srcB; } + + static double fix(double value) { + return Double.isNaN(value) || value < 0 ? 0 : value > 255 ? 255 : value; + } } diff --git a/platform/editor-ui-ex/src/com/intellij/application/options/EditorFontsConstants.java b/platform/editor-ui-ex/src/com/intellij/application/options/EditorFontsConstants.java new file mode 100644 index 000000000000..c1dda7b50924 --- /dev/null +++ b/platform/editor-ui-ex/src/com/intellij/application/options/EditorFontsConstants.java @@ -0,0 +1,54 @@ +/* + * Copyright 2000-2016 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.application.options; + +import com.intellij.util.ui.JBUI; + +/** + * @author Konstantin Bulenkov + */ +public class EditorFontsConstants { + public static int getMinEditorFontSize() {return JBUI.scale(4);} + + public static int getMaxEditorFontSize() {return JBUI.scale(40);} + + public static int getDefaultEditorFontSize() {return JBUI.scale(12);} + + public static float getMinEditorLineSpacing() {return JBUI.scale(.6F);} + + public static float getMaxEditorLineSpacing() {return JBUI.scale(3f);} + + public static float getDefaultEditorLineSpacing() {return JBUI.scale(1f);} + + public static int checkAndFixEditorFontSize(int size) { + return round(getMinEditorFontSize(), getMaxEditorFontSize(), size); + } + + public static float checkAndFixEditorLineSpacing(int size) { + return round(getMinEditorLineSpacing(), getMaxEditorLineSpacing(), size); + } + + private static int round(int min, int max, int val) { + return val < min ? min : val > max ? max : val; + } + + private static float round(float min, float max, float val) { + return val < min ? min : val > max ? max : val; + } + + private EditorFontsConstants() { + } +} diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java index 18e4c995590a..6fd9f3bfc839 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java @@ -19,6 +19,7 @@ */ package com.intellij.openapi.editor.colors.impl; +import com.intellij.application.options.EditorFontsConstants; import com.intellij.ide.ui.ColorBlindness; import com.intellij.ide.ui.UISettings; import com.intellij.openapi.editor.HighlighterColors; @@ -173,6 +174,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { @Override public void setEditorFontSize(int fontSize) { + fontSize = EditorFontsConstants.checkAndFixEditorFontSize(fontSize); myFontPreferences.register(getEditorFontName(), fontSize); initFonts(); } @@ -707,6 +709,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { @Override public void setConsoleFontSize(int fontSize) { + fontSize = EditorFontsConstants.checkAndFixEditorFontSize(fontSize); myConsoleFontPreferences.register(getConsoleFontName(), fontSize); initFonts(); } diff --git a/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java b/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java index b2a79a00d6ea..efcd33fd0135 100644 --- a/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java +++ b/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java @@ -79,7 +79,7 @@ public abstract class SettingsConnectionService { LOG.error(e); } return settings; - }, Collections.emptyMap(), LOG); + }, Collections.emptyMap(), LOG); } @Nullable diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java index f3cad4d24ba1..7170c9e7fe0a 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java @@ -16,7 +16,7 @@ package com.intellij.application.options.colors; -import com.intellij.application.options.OptionsConstants; +import com.intellij.application.options.EditorFontsConstants; import com.intellij.ide.BrowserUtil; import com.intellij.ide.ui.AntialiasingType; import com.intellij.ide.ui.UISettings; @@ -161,7 +161,7 @@ public class FontOptions extends JPanel implements OptionsPanel{ try { int value = Integer.parseInt(myEditorFontSizeField.getText()); value += (up ? 1 : -1); - value = Math.min(OptionsConstants.MAX_EDITOR_FONT_SIZE, Math.max(OptionsConstants.MIN_EDITOR_FONT_SIZE, value)); + value = Math.min(EditorFontsConstants.getMaxEditorFontSize(), Math.max(EditorFontsConstants.getMinEditorFontSize(), value)); myEditorFontSizeField.setText(String.valueOf(value)); } catch (NumberFormatException ignored) { @@ -188,7 +188,7 @@ public class FontOptions extends JPanel implements OptionsPanel{ try { float value = Float.parseFloat(myLineSpacingField.getText()); value += (up ? 1 : -1) * .1F; - value = Math.min(OptionsConstants.MAX_EDITOR_LINE_SPACING, Math.max(OptionsConstants.MIN_EDITOR_LINE_SPACING, value)); + value = Math.min(EditorFontsConstants.getMaxEditorLineSpacing(), Math.max(EditorFontsConstants.getMinEditorLineSpacing(), value)); myLineSpacingField.setText(String.format(Locale.ENGLISH, "%.1f", value)); } catch (NumberFormatException ignored) { @@ -200,19 +200,19 @@ public class FontOptions extends JPanel implements OptionsPanel{ private int getFontSizeFromField() { try { - return Math.min(OptionsConstants.MAX_EDITOR_FONT_SIZE, - Math.max(OptionsConstants.MIN_EDITOR_FONT_SIZE, Integer.parseInt(myEditorFontSizeField.getText()))); + return Math.min(EditorFontsConstants.getMaxEditorFontSize(), + Math.max(EditorFontsConstants.getMinEditorFontSize(), Integer.parseInt(myEditorFontSizeField.getText()))); } catch (NumberFormatException e) { - return OptionsConstants.DEFAULT_EDITOR_FONT_SIZE; + return EditorFontsConstants.getDefaultEditorFontSize(); } } private float getLineSpacingFromField() { try { - return Math.min(OptionsConstants.MAX_EDITOR_LINE_SPACING, Math.max(OptionsConstants.MIN_EDITOR_LINE_SPACING, Float.parseFloat(myLineSpacingField.getText()))); + return Math.min(EditorFontsConstants.getMaxEditorLineSpacing(), Math.max(EditorFontsConstants.getMinEditorLineSpacing(), Float.parseFloat(myLineSpacingField.getText()))); } catch (NumberFormatException e){ - return OptionsConstants.DEFAULT_EDITOR_LINE_SPACING; + return EditorFontsConstants.getDefaultEditorLineSpacing(); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java index 99c21b9dbff6..07ad9f698dcf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/LanguagePostfixTemplate.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.template.postfix.templates; +import com.intellij.ide.plugins.cl.PluginClassLoader; import com.intellij.lang.Language; import com.intellij.lang.LanguageExtension; import com.intellij.openapi.diagnostic.Logger; @@ -22,7 +23,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.List; -import java.util.Set; +import java.util.Map; public class LanguagePostfixTemplate extends LanguageExtension { private static final Logger LOG = Logger.getInstance(LanguagePostfixTemplate.class); @@ -44,13 +45,28 @@ public class LanguagePostfixTemplate extends LanguageExtension providers) { - Set templateKeys = ContainerUtil.newHashSet(); + Map templateKeys = ContainerUtil.newHashMap(); for (PostfixTemplateProvider provider : providers) { for (PostfixTemplate template : provider.getTemplates()) { - if (!templateKeys.add(template.getKey())) { - LOG.error("Duplicated key " + template.getKey() + " for language " + key.getID() + " provider " + provider.getClass()); + PostfixTemplateProvider oldProvider = templateKeys.put(template.getKey(), provider); + if (oldProvider != null) { + String oldPlugin = getPluginId(oldProvider); + String newPlugin = getPluginId(provider); + LOG.error("Duplicated postfix completion key '" + template.getKey() + "' for language " + key.getID() + + ". Possible you need to disable one of the plugins: " + oldPlugin + ", " + newPlugin); } } } } + + @NotNull + private static String getPluginId(@NotNull PostfixTemplateProvider provider) { + ClassLoader loader = provider.getClass().getClassLoader(); + if (loader instanceof PluginClassLoader) { + return ((PluginClassLoader)loader).getPluginId().getIdString(); + } + + return ""; + } + } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java index 0fdb32ffe2d8..4f1849247987 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/QuickFixAction.java @@ -25,15 +25,17 @@ import com.intellij.codeInspection.reference.RefEntity; import com.intellij.codeInspection.reference.RefManagerImpl; import com.intellij.codeInspection.ui.InspectionResultsView; import com.intellij.codeInspection.ui.InspectionTree; +import com.intellij.codeInspection.ui.QuickFixToolbar; import com.intellij.icons.AllIcons; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CustomShortcutSet; +import com.intellij.ide.DataManager; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ex.CustomComponentAction; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; @@ -41,6 +43,8 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiUtilCore; +import com.intellij.ui.ClickListener; +import com.intellij.ui.IdeBorderFactory; import com.intellij.util.SequentialModalProgressTask; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; @@ -49,12 +53,13 @@ import javax.swing.*; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; +import java.awt.event.MouseEvent; import java.util.*; /** * @author max */ -public class QuickFixAction extends AnAction { +public class QuickFixAction extends AnAction implements CustomComponentAction { private static final Logger LOG = Logger.getInstance("#" + QuickFixAction.class.getName()); public static final QuickFixAction[] EMPTY = new QuickFixAction[0]; @@ -307,6 +312,32 @@ public class QuickFixAction extends AnAction { return true; } + @Override + public JComponent createCustomComponent(Presentation presentation) { + final JButton button = new JButton(presentation.getText()); + Icon icon = presentation.getIcon(); + if (icon == null) { + icon = AllIcons.Actions.CreateFromUsage; + } + button.setEnabled(presentation.isEnabled()); + button.setIcon(IconLoader.getTransparentIcon(icon, 0.75f)); + new ClickListener() { + @Override + public boolean onClick(@NotNull MouseEvent event, int clickCount) { + actionPerformed(AnActionEvent.createFromAnAction(QuickFixAction.this, + event, + ActionPlaces.UNKNOWN, + DataManager.getInstance().getDataContext(button))); + return true; + } + }.installOn(button); + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS)); + panel.setBorder(IdeBorderFactory.createEmptyBorder(7, 0, 8, 0)); + panel.add(button); + return panel; + } + private class PerformFixesTask extends PerformFixesModalTask { @NotNull private final GlobalInspectionContextImpl myContext; @NotNull diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionNodeInfo.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionNodeInfo.java index d39b8b27c179..86932581b6c7 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionNodeInfo.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionNodeInfo.java @@ -19,14 +19,12 @@ import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInspection.ex.DisableInspectionToolAction; import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.codeInspection.ex.InspectionToolWrapper; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel; import com.intellij.ui.*; import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBLabelDecorator; -import com.intellij.ui.components.JBScrollPane; import com.intellij.util.ui.JBInsets; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; @@ -78,8 +76,8 @@ public class InspectionNodeInfo extends JPanel { JScrollPane pane = ScrollPaneFactory.createScrollPane(description, true); add(pane, - new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, - new JBInsets(0, 12, 0, 0), 0, 0)); + new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.VERTICAL, + new JBInsets(0, 10, 0, 0), getFontMetrics(UIUtil.getLabelFont()).charWidth('f') * 110 - pane.getMinimumSize().width, 0)); add(myButton, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new JBInsets(15, 9, 9, 0), 0, 0)); diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java index 7dce42438570..ccced5ca3302 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java @@ -40,6 +40,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.project.DumbAware; @@ -138,6 +139,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren mySplitter = new OnePixelSplitter(false, AnalysisUIOptions.getInstance(myProject).SPLITTER_PROPORTION); mySplitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myTree, SideBorder.LEFT)); + mySplitter.setHonorComponentsMinimumSize(false); mySplitter.addPropertyChangeListener(evt -> { if (Splitter.PROP_PROPORTION.equals(evt.getPropertyName())) { @@ -396,7 +398,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren mySplitter.setSecondComponent(getNothingToShowTextLabel()); } else { - showInRightPanel(myTree.getCommonSelectedElement()); + showInRightPanel(myTree.getCommonSelectedElement(), oldEditor == null); } } else { @@ -405,12 +407,12 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren final InspectionTreeNode node = (InspectionTreeNode)pathSelected.getLastPathComponent(); if (node instanceof ProblemDescriptionNode) { final ProblemDescriptionNode problemNode = (ProblemDescriptionNode)node; - showInRightPanel(problemNode.getElement()); + showInRightPanel(problemNode.getElement(), oldEditor == null); } else if (node instanceof InspectionPackageNode || node instanceof InspectionModuleNode || node instanceof RefElementNode) { - showInRightPanel(node.getContainingFileLocalEntity()); + showInRightPanel(node.getContainingFileLocalEntity(), oldEditor == null); } else if (node instanceof InspectionNode) { final String shortName = ((InspectionNode)node).getToolWrapper().getShortName(); @@ -418,7 +420,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren mySplitter.setSecondComponent(getNothingToShowTextLabel()); } else { - showInRightPanel(null); + showInRightPanel(null, oldEditor == null); } } else if (node instanceof InspectionRootNode || node instanceof InspectionGroupNode || node instanceof InspectionSeverityGroupNode) { @@ -452,7 +454,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren return multipleSelectionLabel; } - private void showInRightPanel(@Nullable final RefEntity refEntity) { + private void showInRightPanel(@Nullable final RefEntity refEntity, boolean hasNoEditorToReuse) { Cursor currentCursor = getCursor(); try { setCursor(new Cursor(Cursor.WAIT_CURSOR)); @@ -470,7 +472,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren } editorPanel.add(previewPanel, BorderLayout.CENTER); if (problemCount > 0) { - final QuickFixToolbar fixToolbar = new QuickFixToolbar(myPreviewEditor == null || myPreviewEditor.getUserData(PREVIEW_EDITOR_IS_REUSED_KEY) == null + final QuickFixToolbar fixToolbar = new QuickFixToolbar(myPreviewEditor == null || (!hasNoEditorToReuse && myPreviewEditor.getUserData(PREVIEW_EDITOR_IS_REUSED_KEY) == null) ? null : myPreviewEditor, this); myLoadingProgressPreview = fixToolbar; @@ -521,9 +523,11 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren settings.setLeadingWhitespaceShown(true); settings.setRightMarginShown(true); settings.setRightMargin(60); + myPreviewEditor.getColorsScheme().setColor(EditorColors.GUTTER_BACKGROUND, myPreviewEditor.getColorsScheme().getDefaultBackground()); myPreviewEditor.getScrollPane().setBorder(IdeBorderFactory.createBorder(SideBorder.TOP)); UsagePreviewPanel.highlight(Collections.emptyList(), myPreviewEditor, myProject); } + myPreviewEditor.getSettings().setFoldingOutlineShown(problemCount != 1); if (problemCount == 1) { final PsiElement finalSelectedElement = selectedElement; diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionViewNavigationPanel.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionViewNavigationPanel.java index da25b546f6e4..110222cdaaab 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionViewNavigationPanel.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionViewNavigationPanel.java @@ -50,6 +50,21 @@ public class InspectionViewNavigationPanel extends JPanel implements InspectionT resetChildrenNavigation(); } + @Override + public void updateLoadingProgress() { + resetChildrenAndRepaint(); + } + + @Override + public void treeLoaded() { + resetChildrenAndRepaint(); + } + + @NotNull + public static String getTitleText(boolean addGroupWord, boolean addColon) { + return "Select inspection" + (addGroupWord ? " group " : " ") + "to see problems" + (addColon ? ":" : "."); + } + private void resetChildrenNavigation() { final int currentChildrenCount = myNode.getChildCount(); if (myShownChildrenCount != currentChildrenCount) { @@ -70,18 +85,9 @@ public class InspectionViewNavigationPanel extends JPanel implements InspectionT } } - @NotNull - public static String getTitleText(boolean addGroupWord, boolean addColon) { - return "Select inspection" + (addGroupWord ? " group " : " ") + "to see problems" + (addColon ? ":" : "."); - } - - @Override - public void updateLoadingProgress() { - resetChildrenNavigation(); - } - - @Override - public void treeLoaded() { + private void resetChildrenAndRepaint() { resetChildrenNavigation(); + revalidate(); + repaint(); } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java index 181b7fecf479..c05757c1cf4e 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java @@ -20,28 +20,21 @@ import com.intellij.codeInspection.ex.InspectionToolWrapper; import com.intellij.codeInspection.ex.QuickFixAction; import com.intellij.codeInspection.ui.actions.SuppressActionWrapper; import com.intellij.icons.AllIcons; -import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; -import com.intellij.openapi.actionSystem.ex.CustomComponentAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.IconLoader; -import com.intellij.ui.ClickListener; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.SimpleColoredComponent; import com.intellij.util.ui.AsyncProcessIcon; -import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.TreePath; import java.awt.*; -import java.awt.event.MouseEvent; -import java.util.function.Supplier; /** * @author Dmitry Batkovich @@ -49,7 +42,6 @@ import java.util.function.Supplier; public class QuickFixToolbar extends JPanel implements InspectionTreeLoadingProgressAware { private static final Logger LOG = Logger.getInstance(QuickFixToolbar.class); private static final int MAX_FIX_COUNT = 3; - @Nullable private final String myTargetName; @NotNull private final InspectionResultsView myView; private final InspectionToolWrapper myWrapper; private final ProblemPreviewEditorFoldings myFoldings; @@ -66,13 +58,12 @@ public class QuickFixToolbar extends JPanel implements InspectionTreeLoadingProg int problemCount = descriptors.length; setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); - myTargetName = getTargetName(); if (view.isUpdating() && !areDescriptorNodesSelected()) { setBorder(IdeBorderFactory.createEmptyBorder(16, 9, 13, 0)); AsyncProcessIcon waitingIcon = new AsyncProcessIcon("Inspection preview panel updating..."); Disposer.register(this, waitingIcon); - myWaitingLabel = getLabel(null, problemCount); + myWaitingLabel = getLabel(problemCount); add(myWaitingLabel); add(waitingIcon); } @@ -102,7 +93,7 @@ public class QuickFixToolbar extends JPanel implements InspectionTreeLoadingProg if (myWaitingLabel != null) { myWaitingLabel.clear(); final InspectionTree tree = myView.getTree(); - appendTextToLabel(myWaitingLabel, tree.getSelectedProblemCount(), null); + appendTextToLabel(myWaitingLabel, tree.getSelectedProblemCount()); } } @@ -114,18 +105,20 @@ public class QuickFixToolbar extends JPanel implements InspectionTreeLoadingProg boolean hasFixes = fixes != null && fixes.length != 0; int problemCount = descriptors.length; boolean multipleDescriptors = problemCount > 1; - fill(multipleDescriptors, () -> getLabel(fixes, problemCount), this); - fill(hasFixes, () -> createFixPanel(fixes, multipleDescriptors), this); - fill(true, () -> createSuppressionCombo(myWrapper, tree.getSelectionPaths(), project, multipleDescriptors), this); - } - - @Nullable - private String getTargetName() { - if (myView.getTree().getSelectionCount() == 1) { - final Object node = myView.getTree().getSelectionPath().getLastPathComponent(); - return node instanceof RefElementNode ? ((RefElementNode)node).getElement().getName() : null; + setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); + if (multipleDescriptors) { + add(getLabel(problemCount)); } - return null; + + final DefaultActionGroup actions = new DefaultActionGroup(); + if (hasFixes) { + actions.addAll(createFixActions(fixes, multipleDescriptors)); + } + actions.add(createSuppressionCombo(myWrapper, tree.getSelectionPaths(), project)); + final ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, actions, true); + final JComponent component = toolbar.getComponent(); + toolbar.setTargetComponent(this); + add(component); } private boolean areDescriptorNodesSelected() { @@ -139,34 +132,25 @@ public class QuickFixToolbar extends JPanel implements InspectionTreeLoadingProg } @NotNull - private SimpleColoredComponent getLabel(QuickFixAction[] fixes, int problemsCount) { + private static SimpleColoredComponent getLabel(int problemsCount) { SimpleColoredComponent label = new SimpleColoredComponent(); - appendTextToLabel(label, problemsCount, fixes); + appendTextToLabel(label, problemsCount); label.setBorder(IdeBorderFactory.createEmptyBorder(0, 0, 0, 2)); return label; } - private void appendTextToLabel(SimpleColoredComponent label, - int problemsCount, - QuickFixAction[] fixes) { - boolean hasFixesNonIntersectedFixes = fixes != null && fixes.length == 0; - label.append(problemsCount + " problems" + - (myTargetName == null ? "" : (" in " + myTargetName)) + - (problemsCount > 1 && (fixes != null && fixes.length >= MAX_FIX_COUNT) ? " Fix all:" : "") + - (!hasFixesNonIntersectedFixes ? ":" : "")); - if (hasFixesNonIntersectedFixes) { - label.append(" select a single problem to see its quick fixes"); - } + private static void appendTextToLabel(SimpleColoredComponent label, + int problemsCount) { + label.append(problemsCount + " problems:"); } - private static JComponent createSuppressionCombo(@NotNull final InspectionToolWrapper toolWrapper, - @NotNull final TreePath[] paths, - @NotNull final Project project, - boolean multipleDescriptors) { + private static AnAction createSuppressionCombo(@NotNull final InspectionToolWrapper toolWrapper, + @NotNull final TreePath[] paths, + @NotNull final Project project) { final AnAction[] suppressors = new SuppressActionWrapper(project, toolWrapper, paths).getChildren(null); final ComboBoxAction action = new ComboBoxAction() { { - getTemplatePresentation().setText(multipleDescriptors ? "Suppress All" : "Suppress"); + getTemplatePresentation().setText("Suppress"); getTemplatePresentation().setEnabledAndVisible(suppressors.length != 0); } @@ -179,26 +163,11 @@ public class QuickFixToolbar extends JPanel implements InspectionTreeLoadingProg } }; action.setSmallVariant(false); - return fixComboBoxActionComponent(action.createCustomComponent(action.getTemplatePresentation())); - } - - private static JComponent fixComboBoxActionComponent(JComponent component) { - JPanel containingPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); - containingPanel.add(component); - containingPanel.setBorder(IdeBorderFactory.createEmptyBorder(7, 0, 8, 0)); - return containingPanel; - } - - private static void fill(boolean add, - @NotNull Supplier componentSupplier, - @NotNull JPanel parent) { - if (add) { - parent.add(componentSupplier.get()); - } + return action; } @NotNull - private static JComponent createFixPanel(QuickFixAction[] fixes, boolean multipleDescriptors) { + private static AnAction[] createFixActions(QuickFixAction[] fixes, boolean multipleDescriptors) { if (fixes.length > MAX_FIX_COUNT) { final ComboBoxAction fixComboBox = new ComboBoxAction() { { @@ -217,71 +186,8 @@ public class QuickFixToolbar extends JPanel implements InspectionTreeLoadingProg return actionGroup; } }; - return fixComboBoxActionComponent(fixComboBox.createCustomComponent(fixComboBox.getTemplatePresentation())); - } - else { - JPanel fixPanel = new JPanel(); - fixPanel.setLayout(new BoxLayout(fixPanel, BoxLayout.LINE_AXIS)); - fixPanel.setBorder(IdeBorderFactory.createEmptyBorder(7, 0, 8, 0)); - final boolean multipleFixes = fixes.length > 1; - for (QuickFixAction fix : fixes) { - fixPanel.add(createQuickFixButton(fix, multipleDescriptors && !multipleFixes)); - if (fix != fixes[fixes.length - 1]) { - fixPanel.add(Box.createHorizontalStrut(3)); - } - } - return fixPanel; - } - } - - private static JComponent createQuickFixButton(@NotNull QuickFixAction fix, boolean multipleFixes) { - final MyCustomComponentLocalQuickFixWrapper action = new MyCustomComponentLocalQuickFixWrapper(fix); - if (multipleFixes) { - action.getTemplatePresentation().setText("Fix all '" + fix.getText() + "'"); - } - return action.createCustomComponent(action.getTemplatePresentation()); - } - - private static class MyCustomComponentLocalQuickFixWrapper extends AnAction implements CustomComponentAction { - private QuickFixAction myUnderlying; - - public MyCustomComponentLocalQuickFixWrapper(@NotNull QuickFixAction underlying) { - myUnderlying = underlying; - copyFrom(underlying); - } - - - @Override - public JComponent createCustomComponent(Presentation presentation) { - final JButton button = new JButton(presentation.getText()); - Icon icon = presentation.getIcon(); - if (icon == null) { - icon = AllIcons.Actions.CreateFromUsage; - } - button.setEnabled(presentation.isEnabled()); - button.setIcon(IconLoader.getTransparentIcon(icon, 0.75f)); - new ClickListener() { - @Override - public boolean onClick(@NotNull MouseEvent event, int clickCount) { - actionPerformed(AnActionEvent.createFromAnAction(MyCustomComponentLocalQuickFixWrapper.this, - event, - "LOCAL_QUICK_FIX_WRAPPER_PANEL", - DataManager.getInstance().getDataContext(button))); - return true; - } - }.installOn(button); - return button; - } - - - @Override - public void update(AnActionEvent e) { - myUnderlying.update(e); - } - - @Override - public void actionPerformed(AnActionEvent e) { - myUnderlying.actionPerformed(e); + return new AnAction[] {fixComboBox}; } + return fixes; } } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java index 502ff5851c92..bbc74f4bb4e5 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java @@ -29,6 +29,7 @@ import com.intellij.openapi.actionSystem.ex.ActionUtil; import com.intellij.openapi.actionSystem.ex.QuickList; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.application.TransactionGuard; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapManager; @@ -250,10 +251,9 @@ public class GotoActionAction extends GotoActionBase implements DumbAware { public static void performAction(Object element, @Nullable final Component component, @Nullable final AnActionEvent e) { // element could be AnAction (SearchEverywhere) final AnAction action = element instanceof AnAction ? (AnAction)element : ((GotoActionModel.ActionWrapper)element).getAction(); - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - if (component == null) return; + ApplicationManager.getApplication().invokeLater(() -> { + if (component == null) return; + TransactionGuard.getInstance().performUserActivity(() -> { DataManager instance = DataManager.getInstance(); DataContext context = instance != null ? instance.getDataContext(component) : DataContext.EMPTY_CONTEXT; InputEvent inputEvent = e == null ? null : e.getInputEvent(); @@ -270,12 +270,12 @@ public class GotoActionAction extends GotoActionBase implements DumbAware { else { popup.showInFocusCenter(); } - } + } else { ActionUtil.performActionDumbAware(action, event); } } - } + }); }, ModalityState.NON_MODAL); } diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/LRUPopupBuilder.java b/platform/lang-impl/src/com/intellij/ide/scratch/LRUPopupBuilder.java index 77601cc4b877..6a15f3c5b5b8 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/LRUPopupBuilder.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/LRUPopupBuilder.java @@ -19,12 +19,19 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.Language; import com.intellij.lang.LanguageUtil; import com.intellij.lang.PerFileMappings; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.command.undo.BasicUndoableAction; +import com.intellij.openapi.command.undo.UndoManager; +import com.intellij.openapi.command.undo.UnexpectedUndoException; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.*; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.ReadonlyStatusHandler; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; @@ -38,10 +45,9 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.util.Collections; -import java.util.Comparator; +import java.io.IOException; +import java.util.*; import java.util.List; -import java.util.Map; /** * @author gregsh @@ -62,13 +68,23 @@ public abstract class LRUPopupBuilder { private JBIterable myExtraItems = JBIterable.empty(); @NotNull - public static ListPopup forFileLanguages(@NotNull Project project, @NotNull final Iterable files, @NotNull final PerFileMappings mappings) { + public static ListPopup forFileLanguages(@NotNull Project project, @NotNull Iterable files, @NotNull final PerFileMappings mappings) { + final VirtualFile[] filesCopy = VfsUtilCore.toVirtualFileArray(JBIterable.from(files).toList()); + Arrays.sort(filesCopy, new Comparator() { + @Override + public int compare(VirtualFile o1, VirtualFile o2) { + return StringUtil.compare(o1.getName(), o2.getName(), !o1.getFileSystem().isCaseSensitive()); + } + }); return forFileLanguages(project, null, new Consumer() { @Override - public void consume(Language t) { - for (VirtualFile file : files) { - mappings.setMapping(file, t); - } + public void consume(final Language t) { + new WriteCommandAction(project, "Change Language") { + @Override + protected void run(@NotNull Result result) throws Throwable { + changeLanguageWithUndo(project, t, filesCopy, mappings); + } + }.execute(); } }); } @@ -260,4 +276,47 @@ public abstract class LRUPopupBuilder { return getClass().getName() + "/" + myTitle; } + + private static void changeLanguageWithUndo(@NotNull Project project, + @NotNull final Language t, + @NotNull final VirtualFile[] sortedFiles, + @NotNull final PerFileMappings mappings) throws UnexpectedUndoException { + ReadonlyStatusHandler.OperationStatus status = ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(sortedFiles); + if (status.hasReadonlyFiles()) return; + + final Set matchedExtensions = ContainerUtil.newLinkedHashSet(); + final Map oldMapping = ContainerUtil.newHashMap(); + for (VirtualFile file : sortedFiles) { + oldMapping.put(file, mappings.getMapping(file)); + if (ScratchUtil.hasMatchingExtension(project, file)) { + matchedExtensions.add(file); + } + } + + BasicUndoableAction action = new BasicUndoableAction(sortedFiles) { + @Override + public void undo() throws UnexpectedUndoException { + for (VirtualFile file : sortedFiles) { + mappings.setMapping(file, oldMapping.get(file)); + } + } + + @Override + public void redo() throws UnexpectedUndoException { + for (VirtualFile file : sortedFiles) { + mappings.setMapping(file, t); + } + } + }; + action.redo(); + UndoManager.getInstance(project).undoableActionPerformed(action); + + for (VirtualFile file : matchedExtensions) { + try { + ScratchUtil.updateFileExtension(project, file); + } + catch (IOException ignored) { + } + } + } } diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileActions.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileActions.java index 80aa2bb61178..3e5edb681115 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileActions.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileActions.java @@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; @@ -37,6 +38,7 @@ import com.intellij.psi.PsiFile; import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.ObjectUtils; +import com.intellij.util.PathUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.JBIterable; import org.jetbrains.annotations.NotNull; @@ -111,9 +113,11 @@ public class ScratchFileActions { static void doCreateNewScratch(@NotNull Project project, boolean buffer, @NotNull Language language, @NotNull String text) { FeatureUsageTracker.getInstance().triggerFeatureUsed("scratch"); + LanguageFileType fileType = language.getAssociatedFileType(); + String ext = buffer || fileType == null? "" : fileType.getDefaultExtension(); String fileName = buffer ? "buffer" + nextBufferIndex() : "scratch"; ScratchFileService.Option option = buffer ? ScratchFileService.Option.create_if_missing : ScratchFileService.Option.create_new_always; - VirtualFile f = ScratchRootType.getInstance().createScratchFile(project, fileName, language, text, option); + VirtualFile f = ScratchRootType.getInstance().createScratchFile(project, PathUtil.makeFileName(fileName, ext), language, text, option); if (f != null) { FileEditorManager.getInstance(project).openFile(f, true); } diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchUtil.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchUtil.java index 124e220ecb9c..5e60577fb799 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchUtil.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchUtil.java @@ -15,9 +15,21 @@ */ package com.intellij.ide.scratch; +import com.intellij.lang.Language; +import com.intellij.lang.LanguageUtil; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.PathUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.IOException; + /** * @author gregsh */ @@ -33,4 +45,33 @@ public class ScratchUtil { public static boolean isScratch(@Nullable VirtualFile file) { return file != null && file.getFileType() == ScratchFileType.INSTANCE; } + + public static void updateFileExtension(@NotNull Project project, @Nullable VirtualFile file) throws IOException { + ApplicationManager.getApplication().assertWriteAccessAllowed(); + if (CommandProcessor.getInstance().getCurrentCommand() == null) { + throw new AssertionError("command required"); + } + + if (file == null) return; + Language language = LanguageUtil.getLanguageForPsi(project, file); + String extension = file.getExtension(); + FileType expected = extension == null ? null : FileTypeManager.getInstance().getFileTypeByExtension(extension); + FileType actual = language == null ? null : language.getAssociatedFileType(); + if (expected == actual || actual == null) return; + String ext = actual.getDefaultExtension(); + if (StringUtil.isEmpty(ext)) return; + + String newName = PathUtil.makeFileName(file.getNameWithoutExtension(), ext); + VirtualFile parent = file.getParent(); + newName = parent != null && parent.findChild(newName) != null ? PathUtil.makeFileName(file.getName(), ext) : newName; + file.rename(ScratchUtil.class, newName); + } + + public static boolean hasMatchingExtension(@NotNull Project project, @NotNull VirtualFile file) { + String extension = file.getExtension(); + Language language = LanguageUtil.getLanguageForPsi(project, file); + FileType expected = extension == null ? null : FileTypeManager.getInstance().getFileTypeByExtension(extension); + FileType actual = language == null ? null : language.getAssociatedFileType(); + return expected == actual && actual != null; + } } diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java index 2d84961be490..020b3a2ba9aa 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java @@ -30,6 +30,7 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.highlighter.HighlighterIterator; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.TextRange; @@ -53,9 +54,16 @@ public class SelectWordAtCaretAction extends TextComponentEditorAction implement @Override public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) { + SelectionModel selectionModel = editor.getSelectionModel(); + Document document = editor.getDocument(); + + if (EditorUtil.isPasswordEditor(editor)) { + selectionModel.setSelection(0, document.getTextLength()); + return; + } + int lineNumber = editor.getCaretModel().getLogicalPosition().line; int caretOffset = editor.getCaretModel().getOffset(); - Document document = editor.getDocument(); if (lineNumber >= document.getLineCount()) { return; } @@ -72,10 +80,9 @@ public class SelectWordAtCaretAction extends TextComponentEditorAction implement if (ranges.isEmpty()) return; - SelectionModel selectionModel = editor.getSelectionModel(); final TextRange selectionRange = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); - TextRange minimumRange = new TextRange(0, editor.getDocument().getTextLength()); + TextRange minimumRange = new TextRange(0, document.getTextLength()); for (TextRange range : ranges) { if (range.contains(selectionRange) && !range.equals(selectionRange)) { if (minimumRange.contains(range)) { diff --git a/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java b/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java index 9f32bbc32655..33df34bfeb80 100644 --- a/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/search/PredefinedSearchScopeProviderImpl.java @@ -146,7 +146,7 @@ public class PredefinedSearchScopeProviderImpl extends PredefinedSearchScopeProv } if (usageView) { - if (prevSearchFiles) { + if (!prevSearchFiles) { addHierarchyScope(project, result); } UsageView selectedUsageView = UsageViewManager.getInstance(project).getSelectedUsageView(); diff --git a/platform/lang-impl/src/com/intellij/ui/LanguageTextField.java b/platform/lang-impl/src/com/intellij/ui/LanguageTextField.java index 9074e7478d36..d0b51e3f7814 100644 --- a/platform/lang-impl/src/com/intellij/ui/LanguageTextField.java +++ b/platform/lang-impl/src/com/intellij/ui/LanguageTextField.java @@ -83,8 +83,8 @@ public class LanguageTextField extends EditorTextField { } } - private static Document createDocument(String value, @Nullable Language language, Project project, - @NotNull SimpleDocumentCreator documentCreator) { + public static Document createDocument(String value, @Nullable Language language, Project project, + @NotNull SimpleDocumentCreator documentCreator) { if (language != null) { final PsiFileFactory factory = PsiFileFactory.getInstance(project); final FileType fileType = language.getAssociatedFileType(); diff --git a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java index d0cca1a34c09..bb8cd11cfe09 100644 --- a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java +++ b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java @@ -16,20 +16,15 @@ package com.intellij.ui; -import com.intellij.codeInsight.hint.HintManager; -import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.event.DocumentAdapter; -import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.ex.FocusChangeListener; import com.intellij.openapi.fileTypes.PlainTextLanguage; -import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.util.textCompletion.TextCompletionUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,42 +41,39 @@ import java.util.Collection; * @author Roman Chernyatchik */ public class TextFieldWithAutoCompletion extends LanguageTextField { - public static final TextFieldWithAutoCompletionListProvider EMPTY_COMPLETION = new StringsCompletionProvider(null, null); - private final boolean myShowAutocompletionIsAvailableHint; - private final TextFieldWithAutoCompletionListProvider myProvider; + @NotNull private final TextFieldWithAutoCompletionListProvider myProvider; + private final boolean myShowCompletionHint; - @SuppressWarnings("unchecked") - public TextFieldWithAutoCompletion() { - this(null, EMPTY_COMPLETION, false, null); - } - - - public TextFieldWithAutoCompletion(final Project project, - @NotNull final TextFieldWithAutoCompletionListProvider provider, - final boolean showAutocompletionIsAvailableHint, @Nullable final String text) { + public TextFieldWithAutoCompletion(@Nullable Project project, + @NotNull TextFieldWithAutoCompletionListProvider provider, + boolean showCompletionHint, + @Nullable String text) { super(project == null ? null : PlainTextLanguage.INSTANCE, project, text == null ? "" : text); - myShowAutocompletionIsAvailableHint = showAutocompletionIsAvailableHint; + myShowCompletionHint = showCompletionHint; myProvider = provider; - TextFieldWithAutoCompletionContributor.installCompletion(getDocument(), project, provider, true); + if (project != null) { + installCompletion(getDocument(), project, provider, true); + } } - public static TextFieldWithAutoCompletion create(final Project project, - @NotNull final Collection items, - final boolean showAutocompletionIsAvailableHint, - @Nullable final String text) { - return create(project, items, null, showAutocompletionIsAvailableHint, text); + @NotNull + public static TextFieldWithAutoCompletion create(@Nullable Project project, + @NotNull Collection items, + boolean showCompletionHint, + @Nullable String text) { + return create(project, items, null, showCompletionHint, text); } - public static TextFieldWithAutoCompletion create(final Project project, - @NotNull final Collection items, - @Nullable final Icon icon, - final boolean showAutocompletionIsAvailableHint, - @Nullable final String text) { - return new TextFieldWithAutoCompletion(project, new StringsCompletionProvider(items, icon), showAutocompletionIsAvailableHint, - text); + @NotNull + public static TextFieldWithAutoCompletion create(@Nullable Project project, + @NotNull Collection items, + @Nullable Icon icon, + boolean showCompletionHint, + @Nullable String text) { + return new TextFieldWithAutoCompletion(project, new StringsCompletionProvider(items, icon), showCompletionHint, text); } public void setVariants(@NotNull Collection variants) { @@ -89,85 +81,52 @@ public class TextFieldWithAutoCompletion extends LanguageTextField { } public void installProvider(@NotNull TextFieldWithAutoCompletionListProvider provider) { - TextFieldWithAutoCompletionContributor.installCompletion(getDocument(), getProject(), provider, true); + installCompletion(getDocument(), getProject(), provider, true); + } + + public static void installCompletion(@NotNull Document document, + @NotNull Project project, + @NotNull TextFieldWithAutoCompletionListProvider provider, + boolean autoPopup) { + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); + if (psiFile != null) { + TextCompletionUtil.installProvider(psiFile, provider, autoPopup); + } } @Override protected EditorEx createEditor() { - final EditorEx editor = super.createEditor(); + EditorEx editor = super.createEditor(); - if (!myShowAutocompletionIsAvailableHint) { - return editor; + if (myShowCompletionHint) { + TextCompletionUtil.installCompletionHint(editor); } - final String completionShortcutText = - KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CODE_COMPLETION)); - if (StringUtil.isEmpty(completionShortcutText)) { - return editor; - } - - final Ref toShowHintRef = new Ref(true); - editor.getDocument().addDocumentListener(new DocumentAdapter() { - @Override - public void documentChanged(DocumentEvent e) { - toShowHintRef.set(false); - } - }); - - editor.addFocusListener(new FocusChangeListener() { - @Override - public void focusGained(final Editor editor) { - if (toShowHintRef.get() && getText().length() == 0) { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - HintManager.getInstance().showInformationHint(editor, "Code completion available ( " + completionShortcutText + " )"); - } - }); - } - } - - @Override - public void focusLost(Editor editor) { - // Do nothing - } - }); return editor; } public static class StringsCompletionProvider extends TextFieldWithAutoCompletionListProvider implements DumbAware { @Nullable private final Icon myIcon; - public StringsCompletionProvider(@Nullable final Collection variants, - @Nullable final Icon icon) { + public StringsCompletionProvider(@Nullable Collection variants, @Nullable Icon icon) { super(variants); myIcon = icon; } @Override - public int compare(final String item1, final String item2) { + public int compare(String item1, String item2) { return StringUtil.compare(item1, item2, false); } @Override - protected Icon getIcon(@NotNull final String item) { + protected Icon getIcon(@NotNull String item) { return myIcon; } @NotNull @Override - protected String getLookupString(@NotNull final String item) { + protected String getLookupString(@NotNull String item) { return item; } - - @Override - protected String getTailText(@NotNull final String item) { - return null; - } - - @Override - protected String getTypeText(@NotNull final String item) { - return null; - } } } diff --git a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java deleted file mode 100644 index 9ef69189f3f9..000000000000 --- a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java +++ /dev/null @@ -1,154 +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.ui; - -import com.intellij.codeInsight.completion.*; -import com.intellij.codeInsight.lookup.AutoCompletionPolicy; -import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.concurrency.SensitiveProgressWrapper; -import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.progress.EmptyProgressIndicator; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.DumbService; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Key; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -/** - * @author Roman.Chernyatchik - */ -public class TextFieldWithAutoCompletionContributor extends CompletionContributor implements DumbAware { - private static final Logger LOG = Logger.getInstance("#com.intellij.ui.TextFieldWithAutoCompletionContributor"); - private static final Key KEY = Key.create("text field simple completion available"); - private static final Key AUTO_POPUP_KEY = Key.create("text Field simple completion auto-popup"); - - public static void installCompletion(Document document, - Project project, - @Nullable TextFieldWithAutoCompletionListProvider provider, - boolean autoPopup) { - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); - if (psiFile != null) { - //noinspection unchecked - psiFile.putUserData(KEY, provider == null ? TextFieldWithAutoCompletion.EMPTY_COMPLETION : provider); - psiFile.putUserData(AUTO_POPUP_KEY, autoPopup); - } - } - - - @Override - public void fillCompletionVariants(@NotNull final CompletionParameters parameters, @NotNull CompletionResultSet result) { - PsiFile file = parameters.getOriginalFile(); - final TextFieldWithAutoCompletionListProvider provider = file.getUserData(KEY); - - if (provider == null || (DumbService.isDumb(file.getProject()) && !DumbService.isDumbAware(provider))) { - return; - } - String adv = provider.getAdvertisement(); - if (adv == null) { - final String shortcut = getActionShortcut(IdeActions.ACTION_QUICK_JAVADOC); - if (shortcut != null) { - adv = provider.getQuickDocHotKeyAdvertisement(shortcut); - } - } - if (adv != null) { - result.addLookupAdvertisement(adv); - } - - final String prefix = provider.getPrefix(parameters); - if (prefix == null) { - return; - } - if (parameters.getInvocationCount() == 0 && !file.getUserData(AUTO_POPUP_KEY)) { // is autopopup - return; - } - final PrefixMatcher prefixMatcher = provider.createPrefixMatcher(prefix); - if (prefixMatcher != null) { - result = result.withPrefixMatcher(prefixMatcher); - } - - Collection items = provider.getItems(prefix, true, parameters); - addCompletionElements(result, provider, items, -10000); - - final ProgressManager progressManager = ProgressManager.getInstance(); - ProgressIndicator mainIndicator = progressManager.getProgressIndicator(); - final ProgressIndicator indicator = mainIndicator != null ? new SensitiveProgressWrapper(mainIndicator) : new EmptyProgressIndicator(); - Future> - future = - ApplicationManager.getApplication().executeOnPooledThread(new Callable>() { - @Override - public Collection call() { - return progressManager.runProcess(new Computable>() { - @Override - public Collection compute() { - return provider.getItems(prefix, false, parameters); - } - }, indicator); - } - }); - - while (true) { - try { - Collection tasks = future.get(100, TimeUnit.MILLISECONDS); - if (tasks != null) { - addCompletionElements(result, provider, tasks, 0); - return; - } - } - catch (ProcessCanceledException e) { - throw e; - } - catch (Exception ignore) { - - } - ProgressManager.checkCanceled(); - } - } - - private static void addCompletionElements(final CompletionResultSet result, - final TextFieldWithAutoCompletionListProvider listProvider, - final Collection items, - final int index) { - final AutoCompletionPolicy completionPolicy = ApplicationManager.getApplication().isUnitTestMode() - ? AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE - : AutoCompletionPolicy.NEVER_AUTOCOMPLETE; - int grouping = index; - for (final T item : items) { - if (item == null) { - LOG.error("Null item from " + listProvider); - continue; - } - - LookupElementBuilder builder = listProvider.createLookupBuilder(item); - - result.addElement(PrioritizedLookupElement.withGrouping(builder.withAutoCompletionPolicy(completionPolicy), grouping--)); - } - } -} diff --git a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionListProvider.java b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionListProvider.java index 8ef12dfb1878..860fc6ea8a69 100644 --- a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionListProvider.java +++ b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionListProvider.java @@ -15,46 +15,133 @@ */ package com.intellij.ui; -import com.intellij.codeInsight.completion.CompletionParameters; -import com.intellij.codeInsight.completion.InsertHandler; -import com.intellij.codeInsight.completion.PlainPrefixMatcher; -import com.intellij.codeInsight.completion.PrefixMatcher; -import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.lookup.AutoCompletionPolicy; +import com.intellij.codeInsight.lookup.CharFilter; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.concurrency.SensitiveProgressWrapper; +import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.openapi.progress.EmptyProgressIndicator; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.util.Computable; +import com.intellij.util.textCompletion.DefaultTextCompletionValueDescriptor; +import com.intellij.util.textCompletion.TextCompletionProvider; +import com.intellij.util.textCompletion.TextCompletionUtil; +import com.intellij.util.textCompletion.TextCompletionValueDescriptor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; /** * @author Roman.Chernyatchik */ -public abstract class TextFieldWithAutoCompletionListProvider implements Comparator { +public abstract class TextFieldWithAutoCompletionListProvider extends DefaultTextCompletionValueDescriptor implements + TextCompletionProvider { + private static final Logger LOG = Logger.getInstance(TextFieldWithAutoCompletionListProvider.class); @NotNull protected Collection myVariants; @Nullable private String myCompletionAdvertisement; - @Nullable - protected abstract Icon getIcon(@NotNull final T item); - - @NotNull - protected abstract String getLookupString(@NotNull final T item); - - @Nullable - protected abstract String getTailText(@NotNull final T item); - - @Nullable - protected abstract String getTypeText(@NotNull final T item); - - @Override - public abstract int compare(T item1, T item2); - protected TextFieldWithAutoCompletionListProvider(@Nullable final Collection variants) { setItems(variants); myCompletionAdvertisement = null; } + @Nullable + @Override + public String getPrefix(@NotNull String text, int offset) { + return getCompletionPrefix(text, offset); + } + + @NotNull + @Override + public CompletionResultSet applyPrefixMatcher(@NotNull CompletionResultSet result, @NotNull String prefix) { + PrefixMatcher prefixMatcher = createPrefixMatcher(prefix); + if (prefixMatcher != null) { + return result.withPrefixMatcher(prefixMatcher); + } + return result; + } + + @Nullable + @Override + public CharFilter.Result acceptChar(char c) { + return null; + } + + @Override + public void fillCompletionVariants(@NotNull CompletionParameters parameters, + @NotNull String prefix, + @NotNull CompletionResultSet result) { + Collection items = getItems(prefix, true, parameters); + addCompletionElements(result, this, items, -10000); + + final ProgressManager progressManager = ProgressManager.getInstance(); + ProgressIndicator mainIndicator = progressManager.getProgressIndicator(); + final ProgressIndicator indicator = mainIndicator != null ? new SensitiveProgressWrapper(mainIndicator) : new EmptyProgressIndicator(); + Future> + future = + ApplicationManager.getApplication().executeOnPooledThread(new Callable>() { + @Override + public Collection call() { + return progressManager.runProcess(new Computable>() { + @Override + public Collection compute() { + return getItems(prefix, false, parameters); + } + }, indicator); + } + }); + + while (true) { + try { + Collection tasks = future.get(100, TimeUnit.MILLISECONDS); + if (tasks != null) { + addCompletionElements(result, this, tasks, 0); + return; + } + } + catch (ProcessCanceledException e) { + throw e; + } + catch (Exception ignore) { + + } + ProgressManager.checkCanceled(); + } + } + + private static void addCompletionElements(final CompletionResultSet result, + final TextCompletionValueDescriptor descriptor, + final Collection items, + final int index) { + final AutoCompletionPolicy completionPolicy = ApplicationManager.getApplication().isUnitTestMode() + ? AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE + : AutoCompletionPolicy.NEVER_AUTOCOMPLETE; + int grouping = index; + for (final T item : items) { + if (item == null) { + LOG.error("Null item from " + descriptor); + continue; + } + + LookupElementBuilder builder = descriptor.createLookupBuilder(item); + result.addElement(PrioritizedLookupElement.withGrouping(builder.withAutoCompletionPolicy(completionPolicy), grouping--)); + } + } + public void setItems(@Nullable final Collection variants) { myVariants = (variants != null) ? variants : Collections.emptyList(); } @@ -71,21 +158,6 @@ public abstract class TextFieldWithAutoCompletionListProvider implements Comp return items; } - /** - * Completion list advertisement for documentation popup - * - * @param shortcut - * @return text - */ - @Nullable - public String getQuickDocHotKeyAdvertisement(@NotNull final String shortcut) { - final String advertisementTail = getQuickDocHotKeyAdvertisementTail(shortcut); - if (advertisementTail == null) { - return null; - } - return "Pressing " + shortcut + " would show " + advertisementTail; - } - /** * Completion list advertisement text, if null advertisement for documentation * popup will be shown @@ -94,10 +166,21 @@ public abstract class TextFieldWithAutoCompletionListProvider implements Comp */ @Nullable public String getAdvertisement() { - return myCompletionAdvertisement; + if (myCompletionAdvertisement != null) return myCompletionAdvertisement; + String shortcut = KeymapUtil.getFirstKeyboardShortcutText((IdeActions.ACTION_QUICK_JAVADOC)); + String advertisementTail = getQuickDocHotKeyAdvertisementTail(shortcut); + if (advertisementTail == null) { + return null; + } + return "Pressing " + shortcut + " would show " + advertisementTail; } - public void setAdvertisement(@Nullable final String completionAdvertisement) { + @Nullable + protected String getQuickDocHotKeyAdvertisementTail(@NotNull final String shortcut) { + return null; + } + + public void setAdvertisement(@Nullable String completionAdvertisement) { myCompletionAdvertisement = completionAdvertisement; } @@ -106,47 +189,17 @@ public abstract class TextFieldWithAutoCompletionListProvider implements Comp return new PlainPrefixMatcher(prefix); } - public LookupElementBuilder createLookupBuilder(@NotNull final T item) { - LookupElementBuilder builder = LookupElementBuilder.create(item, getLookupString(item)) - .withIcon(getIcon(item)); - - final InsertHandler handler = createInsertHandler(item); - if (handler != null) { - builder = builder.withInsertHandler(handler); - } - - final String tailText = getTailText(item); - if (tailText != null) { - builder = builder.withTailText(tailText, true); - } - - final String typeText = getTypeText(item); - if (typeText != null) { - builder = builder.withTypeText(typeText); - } - return builder; - } - - @Nullable - public String getPrefix(@NotNull final CompletionParameters parameters) { - return getCompletionPrefix(parameters); - } - + @NotNull public static String getCompletionPrefix(CompletionParameters parameters) { String text = parameters.getOriginalFile().getText(); int offset = parameters.getOffset(); + return getCompletionPrefix(text, offset); + } + + @NotNull + private static String getCompletionPrefix(String text, int offset) { int i = text.lastIndexOf(' ', offset - 1) + 1; int j = text.lastIndexOf('\n', offset - 1) + 1; return text.substring(Math.max(i, j), offset); } - - @Nullable - protected String getQuickDocHotKeyAdvertisementTail(@NotNull final String shortcut) { - return null; - } - - @Nullable - protected InsertHandler createInsertHandler(@NotNull final T item) { - return null; - } } diff --git a/platform/lang-impl/src/com/intellij/util/CompletionContributorForTextField.java b/platform/lang-impl/src/com/intellij/util/CompletionContributorForTextField.java deleted file mode 100644 index 427805facc71..000000000000 --- a/platform/lang-impl/src/com/intellij/util/CompletionContributorForTextField.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.intellij.util; - -import com.intellij.codeInsight.completion.CompletionContributor; -import com.intellij.codeInsight.completion.CompletionParameters; -import com.intellij.codeInsight.completion.CompletionResultSet; -import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.DumbService; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiPlainTextFile; -import org.jetbrains.annotations.NotNull; - -/** - * @author sergey.evdokimov - */ -public class CompletionContributorForTextField extends CompletionContributor implements DumbAware { - - @Override - public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) { - PsiFile file = parameters.getOriginalFile(); - if (!(file instanceof PsiPlainTextFile)) return; - - TextFieldCompletionProvider field = file.getUserData(TextFieldCompletionProvider.COMPLETING_TEXT_FIELD_KEY); - if (field == null) return; - - if (!(field instanceof DumbAware) && DumbService.isDumb(file.getProject())) return; - - String text = file.getText(); - int offset = Math.min(text.length(), parameters.getOffset()); - - String prefix = field.getPrefix(text.substring(0, offset)); - - CompletionResultSet activeResult; - - if (!result.getPrefixMatcher().getPrefix().equals(prefix)) { - activeResult = result.withPrefixMatcher(prefix); - } - else { - activeResult = result; - } - - if (field.isCaseInsensitivity()) { - activeResult = activeResult.caseInsensitive(); - } - - field.addCompletionVariants(text, offset, prefix, activeResult); - activeResult.stopHere(); - } -} diff --git a/platform/lang-impl/src/com/intellij/util/TextFieldCompletionProvider.java b/platform/lang-impl/src/com/intellij/util/TextFieldCompletionProvider.java index 09c1a7e83e06..3d9e4c92353e 100644 --- a/platform/lang-impl/src/com/intellij/util/TextFieldCompletionProvider.java +++ b/platform/lang-impl/src/com/intellij/util/TextFieldCompletionProvider.java @@ -1,27 +1,29 @@ package com.intellij.util; +import com.intellij.codeInsight.completion.CompletionParameters; import com.intellij.codeInsight.completion.CompletionResultSet; +import com.intellij.codeInsight.lookup.CharFilter; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.PlainTextLanguage; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Key; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; import com.intellij.ui.EditorTextField; +import com.intellij.ui.LanguageTextField; +import com.intellij.util.textCompletion.TextCompletionProvider; +import com.intellij.util.textCompletion.TextCompletionUtil; +import com.intellij.util.textCompletion.TextFieldWithCompletion; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * @author sergey.evdokimov */ -public abstract class TextFieldCompletionProvider { - - static final Key COMPLETING_TEXT_FIELD_KEY = Key.create("COMPLETING_TEXT_FIELD_KEY"); - +public abstract class TextFieldCompletionProvider implements TextCompletionProvider { protected boolean myCaseInsensitivity; protected TextFieldCompletionProvider() { @@ -32,30 +34,55 @@ public abstract class TextFieldCompletionProvider { myCaseInsensitivity = caseInsensitivity; } + @Nullable + @Override + public String getPrefix(@NotNull String text, int offset) { + return getPrefix(text.substring(0, offset)); + } + + @NotNull + @Override + public CompletionResultSet applyPrefixMatcher(@NotNull CompletionResultSet result, @NotNull String prefix) { + CompletionResultSet activeResult = result; + + if (!activeResult.getPrefixMatcher().getPrefix().equals(prefix)) { + activeResult = activeResult.withPrefixMatcher(prefix); + } + + if (isCaseInsensitivity()) { + activeResult = activeResult.caseInsensitive(); + } + + return activeResult; + } + + @Nullable + @Override + public CharFilter.Result acceptChar(char c) { + return null; + } + + @Override + public void fillCompletionVariants(@NotNull CompletionParameters parameters, + @NotNull String prefix, + @NotNull CompletionResultSet result) { + addCompletionVariants(parameters.getOriginalFile().getText(), parameters.getOffset(), prefix, result); + result.stopHere(); + } + public void apply(@NotNull EditorTextField field, @NotNull String text) { Project project = field.getProject(); if (project != null) { field.setDocument(createDocument(project, text)); } } - + public void apply(@NotNull EditorTextField field) { apply(field, ""); } - private Document createDocument(final Project project, @NotNull String text) { - final FileType fileType = PlainTextLanguage.INSTANCE.getAssociatedFileType(); - assert fileType != null; - - final long stamp = LocalTimeCounter.currentTime(); - final PsiFile psiFile = PsiFileFactory.getInstance(project) - .createFileFromText("Dummy." + fileType.getDefaultExtension(), fileType, text, stamp, true, false); - - psiFile.putUserData(COMPLETING_TEXT_FIELD_KEY, this); - - final Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile); - assert document != null; - return document; + private Document createDocument(Project project, @NotNull String text) { + return LanguageTextField.createDocument(text, PlainTextLanguage.INSTANCE, project, new TextCompletionUtil.DocumentWithCompletionCreator(this, true)); } public boolean isCaseInsensitivity() { @@ -67,23 +94,26 @@ public abstract class TextFieldCompletionProvider { return currentTextPrefix; } - protected abstract void addCompletionVariants(@NotNull String text, int offset, @NotNull String prefix, @NotNull CompletionResultSet result); + @Nullable + @Override + public String getAdvertisement() { + return null; + } + + protected abstract void addCompletionVariants(@NotNull String text, + int offset, + @NotNull String prefix, + @NotNull CompletionResultSet result); @NotNull public EditorTextField createEditor(Project project) { - return createEditor(project, true); + return createEditor(project, true, null); } - - @NotNull - public EditorTextField createEditor(Project project, final boolean shouldHaveBorder) { - return createEditor(project, shouldHaveBorder, null); - } - + @NotNull public EditorTextField createEditor(Project project, final boolean shouldHaveBorder, - @Nullable final Consumer editorConstructionCallback) - { + @Nullable final Consumer editorConstructionCallback) { return new EditorTextField(createDocument(project, ""), project, PlainTextLanguage.INSTANCE.getAssociatedFileType()) { @Override protected boolean shouldHaveBorder() { diff --git a/platform/lang-impl/src/com/intellij/util/textCompletion/DefaultTextCompletionValueDescriptor.java b/platform/lang-impl/src/com/intellij/util/textCompletion/DefaultTextCompletionValueDescriptor.java new file mode 100644 index 000000000000..2b11cea9c464 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/textCompletion/DefaultTextCompletionValueDescriptor.java @@ -0,0 +1,86 @@ +/* + * Copyright 2000-2016 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.util.textCompletion; + +import com.intellij.codeInsight.completion.InsertHandler; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public abstract class DefaultTextCompletionValueDescriptor implements TextCompletionValueDescriptor { + @NotNull + protected abstract String getLookupString(@NotNull T item); + + @Nullable + protected Icon getIcon(@NotNull T item) { + return null; + } + + @Nullable + protected String getTailText(@NotNull T item) { + return null; + } + + @Nullable + protected String getTypeText(@NotNull T item) { + return null; + } + + @Nullable + protected InsertHandler createInsertHandler(@NotNull final T item) { + return null; + } + + @Override + public int compare(T item1, T item2) { + return StringUtil.compare(getLookupString(item1), getLookupString(item2), false); + } + + @NotNull + @Override + public LookupElementBuilder createLookupBuilder(@NotNull T item) { + LookupElementBuilder builder = LookupElementBuilder.create(item, getLookupString(item)) + .withIcon(getIcon(item)); + + InsertHandler handler = createInsertHandler(item); + if (handler != null) { + builder = builder.withInsertHandler(handler); + } + + String tailText = getTailText(item); + if (tailText != null) { + builder = builder.withTailText(tailText, true); + } + + String typeText = getTypeText(item); + if (typeText != null) { + builder = builder.withTypeText(typeText); + } + return builder; + } + + public static class StringValueDescriptor extends DefaultTextCompletionValueDescriptor { + @NotNull + @Override + public String getLookupString(@NotNull String item) { + return item; + } + } +} diff --git a/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionCharFilter.java b/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionCharFilter.java new file mode 100644 index 000000000000..d55768ba9ac2 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionCharFilter.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2016 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.util.textCompletion; + +import com.intellij.codeInsight.lookup.CharFilter; +import com.intellij.codeInsight.lookup.Lookup; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class TextCompletionCharFilter extends CharFilter { + @Nullable + @Override + public Result acceptChar(char c, int prefixLength, @NotNull Lookup lookup) { + if (!lookup.isCompletion()) return null; + PsiFile file = lookup.getPsiFile(); + if (file == null) return null; + TextCompletionProvider provider = TextCompletionUtil.getProvider(file); + if (provider != null) return provider.acceptChar(c); + return null; + } +} diff --git a/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionContributor.java b/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionContributor.java new file mode 100644 index 000000000000..27818913d6be --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionContributor.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2016 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.util.textCompletion; + +import com.intellij.codeInsight.completion.CompletionContributor; +import com.intellij.codeInsight.completion.CompletionParameters; +import com.intellij.codeInsight.completion.CompletionResultSet; +import com.intellij.codeInsight.lookup.CharFilter; +import com.intellij.openapi.project.DumbAware; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +import static com.intellij.codeInsight.AutoPopupController.ALWAYS_AUTO_POPUP; + +/** + * @author sergey.evdokimov + */ +public class TextCompletionContributor extends CompletionContributor implements DumbAware { + + @Override + public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) { + PsiFile file = parameters.getOriginalFile(); + + TextCompletionProvider provider = TextCompletionUtil.getProvider(file); + if (provider == null) return; + + if (parameters.getInvocationCount() == 0 && + !Boolean.TRUE.equals(file.getUserData(TextCompletionUtil.AUTO_POPUP_KEY))) { + return; + } + + String advertisement = provider.getAdvertisement(); + if (advertisement != null) { + result.addLookupAdvertisement(advertisement); + } + + String text = file.getText(); + int offset = Math.min(text.length(), parameters.getOffset()); + String prefix = provider.getPrefix(text, offset); + if (prefix == null) return; + + CompletionResultSet activeResult = provider.applyPrefixMatcher(result, prefix); + + provider.fillCompletionVariants(parameters, prefix, activeResult); + } + + @Override + public boolean invokeAutoPopup(@NotNull PsiElement position, char typeChar) { + TextCompletionProvider provider = TextCompletionUtil.getProvider(position.getContainingFile()); + if (provider != null) { + if (Boolean.TRUE.equals(position.getContainingFile().getUserData(TextCompletionUtil.AUTO_POPUP_KEY))) { + return Objects.equals(CharFilter.Result.ADD_TO_PREFIX, provider.acceptChar(typeChar)); + } + } + return super.invokeAutoPopup(position, typeChar); + } +} diff --git a/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionProvider.java b/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionProvider.java new file mode 100644 index 000000000000..f87da73ca238 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionProvider.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2016 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.util.textCompletion; + +import com.intellij.codeInsight.completion.CompletionParameters; +import com.intellij.codeInsight.completion.CompletionResultSet; +import com.intellij.codeInsight.lookup.CharFilter; +import com.intellij.openapi.util.Key; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface TextCompletionProvider { + @Nullable + String getAdvertisement(); + + @Nullable + String getPrefix(@NotNull String text, int offset); + + @NotNull + CompletionResultSet applyPrefixMatcher(@NotNull CompletionResultSet result, @NotNull String prefix); + + @Nullable + CharFilter.Result acceptChar(char c); + + void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull String prefix, @NotNull CompletionResultSet result); +} diff --git a/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionUtil.java b/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionUtil.java new file mode 100644 index 000000000000..e6255e310f9e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionUtil.java @@ -0,0 +1,104 @@ +/* + * Copyright 2000-2016 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.util.textCompletion; + +import com.intellij.codeInsight.hint.HintManager; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.event.DocumentAdapter; +import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.ex.FocusChangeListener; +import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiFile; +import com.intellij.ui.LanguageTextField; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class TextCompletionUtil { + public static final Key COMPLETING_TEXT_FIELD_KEY = Key.create("COMPLETING_TEXT_FIELD_KEY"); + public static final Key AUTO_POPUP_KEY = Key.create("AUTOPOPUP_TEXT_FIELD_KEY"); + + public static void installProvider(@NotNull PsiFile psiFile, @NotNull TextCompletionProvider provider, boolean autoPopup) { + psiFile.putUserData(COMPLETING_TEXT_FIELD_KEY, provider); + psiFile.putUserData(AUTO_POPUP_KEY, autoPopup); + } + + @Nullable + public static TextCompletionProvider getProvider(@NotNull PsiFile file) { + TextCompletionProvider provider = file.getUserData(COMPLETING_TEXT_FIELD_KEY); + + if (provider == null || (DumbService.isDumb(file.getProject()) && !DumbService.isDumbAware(provider))) { + return null; + } + return provider; + } + + public static void installCompletionHint(@NotNull EditorEx editor) { + String completionShortcutText = + KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CODE_COMPLETION)); + if (!StringUtil.isEmpty(completionShortcutText)) { + + final Ref toShowHintRef = new Ref(true); + editor.getDocument().addDocumentListener(new DocumentAdapter() { + @Override + public void documentChanged(DocumentEvent e) { + toShowHintRef.set(false); + } + }); + + editor.addFocusListener(new FocusChangeListener() { + @Override + public void focusGained(final Editor editor) { + if (toShowHintRef.get() && editor.getDocument().getText().isEmpty()) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + HintManager.getInstance().showInformationHint(editor, "Code completion available ( " + completionShortcutText + " )"); + } + }); + } + } + + @Override + public void focusLost(Editor editor) { + // Do nothing + } + }); + } + } + + public static class DocumentWithCompletionCreator extends LanguageTextField.SimpleDocumentCreator { + @NotNull private final TextCompletionProvider myProvider; + private final boolean myAutoPopup; + + public DocumentWithCompletionCreator(@NotNull TextCompletionProvider provider, boolean autoPopup) { + myProvider = provider; + myAutoPopup = autoPopup; + } + + @Override + public void customizePsiFile(@NotNull PsiFile file) { + installProvider(file, myProvider, myAutoPopup); + } + } +} diff --git a/platform/util/src/com/intellij/openapi/util/text/LevenshteinDistance.java b/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionValueDescriptor.java similarity index 59% rename from platform/util/src/com/intellij/openapi/util/text/LevenshteinDistance.java rename to platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionValueDescriptor.java index b66d61ad0568..e3e0c27fb7fe 100644 --- a/platform/util/src/com/intellij/openapi/util/text/LevenshteinDistance.java +++ b/platform/lang-impl/src/com/intellij/util/textCompletion/TextCompletionValueDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.util.text; +package com.intellij.util.textCompletion; -import com.intellij.util.text.EditDistance; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import org.jetbrains.annotations.NotNull; -/** @deprecated use {@link EditDistance} (to be removed in IDEA 17) */ -@SuppressWarnings("unused") -public class LevenshteinDistance { - public int calculateMetrics(CharSequence str1, CharSequence str2) { - return EditDistance.levenshtein(str1, str2, true); - } +import java.util.Comparator; + +public interface TextCompletionValueDescriptor extends Comparator { + @NotNull + LookupElementBuilder createLookupBuilder(@NotNull T item); } diff --git a/platform/lang-impl/src/com/intellij/util/textCompletion/TextFieldWithCompletion.java b/platform/lang-impl/src/com/intellij/util/textCompletion/TextFieldWithCompletion.java new file mode 100644 index 000000000000..cb489f795213 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/textCompletion/TextFieldWithCompletion.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2016 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.util.textCompletion; + +import com.intellij.codeInsight.AutoPopupController; +import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.fileTypes.PlainTextLanguage; +import com.intellij.openapi.project.Project; +import com.intellij.ui.EditorCustomization; +import com.intellij.ui.LanguageTextField; +import org.jetbrains.annotations.NotNull; + +public class TextFieldWithCompletion extends LanguageTextField { + private final boolean myForceAutoPopup; + private final boolean myShowHint; + + public TextFieldWithCompletion(@NotNull Project project, + @NotNull TextCompletionProvider provider, + @NotNull String value, + boolean oneLineMode, + boolean forceAutoPopup, + boolean showHint) { + this(project, provider, value, oneLineMode, true, forceAutoPopup, showHint); + } + + public TextFieldWithCompletion(@NotNull Project project, + @NotNull TextCompletionProvider provider, + @NotNull String value, + boolean oneLineMode, + boolean autoPopup, + boolean forceAutoPopup, + boolean showHint) { + super(PlainTextLanguage.INSTANCE, project, value, new TextCompletionUtil.DocumentWithCompletionCreator(provider, autoPopup), oneLineMode); + myForceAutoPopup = forceAutoPopup; + myShowHint = showHint; + } + + @Override + protected EditorEx createEditor() { + EditorEx editor = super.createEditor(); + EditorCustomization disableSpellChecking = SpellCheckingEditorCustomizationProvider.getInstance().getDisabledCustomization(); + if (disableSpellChecking != null) disableSpellChecking.customize(editor); + editor.putUserData(AutoPopupController.ALWAYS_AUTO_POPUP, myForceAutoPopup); + + if (myShowHint) { + TextCompletionUtil.installCompletionHint(editor); + } + + return editor; + } +} diff --git a/platform/lang-impl/src/com/intellij/util/textCompletion/ValuesCompletionProvider.java b/platform/lang-impl/src/com/intellij/util/textCompletion/ValuesCompletionProvider.java new file mode 100644 index 000000000000..9f872c6d5daa --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/textCompletion/ValuesCompletionProvider.java @@ -0,0 +1,121 @@ +/* + * Copyright 2000-2016 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.util.textCompletion; + +import com.intellij.codeInsight.completion.CompletionParameters; +import com.intellij.codeInsight.completion.CompletionResultSet; +import com.intellij.codeInsight.completion.PlainPrefixMatcher; +import com.intellij.codeInsight.lookup.CharFilter; +import com.intellij.openapi.project.DumbAware; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class ValuesCompletionProvider implements TextCompletionProvider { + @NotNull protected final TextCompletionValueDescriptor myDescriptor; + @NotNull private final List mySeparators; + @NotNull protected final Collection myValues; + private final boolean myCaseSensitive; + + public ValuesCompletionProvider(@NotNull TextCompletionValueDescriptor descriptor, + @NotNull List separators, + @NotNull Collection values, boolean caseSensitive) { + myDescriptor = descriptor; + mySeparators = separators; + myValues = values; + myCaseSensitive = caseSensitive; + } + + /* + Single-line single-value case-insensitive completion. + */ + public ValuesCompletionProvider(@NotNull TextCompletionValueDescriptor presentation, + @NotNull Collection values) { + this(presentation, Collections.emptyList(), values, false); + } + + @Nullable + @Override + public String getAdvertisement() { + return ""; + } + + @Nullable + @Override + public String getPrefix(@NotNull String text, int offset) { + return getPrefix(text, offset, mySeparators); + } + + @NotNull + protected static String getPrefix(@NotNull String text, int offset, @NotNull Collection separators) { + int index = -1; + for (char c : separators) { + index = Math.max(text.lastIndexOf(c, offset - 1), index); + } + return text.substring(index + 1, offset); + } + + @NotNull + @Override + public CompletionResultSet applyPrefixMatcher(@NotNull CompletionResultSet result, @NotNull String prefix) { + CompletionResultSet resultWithMatcher = result.withPrefixMatcher(new PlainPrefixMatcher(prefix)); + if (!myCaseSensitive) resultWithMatcher = resultWithMatcher.caseInsensitive(); + return resultWithMatcher; + } + + @Override + @Nullable + public CharFilter.Result acceptChar(char c) { + if (!mySeparators.contains(c)) return CharFilter.Result.ADD_TO_PREFIX; + return CharFilter.Result.HIDE_LOOKUP; + } + + @Override + public void fillCompletionVariants(@NotNull CompletionParameters parameters, + @NotNull String prefix, + @NotNull CompletionResultSet result) { + Collection values = getValues(prefix, result); + values = ContainerUtil.sorted(values, myDescriptor); + + for (T completionVariant : values) { + result.addElement(myDescriptor.createLookupBuilder(completionVariant)); + } + result.stopHere(); + } + + @NotNull + protected Collection getValues(@NotNull String prefix, @NotNull CompletionResultSet result) { + return myValues; + } + + public static class ValuesCompletionProviderDumbAware extends ValuesCompletionProvider implements DumbAware { + public ValuesCompletionProviderDumbAware(@NotNull TextCompletionValueDescriptor descriptor, + @NotNull List separators, + @NotNull Collection values, + boolean caseSensitive) { + super(descriptor, separators, values, caseSensitive); + } + + public ValuesCompletionProviderDumbAware(@NotNull TextCompletionValueDescriptor presentation, + @NotNull Collection values) { + super(presentation, values); + } + } +} diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java index 6fe0f50465b1..af52ad97f4d9 100644 --- a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java +++ b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/DirectoryHistoryDialog.java @@ -27,7 +27,6 @@ import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Pair; import com.intellij.diff.DiffDialogHints; import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.actions.ShowDiffUIContext; import com.intellij.openapi.vcs.changes.actions.diff.ShowDiffAction; import com.intellij.openapi.vcs.changes.actions.diff.ShowDiffContext; import com.intellij.openapi.vcs.changes.ui.ChangeNodeDecorator; diff --git a/platform/platform-impl/src/com/intellij/application/options/OptionsConstants.java b/platform/platform-impl/src/com/intellij/application/options/OptionsConstants.java index b020da27f557..be5beec6eceb 100644 --- a/platform/platform-impl/src/com/intellij/application/options/OptionsConstants.java +++ b/platform/platform-impl/src/com/intellij/application/options/OptionsConstants.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2016 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,14 +18,21 @@ package com.intellij.application.options; /** * @author Denis Zhdanov * @since 4/25/11 4:23 PM + * @deprecated + * @use com.intellij.application.options.EditorFontsConstants */ public class OptionsConstants { - + @Deprecated public static final int MIN_EDITOR_FONT_SIZE = 4; + @Deprecated public static final int MAX_EDITOR_FONT_SIZE = 40; + @Deprecated public static final int DEFAULT_EDITOR_FONT_SIZE = 12; + @Deprecated public static final float MIN_EDITOR_LINE_SPACING = .6F; + @Deprecated public static final float MAX_EDITOR_LINE_SPACING = 3; + @Deprecated public static final float DEFAULT_EDITOR_LINE_SPACING = 1; private OptionsConstants() { diff --git a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java index 700432978815..cf1525fa90a1 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java +++ b/platform/platform-impl/src/com/intellij/execution/process/ProcessInfo.java @@ -94,7 +94,8 @@ public class ProcessInfo { @Override public String toString() { - return myPid + " '" + myCommandLine + "' '" + myExecutableName + "' '" + myArgs + "'"; + return myPid + " '" + myCommandLine + "' '" + myExecutableName + "' '" + myArgs + "'" + + (myExecutablePath.isPresent() ? " " + myExecutablePath.get() : ""); } @Override @@ -108,6 +109,7 @@ public class ProcessInfo { if (!myExecutableName.equals(info.myExecutableName)) return false; if (!myArgs.equals(info.myArgs)) return false; if (!myCommandLine.equals(info.myCommandLine)) return false; + if (!myExecutablePath.equals(info.myExecutablePath)) return false; return true; } diff --git a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java index fa42c2837020..fc52580be38e 100644 --- a/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java +++ b/platform/platform-impl/src/com/intellij/execution/process/impl/ProcessListUtil.java @@ -305,7 +305,7 @@ public class ProcessListUtil { String name = line.substring(0, commandLineStart).trim(); if (name.isEmpty()) continue; - String commandLine = line.substring(commandLineStart, pidStart).trim(); + String commandLine = line.substring(commandLineStart, executablePathStart).trim(); String args = ""; if (commandLine.isEmpty()) { diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java index 3ceb6f620964..cdf1d46b57d6 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java @@ -21,9 +21,7 @@ import com.intellij.ide.plugins.PluginManager; import com.intellij.ide.ui.UISettings; import com.intellij.idea.IdeaApplication; import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.application.*; import com.intellij.openapi.application.ex.ApplicationEx; import com.intellij.openapi.application.impl.LaterInvocator; import com.intellij.openapi.diagnostic.FrequentEventDetector; @@ -385,6 +383,7 @@ public class IdeEventQueue extends EventQueue { } AWTEvent oldEvent = myCurrentEvent; myCurrentEvent = e; + AccessToken token = ((TransactionGuardImpl)TransactionGuard.getInstance()).startActivity(myIsInInputEvent); try { _dispatchEvent(e, false); @@ -393,6 +392,7 @@ public class IdeEventQueue extends EventQueue { processException(t); } finally { + token.finish(); myIsInInputEvent = wasInputEvent; myCurrentEvent = oldEvent; diff --git a/platform/platform-impl/src/com/intellij/ide/ui/ColorBlindnessInternalAction.java b/platform/platform-impl/src/com/intellij/ide/ui/ColorBlindnessInternalAction.java new file mode 100644 index 000000000000..5163f40dadbd --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/ColorBlindnessInternalAction.java @@ -0,0 +1,147 @@ +/* + * Copyright 2000-2016 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.ide.ui; + +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.ui.ComboBox; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.util.ui.ImageUtil; +import com.intellij.util.ui.JBDimension; +import com.intellij.util.ui.JBInsets; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.image.BufferedImage; +import java.awt.image.ImageFilter; + +/** + * @author Sergey.Malenkov + */ +public class ColorBlindnessInternalAction extends DumbAwareAction { + @Override + public void actionPerformed(AnActionEvent event) { + new ColorDialog(event).show(); + } + + private static final class ColorDialog extends DialogWrapper { + private final ColorView myView = new ColorView(); + + private ColorDialog(AnActionEvent event) { + super(event.getProject()); + init(); + setTitle("ColorBlindness"); + } + + @Override + protected JComponent createCenterPanel() { + myView.setMinimumSize(new JBDimension(360, 200)); + myView.setPreferredSize(new JBDimension(720, 400)); + + JComboBox combo = new ComboBox<>(FilterItem.ALL); + combo.addItemListener(myView); + + JPanel panel = new JPanel(new BorderLayout(10, 10)); + panel.add(BorderLayout.CENTER, myView); + panel.add(BorderLayout.SOUTH, combo); + return panel; + } + + @NotNull + @Override + protected Action[] createActions() { + return new Action[]{getCancelAction()}; + } + } + + private static final class FilterItem { + private final ImageFilter myFilter; + + public FilterItem(ImageFilter filter) { + myFilter = filter; + } + + @Override + public String toString() { + return myFilter == null ? "No filtering" : myFilter.toString(); + } + + private static final FilterItem[] ALL = new FilterItem[]{ + new FilterItem(null), + new FilterItem(DaltonizationFilter.protanopia), + new FilterItem(DaltonizationFilter.forProtanopia(.5)), + new FilterItem(DaltonizationFilter.deuteranopia), + new FilterItem(DaltonizationFilter.forDeuteranopia(.5)), + new FilterItem(DaltonizationFilter.tritanopia), + new FilterItem(DaltonizationFilter.forTritanopia(.5)), + new FilterItem(SimulationFilter.protanopia), + new FilterItem(SimulationFilter.forProtanopia(.5)), + new FilterItem(SimulationFilter.deuteranopia), + new FilterItem(SimulationFilter.forDeuteranopia(.5)), + new FilterItem(SimulationFilter.tritanopia), + new FilterItem(SimulationFilter.forTritanopia(.5)), + new FilterItem(SimulationFilter.achromatopsia), + new FilterItem(SimulationFilter.forAchromatopsia(.5)), + }; + } + + private static final class ColorView extends JComponent implements ItemListener { + private ImageFilter myFilter; + private Image myImage; + + @Override + protected void paintComponent(Graphics g) { + Rectangle bounds = new Rectangle(getWidth(), getHeight()); + JBInsets.removeFrom(bounds, getInsets()); + if (bounds.isEmpty()) return; + + if (myImage == null || bounds.width != myImage.getWidth(this) || bounds.height != myImage.getHeight(this)) { + int[] array = new int[bounds.width * bounds.height]; + float width = (float)(bounds.width - 1); + float height = (float)(bounds.height - 1); + for (int i = 0, h = 0; h < bounds.height; h++) { + for (int w = 0; w < bounds.width; w++, i++) { + float level = 2 * h / height; + float saturation = (level > 1f) ? 1 : level; + float brightness = (level > 1f) ? 2 - level : 1; + array[i] = Color.HSBtoRGB(w / width, saturation, brightness); + } + } + BufferedImage image = UIUtil.createImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_RGB); + image.setRGB(0, 0, bounds.width, bounds.height, array, 0, bounds.width); + myImage = ImageUtil.filter(image, myFilter); + } + g.drawImage(myImage, bounds.x, bounds.y, bounds.width, bounds.height, this); + } + + @Override + public void itemStateChanged(ItemEvent event) { + if (ItemEvent.SELECTED == event.getStateChange()) { + Object object = event.getItem(); + if (object instanceof FilterItem) { + FilterItem item = (FilterItem)object; + myFilter = item.myFilter; + myImage = null; + repaint(); + } + } + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java index c6fe3dfc6c8e..375f764abfc1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java @@ -29,10 +29,7 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.actionSystem.ex.ActionUtil; import com.intellij.openapi.actionSystem.ex.AnActionListener; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationActivationListener; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.application.*; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.PluginId; @@ -1298,15 +1295,14 @@ public final class ActionManagerImpl extends ActionManagerEx implements Disposab private void tryToExecuteNow(final AnAction action, final InputEvent inputEvent, final Component contextComponent, final String place, final ActionCallback result) { final Presentation presentation = action.getTemplatePresentation().clone(); - IdeFocusManager.findInstanceByContext(getContextBy(contextComponent)).doWhenFocusSettlesDown(new Runnable() { - @Override - public void run() { + IdeFocusManager.findInstanceByContext(getContextBy(contextComponent)).doWhenFocusSettlesDown( + () -> TransactionGuard.getInstance().performUserActivity(() -> { final DataContext context = getContextBy(contextComponent); AnActionEvent event = new AnActionEvent( inputEvent, context, place != null ? place : ActionPlaces.UNKNOWN, - presentation, ActionManagerImpl.this, + presentation, this, inputEvent.getModifiersEx() ); @@ -1346,7 +1342,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Disposab result.setDone(); queueActionPerformedEvent(action, context, event); } - }); + )); } private class MyTimer extends Timer implements ActionListener { diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index beee7d02aef0..48e6b1d9e314 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -1229,9 +1229,9 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App private void startWrite(/*@NotNull*/ Class clazz) { assertIsDispatchThread(getStatus(), "Write access is allowed from event dispatch thread only"); HeavyProcessLatch.INSTANCE.stopThreadPrioritizing(); // let non-cancellable read actions complete faster, if present - if (Registry.is("ide.require.transaction.for.model.changes", false)) { - TransactionGuard.getInstance().assertInsideTransaction( - true, "Write access is allowed from model transactions only, see TransactionGuard documentation for details"); + if (!((TransactionGuardImpl)TransactionGuard.getInstance()).isWriteActionAllowed()) { + // please assign exceptions here to Peter + LOG.error("Write access is allowed from model transactions only, see TransactionGuard documentation for details"); } boolean writeActionPending = myWriteActionPending; if (gatherWriteActionStatistics && myWriteActionsStack.isEmpty() && !writeActionPending) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java index 88e5db1b7ab4..7cd8e62c5531 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java @@ -28,12 +28,11 @@ import com.intellij.injected.editor.EditorWindow; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.actionSystem.EditorAction; import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; import com.intellij.util.ui.MacUIUtil; import org.jetbrains.annotations.NotNull; -public class BackspaceAction extends EditorAction { +public class BackspaceAction extends TextComponentEditorAction { public BackspaceAction() { super(new Handler()); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ChangeEditorFontSizeAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ChangeEditorFontSizeAction.java index 9213f1a63a44..a76fa22c6cf7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ChangeEditorFontSizeAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ChangeEditorFontSizeAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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,7 +15,7 @@ */ package com.intellij.openapi.editor.actions; -import com.intellij.application.options.OptionsConstants; +import com.intellij.application.options.EditorFontsConstants; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; @@ -41,7 +41,7 @@ public abstract class ChangeEditorFontSizeAction extends AnAction implements Dum final EditorImpl editor = getEditor(e); if (editor != null) { final int size = editor.getFontSize() + myStep; - if (size >= 8 && size <= OptionsConstants.MAX_EDITOR_FONT_SIZE) { + if (size >= 8 && size <= EditorFontsConstants.getMaxEditorFontSize()) { editor.setFontSize(size); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextPrevWordHandler.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextPrevWordHandler.java index c4fb7417d770..84d669bd8303 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextPrevWordHandler.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextPrevWordHandler.java @@ -20,6 +20,7 @@ import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.VisualPosition; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; +import com.intellij.openapi.editor.ex.util.EditorUtil; import org.jetbrains.annotations.Nullable; class NextPrevWordHandler extends EditorActionHandler { @@ -37,21 +38,28 @@ class NextPrevWordHandler extends EditorActionHandler { @Override protected void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) { assert caret != null; - VisualPosition currentPosition = caret.getVisualPosition(); - if (caret.isAtBidiRunBoundary() && (myNext ^ currentPosition.leansRight)) { + if (EditorUtil.isPasswordEditor(editor)) { int selectionStartOffset = caret.getLeadSelectionOffset(); - VisualPosition selectionStartPosition = caret.getLeadSelectionPosition(); - caret.moveToVisualPosition(currentPosition.leanRight(!currentPosition.leansRight)); - if (myWithSelection) { - caret.setSelection(selectionStartPosition, selectionStartOffset, caret.getVisualPosition(), caret.getOffset()); - } + caret.moveToOffset(myNext ? editor.getDocument().getTextLength() : 0); + if (myWithSelection) caret.setSelection(selectionStartOffset, caret.getOffset()); } else { - if (myNext ^ caret.isAtRtlLocation()) { - EditorActionUtil.moveCaretToNextWord(editor, myWithSelection, myInDifferentHumpsMode ^ editor.getSettings().isCamelWords()); + VisualPosition currentPosition = caret.getVisualPosition(); + if (caret.isAtBidiRunBoundary() && (myNext ^ currentPosition.leansRight)) { + int selectionStartOffset = caret.getLeadSelectionOffset(); + VisualPosition selectionStartPosition = caret.getLeadSelectionPosition(); + caret.moveToVisualPosition(currentPosition.leanRight(!currentPosition.leansRight)); + if (myWithSelection) { + caret.setSelection(selectionStartPosition, selectionStartOffset, caret.getVisualPosition(), caret.getOffset()); + } } else { - EditorActionUtil.moveCaretToPreviousWord(editor, myWithSelection, myInDifferentHumpsMode ^ editor.getSettings().isCamelWords()); + if (myNext ^ caret.isAtRtlLocation()) { + EditorActionUtil.moveCaretToNextWord(editor, myWithSelection, myInDifferentHumpsMode ^ editor.getSettings().isCamelWords()); + } + else { + EditorActionUtil.moveCaretToPreviousWord(editor, myWithSelection, myInDifferentHumpsMode ^ editor.getSettings().isCamelWords()); + } } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java index 7ca257da3030..4fc821552145 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java @@ -65,6 +65,10 @@ public final class EditorUtil { return editor != null && TextEditorProvider.getInstance().getTextEditor(editor) instanceof TextEditorImpl; } + public static boolean isPasswordEditor(@Nullable Editor editor) { + return editor != null && editor.getContentComponent() instanceof JPasswordField; + } + public static int getLastVisualLineColumnNumber(@NotNull Editor editor, final int line) { if (editor instanceof EditorImpl && ((EditorImpl)editor).myUseNewRendering) { LogicalPosition lineEndPosition = editor.visualToLogicalPosition(new VisualPosition(line, Integer.MAX_VALUE)); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index f9698c4342d1..a8652b4ea975 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -15,7 +15,7 @@ */ package com.intellij.openapi.editor.impl; -import com.intellij.application.options.OptionsConstants; +import com.intellij.application.options.EditorFontsConstants; import com.intellij.codeInsight.hint.DocumentFragmentTooltipRenderer; import com.intellij.codeInsight.hint.EditorFragmentComponent; import com.intellij.codeInsight.hint.TooltipController; @@ -30,7 +30,8 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionManagerEx; import com.intellij.openapi.actionSystem.impl.MouseGestureManager; -import com.intellij.openapi.application.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.UndoConfirmationPolicy; import com.intellij.openapi.diagnostic.Logger; @@ -6338,7 +6339,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi private final Map myOwnColors = ContainerUtilRt.newHashMap(); private final EditorColorsScheme myCustomGlobalScheme; private Map myFontsMap; - private int myMaxFontSize = OptionsConstants.MAX_EDITOR_FONT_SIZE; + private int myMaxFontSize = EditorFontsConstants.getMaxEditorFontSize(); private int myFontSize = -1; private int myConsoleFontSize = -1; private String myFaceName; @@ -6510,7 +6511,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi public void setDelegate(@NotNull EditorColorsScheme delegate) { super.setDelegate(delegate); int globalFontSize = getDelegate().getEditorFontSize(); - myMaxFontSize = Math.max(OptionsConstants.MAX_EDITOR_FONT_SIZE, globalFontSize); + myMaxFontSize = Math.max(EditorFontsConstants.getMaxEditorFontSize(), globalFontSize); reinitFonts(); clearSettingsCache(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java index e0de68cfdb2c..e487c7c303c1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java @@ -148,9 +148,13 @@ public class ScrollingModelImpl implements ScrollingModelEx { } private void scrollTo(@NotNull VisualPosition pos, @NotNull ScrollType scrollType) { + Point targetLocation = myEditor.visualPositionToXY(pos); + scrollTo(targetLocation, scrollType); + } + + private void scrollTo(@NotNull Point targetLocation, @NotNull ScrollType scrollType) { AnimatedScrollingRunnable canceledThread = cancelAnimatedScrolling(false); Rectangle viewRect = canceledThread != null ? canceledThread.getTargetVisibleArea() : getVisibleArea(); - Point targetLocation = myEditor.visualPositionToXY(pos); Point p = calcOffsetsToScroll(targetLocation, scrollType, viewRect); scrollToOffsets(p.x, p.y); } @@ -159,11 +163,8 @@ public class ScrollingModelImpl implements ScrollingModelEx { public void scrollTo(@NotNull LogicalPosition pos, @NotNull ScrollType scrollType) { assertIsDispatchThread(); - AnimatedScrollingRunnable canceledThread = cancelAnimatedScrolling(false); - Rectangle viewRect = canceledThread != null ? canceledThread.getTargetVisibleArea() : getVisibleArea(); Point targetLocation = myEditor.logicalPositionToXY(pos); - Point p = calcOffsetsToScroll(targetLocation, scrollType, viewRect); - scrollToOffsets(p.x, p.y); + scrollTo(targetLocation, scrollType); } private static void assertIsDispatchThread() { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/actions/RefreshFileChooserAction.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/actions/RefreshFileChooserAction.java index d57c2f55a579..1117602ec1e9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/actions/RefreshFileChooserAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/actions/RefreshFileChooserAction.java @@ -15,18 +15,21 @@ */ package com.intellij.openapi.fileChooser.actions; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.fileChooser.FileSystemTree; import com.intellij.openapi.vfs.newvfs.ManagingFS; import com.intellij.openapi.vfs.newvfs.RefreshQueue; /** * @author yole -*/ -public class RefreshFileChooserAction extends AnAction implements DumbAware { - public void actionPerformed(final AnActionEvent e) { + */ +public class RefreshFileChooserAction extends FileChooserAction { + protected void update(FileSystemTree fileChooser, AnActionEvent e) { + } + + @Override + protected void actionPerformed(FileSystemTree fileChooser, AnActionEvent e) { RefreshQueue.getInstance().refresh(true, true, null, ModalityState.current(), ManagingFS.getInstance().getLocalRoots()); } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java index 1cfb301ef9d7..992c83d5a577 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/IdeKeyEventDispatcher.java @@ -868,17 +868,15 @@ public final class IdeKeyEventDispatcher implements Disposable { } private static void invokeAction(@NotNull final AnAction action, final DataContext ctx) { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { + ApplicationManager.getApplication().invokeLater( + () -> TransactionGuard.getInstance().performUserActivity(() -> { final AnActionEvent event = new AnActionEvent(null, ctx, ActionPlaces.UNKNOWN, action.getTemplatePresentation().clone(), ActionManager.getInstance(), 0); if (ActionUtil.lastUpdateAndCheckDumb(action, event, true)) { ActionUtil.performActionDumbAware(action, event); } - } - }); + })); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java index 0f40317966d1..fe27df9d859c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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,6 +24,7 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.ui.ColorUtil; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.LicensingFacade; +import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,6 +33,7 @@ import javax.swing.*; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import java.awt.*; +import java.util.Date; /** * @author anna @@ -40,8 +42,6 @@ public abstract class AbstractUpdateDialog extends DialogWrapper { private final boolean myEnableLink; protected String myLicenseInfo = null; - protected boolean myPaidUpgrade; - protected boolean mySubscriptionLicense = false; protected AbstractUpdateDialog(boolean enableLink) { super(true); @@ -71,56 +71,44 @@ public abstract class AbstractUpdateDialog extends DialogWrapper { } protected void restart() { - final ApplicationEx app = ApplicationManagerEx.getApplicationEx(); // do not stack several modal dialogs (native & swing) - app.invokeLater(new Runnable() { - @Override - public void run() { - app.restart(true); - } - }); + ApplicationEx app = ApplicationManagerEx.getApplicationEx(); + app.invokeLater(() -> app.restart(true)); } - protected void initLicensingInfo(@NotNull UpdateChannel channel, @NotNull BuildInfo build) { + protected void initLicensingInfo(@NotNull UpdateChannel channel, @SuppressWarnings("UnusedParameters") @NotNull BuildInfo build) { LicensingFacade facade = LicensingFacade.getInstance(); if (facade != null) { - mySubscriptionLicense = facade.isSubscriptionLicense(); - if (!channel.getLicensing().equals(UpdateChannel.LICENSING_EAP)) { - int majorVersion = build.getMajorVersion(); - if (majorVersion < 0) { - majorVersion = channel.getMajorVersion(); // fallback - } - final Boolean paidUpgrade = facade.isPaidUpgrade(majorVersion, build.getReleaseDate()); - if (paidUpgrade == Boolean.TRUE) { - myPaidUpgrade = true; - myLicenseInfo = IdeBundle.message("updates.channel.key.needed", channel.getEvalDays()); - } - else if (paidUpgrade == Boolean.FALSE) { - myLicenseInfo = IdeBundle.message("updates.channel.existing.key"); - } + if (channel.getLicensing().equals(UpdateChannel.LICENSING_EAP)) { + myLicenseInfo = IdeBundle.message("updates.channel.bundled.key"); } else { - myLicenseInfo = IdeBundle.message("updates.channel.bundled.key"); + Date buildDate = build.getReleaseDate(); + Date expiration = facade.getLicenseExpirationDate(); + if (buildDate != null && facade.isPerpetualForProduct(buildDate)) { + myLicenseInfo = IdeBundle.message("updates.fallback.build"); + } + else if (expiration != null && expiration.after(new Date())) { + myLicenseInfo = IdeBundle.message("updates.subscription.active.till", DateFormatUtil.formatAboutDialogDate(expiration)); + } } } } - protected void configureMessageArea(@NotNull JEditorPane area) { String messageBody = myEnableLink ? IdeBundle.message("updates.configure.label", ShowSettingsUtil.getSettingsMenuName()) : ""; configureMessageArea(area, messageBody, null, null); } - protected void configureMessageArea(final @NotNull JEditorPane area, + protected void configureMessageArea(@NotNull JEditorPane area, @NotNull String messageBody, @Nullable Color fontColor, @Nullable HyperlinkListener listener) { - String text = "" + - UIUtil.getCssFontDeclaration(UIUtil.getLabelFont(), fontColor, null, null) + - "" + - "" + - messageBody + - ""; + String text = + "" + + UIUtil.getCssFontDeclaration(UIUtil.getLabelFont(), fontColor, null, null) + + "" + + "" + messageBody + ""; area.setBackground(UIUtil.getPanelBackground()); area.setBorder(IdeBorderFactory.createEmptyBorder()); @@ -128,13 +116,9 @@ public abstract class AbstractUpdateDialog extends DialogWrapper { area.setEditable(false); if (listener == null && myEnableLink) { - listener = new HyperlinkListener() { - @Override - public void hyperlinkUpdate(final HyperlinkEvent e) { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - UpdateSettingsConfigurable settings = new UpdateSettingsConfigurable(false); - ShowSettingsUtil.getInstance().editConfigurable(area, settings); - } + listener = (e) -> { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + ShowSettingsUtil.getInstance().editConfigurable(area, new UpdateSettingsConfigurable(false)); } }; } @@ -142,4 +126,4 @@ public abstract class AbstractUpdateDialog extends DialogWrapper { area.addHyperlinkListener(listener); } } -} +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java index ff093e28e489..d97a02f78c88 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 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,13 +18,11 @@ package com.intellij.openapi.updateSettings.impl; import com.intellij.ide.BrowserUtil; import com.intellij.ide.IdeBundle; import com.intellij.ui.BrowserHyperlinkListener; -import com.intellij.ui.LicensingFacade; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.event.ActionEvent; -import java.util.List; +import java.util.Objects; /** * @author yole @@ -52,31 +50,19 @@ class NewChannelDialog extends AbstractUpdateDialog { @NotNull @Override protected Action[] createActions() { - List actions = ContainerUtil.newArrayList(getOKAction()); + return new Action[]{ + getOKAction(), - if (myPaidUpgrade) { - actions.add(new AbstractAction(IdeBundle.message("updates.buy.online.button")) { + new AbstractAction(IdeBundle.message("updates.remind.later.button")) { @Override public void actionPerformed(ActionEvent e) { - LicensingFacade facade = LicensingFacade.getInstance(); - assert facade != null; - BrowserUtil.browse(facade.getUpgradeUrl()); + UpdateSettings.getInstance().forgetChannelId(myChannel.getId()); doCancelAction(); } - }); - } + }, - actions.add(new AbstractAction(IdeBundle.message("updates.remind.later.button")) { - @Override - public void actionPerformed(ActionEvent e) { - UpdateSettings.getInstance().forgetChannelId(myChannel.getId()); - doCancelAction(); - } - }); - - actions.add(getCancelAction()); - - return actions.toArray(new Action[actions.size()]); + getCancelAction() + }; } @Override @@ -91,7 +77,7 @@ class NewChannelDialog extends AbstractUpdateDialog { @Override protected void doOKAction() { - BrowserUtil.browse(myChannel.getHomePageUrl()); + BrowserUtil.browse(Objects.requireNonNull(myChannel.getHomePageUrl(), "missing URL for channel " + myChannel.getId())); super.doOKAction(); } @@ -112,4 +98,4 @@ class NewChannelDialog extends AbstractUpdateDialog { } } } -} +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java index 6c7a1ced59fe..9fd19b71de69 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -236,7 +236,7 @@ class UpdateInfoDialog extends AbstractUpdateDialog { } if (myLicenseInfo != null) { - configureMessageArea(myLicenseArea, myLicenseInfo, myPaidUpgrade ? JBColor.RED : null, null); + configureMessageArea(myLicenseArea, myLicenseInfo, null, null); } } } diff --git a/platform/platform-impl/src/com/intellij/ui/LicensingFacade.java b/platform/platform-impl/src/com/intellij/ui/LicensingFacade.java index 9df936acdfbf..4cc49749ac9b 100644 --- a/platform/platform-impl/src/com/intellij/ui/LicensingFacade.java +++ b/platform/platform-impl/src/com/intellij/ui/LicensingFacade.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2016 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,6 +15,7 @@ */ package com.intellij.ui; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Date; @@ -32,11 +33,13 @@ public abstract class LicensingFacade { } public abstract String getLicensedToMessage(); + public abstract List getLicenseRestrictionsMessages(); + public abstract boolean isEvaluationLicense(); - public abstract boolean isSubscriptionLicense(); + + public abstract boolean isPerpetualForProduct(@NotNull Date productBuildDate); @Nullable - public abstract Boolean isPaidUpgrade(int majorVersion, Date releaseDate); - public abstract String getUpgradeUrl(); -} + public abstract Date getLicenseExpirationDate(); +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java index 76959083f905..312a605add38 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java @@ -28,6 +28,7 @@ import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.application.TransactionGuard; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; @@ -1392,7 +1393,7 @@ public class AbstractPopup implements JBPopup { //noinspection SSBasedInspection SwingUtilities.invokeLater(() -> { if (ModalityState.current().equals(modalityState)) { - finalRunnable.run(); + TransactionGuard.getInstance().performUserActivity(finalRunnable::run); } // Otherwise the UI has changed unexpectedly and the action is likely not applicable. // And we don't want finalRunnable to perform potentially destructive actions diff --git a/platform/platform-resources-en/src/messages/DiffBundle.properties b/platform/platform-resources-en/src/messages/DiffBundle.properties index 21c7b42012cd..6a872087a243 100644 --- a/platform/platform-resources-en/src/messages/DiffBundle.properties +++ b/platform/platform-resources-en/src/messages/DiffBundle.properties @@ -57,6 +57,8 @@ select.external.diff.program.dialog.title=Select External Diff Program select.external.merge.program.dialog.title=Select External Merge Program diff.contents.are.identical.message.text=Contents are identical diff.contents.have.differences.only.in.line.separators.message.text=Contents have differences only in line separators +diff.contents.have.differences.only.in.charset.message.text=Contents have differences only in encoding +diff.contents.have.differences.only.in.charset.and.line.separators.message.text=Contents have differences only in line separators and encoding diff.contents.have.differences.only.in.line.separators.or.whitespaces=Contents have differences only in line separators or whitespaces show.diff.anyway.dialog.message=Show diff anyway? no.differences.dialog.title=No Differences diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index f153c9455837..e9e4f52f914d 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -907,9 +907,9 @@ updates.error.plugin.description.failed=Failed to load plugin descriptions from: update.notifications.title=Platform and Plugin Updates update.notifications.group=Platform and Plugin Updates updates.channel.name.message={0}: {1} -updates.channel.key.needed=You can evaluate the new version for {0} days or buy a license key or an upgrade online. -updates.channel.existing.key=The new version can be used with your existing license key. updates.channel.bundled.key=The new version has an expiration date and does not require a license key. +updates.fallback.build=You have perpetual fallback license for the new version. +updates.subscription.active.till=Your subscription is active until {0}. updates.ready.message={0} is ready to update. updates.plugins.ready.message=The following plugin{0,choice,1# is|2#s are} ready to update: {1} updates.no.updates.message=You already have the latest version of {0} installed. @@ -923,7 +923,6 @@ updates.more.info.button=&More Info... updates.download.page.button=Open &Download Page updates.ignore.update.button=&Ignore This Update updates.remind.later.button=&Remind Me Later -updates.buy.online.button=&Buy Upgrade Online updates.new.version.available=A new version of {0} is available! updates.current.version=Current version: updates.available.version=New version: diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index ca09d5f97caf..02489b6d7dd9 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -877,11 +877,9 @@ - - - + diff --git a/platform/platform-resources/src/idea/Keymap_Default.xml b/platform/platform-resources/src/idea/Keymap_Default.xml index 66d81bbbd679..be6172a40e67 100644 --- a/platform/platform-resources/src/idea/Keymap_Default.xml +++ b/platform/platform-resources/src/idea/Keymap_Default.xml @@ -692,9 +692,6 @@ - - - diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 1b76370488e4..f7dc145b8ea3 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -725,7 +725,7 @@ - + + diff --git a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java index dc63a5c33291..4a5bcd83f444 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/process/impl/ProcessListTest.java @@ -45,9 +45,9 @@ public class ProcessListTest extends UsefulTestCase { " 3 S user ./dir/dir/file param param" ); assertOrderedEquals(infos, - new ProcessInfo(1, "/dir/file", "file", ""), - new ProcessInfo(2, "./dir/dir/file", "file", ""), - new ProcessInfo(3, "./dir/dir/file param param", "file", "param param")); + new ProcessInfo(1, "/dir/file", "file", "", "/dir/file"), + new ProcessInfo(2, "./dir/dir/file", "file", "", "./dir/dir/file"), + new ProcessInfo(3, "./dir/dir/file param param", "file", "param param", "./dir/dir/file")); } public void testMac_DoNotIncludeProcessedMissingOnTheSecondPSRun() throws Exception { @@ -59,7 +59,7 @@ public class ProcessListTest extends UsefulTestCase { " 1 S user /dir/file\n" + " 5 S user /dir/file\n" ); - assertOrderedEquals(infos, new ProcessInfo(1, "/dir/file", "file", "")); + assertOrderedEquals(infos, new ProcessInfo(1, "/dir/file", "file", "", "/dir/file")); } public void testMac_DoNotIncludeProcessedChangedOnTheSecondPSRun() throws Exception { @@ -75,7 +75,7 @@ public class ProcessListTest extends UsefulTestCase { " 3 S user /dir/file1\n" + " 4 S user /dir/file/1\n" ); - assertOrderedEquals(infos, new ProcessInfo(1, "/dir/file param", "file", "param")); + assertOrderedEquals(infos, new ProcessInfo(1, "/dir/file param", "file", "param", "/dir/file")); } public void testMac_DoNotIncludeZombies() throws Exception { @@ -89,7 +89,7 @@ public class ProcessListTest extends UsefulTestCase { " 2 Z user /dir/file\n" + " 3 SZ user /dir/file\n" ); - assertOrderedEquals(infos, new ProcessInfo(1, "/dir/file", "file", "")); + assertOrderedEquals(infos, new ProcessInfo(1, "/dir/file", "file", "", "/dir/file")); } public void testMac_VariousFormsPidStatUser() throws Exception { @@ -102,8 +102,8 @@ public class ProcessListTest extends UsefulTestCase { " 101 Ss user_name /dir/file\n" ); assertOrderedEquals(infos, - new ProcessInfo(1, "/dir/file", "file", ""), - new ProcessInfo(101, "/dir/file", "file", "")); + new ProcessInfo(1, "/dir/file", "file", "", "/dir/file"), + new ProcessInfo(101, "/dir/file", "file", "", "/dir/file")); } public void testMac_WrongFormat() throws Exception { @@ -146,28 +146,28 @@ public class ProcessListTest extends UsefulTestCase { public void testWindows_WMIC() throws Exception { List infos = ProcessListUtil.parseWMICOutput( - "Caption CommandLine ProcessId \n" + - "smss.exe 304 \n" + - "sihost.exe sihost.exe 3052 \n" + - "taskhostw.exe taskhostw.exe {222A245B-E637-4AE9-A93F-A59CA119A75E} 3068 \n" + - "explorer.exe C:\\WINDOWS\\Explorer.EXE 3164 \n" + - "TPAutoConnect.exe TPAutoConnect.exe -q -i vmware -a COM1 -F 30 3336 \n" + - "conhost.exe \\??\\C:\\WINDOWS\\system32\\conhost.exe 0x4 3348 \n"); + "Caption CommandLine ExecutablePath ProcessId \n" + + "smss.exe 304 \n" + + "sihost.exe sihost.exe 3052 \n" + + "taskhostw.exe taskhostw.exe {222A245B-E637-4AE9-A93F-A59CA119A75E} 3068 \n" + + "explorer.exe C:\\WINDOWS\\Explorer.EXE C:\\WINDOWS\\Explorer.EXE 3164 \n" + + "TPAutoConnect.exe TPAutoConnect.exe -q -i vmware -a COM1 -F 30 3336 \n" + + "conhost.exe \\??\\C:\\WINDOWS\\system32\\conhost.exe 0x4 \\??\\C:\\WINDOWS\\system32\\conhost.exe 3348 \n"); assertOrderedEquals(infos, new ProcessInfo(304, "smss.exe", "smss.exe", ""), new ProcessInfo(3052, "sihost.exe", "sihost.exe", ""), new ProcessInfo(3068, "taskhostw.exe {222A245B-E637-4AE9-A93F-A59CA119A75E}", "taskhostw.exe", "{222A245B-E637-4AE9-A93F-A59CA119A75E}"), - new ProcessInfo(3164, "C:\\WINDOWS\\Explorer.EXE", "explorer.exe", ""), + new ProcessInfo(3164, "C:\\WINDOWS\\Explorer.EXE", "explorer.exe", "", "C:\\WINDOWS\\Explorer.EXE"), new ProcessInfo(3336, "TPAutoConnect.exe -q -i vmware -a COM1 -F 30", "TPAutoConnect.exe", "-q -i vmware -a COM1 -F 30"), - new ProcessInfo(3348, "\\??\\C:\\WINDOWS\\system32\\conhost.exe 0x4", "conhost.exe", "0x4")); + new ProcessInfo(3348, "\\??\\C:\\WINDOWS\\system32\\conhost.exe 0x4", "conhost.exe", "0x4", "\\??\\C:\\WINDOWS\\system32\\conhost.exe")); } public void testOnWindows_WMIC_DoNotIncludeSystemIdleProcess() throws Exception { List infos = ProcessListUtil.parseWMICOutput( - "Caption CommandLine ProcessId \n" + - "System Idle Process 0 \n" + - "System 4 \n" + - "smss.exe 304 \n"); + "Caption CommandLine ExecutablePath ProcessId \n" + + "System Idle Process 0 \n" + + "System 4 \n" + + "smss.exe 304 \n"); assertOrderedEquals(infos, new ProcessInfo(4, "System", "System", ""), new ProcessInfo(304, "smss.exe", "smss.exe", "")); @@ -179,19 +179,19 @@ public class ProcessListTest extends UsefulTestCase { assertNull(ProcessListUtil.parseWMICOutput( "wrong format")); assertEmpty(ProcessListUtil.parseWMICOutput( - "Caption CommandLine ProcessId \n")); + "Caption CommandLine ExecutablePath ProcessId \n")); assertNull(ProcessListUtil.parseWMICOutput( "smss.exe 304 \n")); assertNull(ProcessListUtil.parseWMICOutput( - "Caption XXX ProcessId \n" + - "smss.exe 304 \n")); + "Caption XXX ExecutablePath ProcessId \n" + + "smss.exe 304 \n")); assertNull(ProcessListUtil.parseWMICOutput( - "Caption CommandLine XXX \n" + - "smss.exe 304 \n")); + "Caption CommandLine ExecutablePath XXX \n" + + "smss.exe 304 \n")); assertEmpty(ProcessListUtil.parseWMICOutput( - "Caption CommandLine ProcessId \n" + - " \n")); + "Caption CommandLine ExecutablePath ProcessId \n" + + " \n")); } public void testWindows_TaskList() throws Exception { diff --git a/platform/testRunner/src/com/intellij/execution/testframework/autotest/AutoTestManager.java b/platform/testRunner/src/com/intellij/execution/testframework/autotest/AutoTestManager.java index 7a9b06229082..f817967cf63f 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/autotest/AutoTestManager.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/autotest/AutoTestManager.java @@ -15,8 +15,10 @@ */ package com.intellij.execution.testframework.autotest; -import com.intellij.execution.DelayedDocumentWatcher; -import com.intellij.execution.ExecutionManager; +import com.intellij.execution.*; +import com.intellij.execution.configurations.RunConfiguration; +import com.intellij.execution.configurations.RunProfile; +import com.intellij.execution.impl.RunManagerImpl; import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.process.ProcessHandler; @@ -31,7 +33,7 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.components.*; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; @@ -39,24 +41,35 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.content.Content; import com.intellij.util.Consumer; +import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.xmlb.annotations.AbstractCollection; +import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.Tag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.util.List; +import java.util.Set; /** * @author yole */ -public class AutoTestManager { +@State( + name = "AutoTestManager", + storages = {@Storage(StoragePathMacros.WORKSPACE_FILE)} +) +public class AutoTestManager implements PersistentStateComponent { private static final String AUTO_TEST_MANAGER_DELAY = "auto.test.manager.delay"; private static final int AUTO_TEST_MANAGER_DELAY_DEFAULT = 3000; private static final Key ON_TERMINATION_RESTARTER_KEY = Key.create("auto.test.manager.on.termination.restarter"); - private static final Key EXECUTION_ENVIRONMENT_KEY = Key.create("auto.test.manager.execution.environment"); private final Project myProject; private int myDelayMillis; private DelayedDocumentWatcher myDocumentWatcher; + private final Set myEnabledRunProfiles = ContainerUtil.newHashSet(); @NotNull public static AutoTestManager getInstance(Project project) { @@ -92,11 +105,11 @@ public class AutoTestManager { Content content = descriptor.getAttachedContent(); if (content != null) { if (enabled) { - EXECUTION_ENVIRONMENT_KEY.set(content, environment); + myEnabledRunProfiles.add(environment.getRunProfile()); myDocumentWatcher.activate(); } else { - EXECUTION_ENVIRONMENT_KEY.set(content, null); + myEnabledRunProfiles.remove(environment.getRunProfile()); if (!hasEnabledAutoTests()) { myDocumentWatcher.deactivate(); } @@ -122,19 +135,11 @@ public class AutoTestManager { return isAutoTestEnabledForDescriptor(descriptor); } - private static boolean isAutoTestEnabledForDescriptor(@NotNull RunContentDescriptor descriptor) { + private boolean isAutoTestEnabledForDescriptor(@NotNull RunContentDescriptor descriptor) { Content content = descriptor.getAttachedContent(); if (content != null) { - ExecutionEnvironment watched = EXECUTION_ENVIRONMENT_KEY.get(content); - if (watched != null) { - ExecutionEnvironment current = getCurrentEnvironment(content); - boolean result = current != null && equals(current, watched); - if (!result) { - // let GC do its work - EXECUTION_ENVIRONMENT_KEY.set(content, null); - } - return result; - } + ExecutionEnvironment environment = getCurrentEnvironment(content); + return environment != null && myEnabledRunProfiles.contains(environment.getRunProfile()); } return false; } @@ -148,13 +153,6 @@ public class AutoTestManager { return LangDataKeys.EXECUTION_ENVIRONMENT.getData(DataManager.getInstance().getDataContext(component)); } - private static boolean equals(@NotNull ExecutionEnvironment env1, @NotNull ExecutionEnvironment env2) { - return env1.getRunProfile() == env2.getRunProfile() && - env1.getRunner() == env2.getRunner() && - env1.getExecutor() == env2.getExecutor() && - env1.getExecutionTarget() == env2.getExecutionTarget(); - } - private static void clearRestarterListener(@NotNull ProcessHandler processHandler) { ProcessListener restarterListener = ON_TERMINATION_RESTARTER_KEY.get(processHandler, null); if (restarterListener != null) { @@ -177,9 +175,9 @@ public class AutoTestManager { } } - private static void restartAutoTest(@NotNull RunContentDescriptor descriptor, - int modificationStamp, - @NotNull DelayedDocumentWatcher documentWatcher) { + private void restartAutoTest(@NotNull RunContentDescriptor descriptor, + int modificationStamp, + @NotNull DelayedDocumentWatcher documentWatcher) { ProcessHandler processHandler = descriptor.getProcessHandler(); if (processHandler != null && !processHandler.isProcessTerminated()) { scheduleRestartOnTermination(descriptor, processHandler, modificationStamp, documentWatcher); @@ -189,10 +187,10 @@ public class AutoTestManager { } } - private static void scheduleRestartOnTermination(@NotNull final RunContentDescriptor descriptor, - @NotNull final ProcessHandler processHandler, - final int modificationStamp, - @NotNull final DelayedDocumentWatcher documentWatcher) { + private void scheduleRestartOnTermination(@NotNull final RunContentDescriptor descriptor, + @NotNull final ProcessHandler processHandler, + final int modificationStamp, + @NotNull final DelayedDocumentWatcher documentWatcher) { ProcessListener restarterListener = ON_TERMINATION_RESTARTER_KEY.get(processHandler); if (restarterListener != null) { clearRestarterListener(processHandler); @@ -234,4 +232,51 @@ public class AutoTestManager { } PropertiesComponent.getInstance(myProject).setValue(AUTO_TEST_MANAGER_DELAY, myDelayMillis, AUTO_TEST_MANAGER_DELAY_DEFAULT); } + + @Nullable + @Override + public State getState() { + State state = new State(); + for (RunProfile profile : myEnabledRunProfiles) { + RunConfiguration runConfiguration = ObjectUtils.tryCast(profile, RunConfiguration.class); + if (runConfiguration != null) { + RunConfigurationDescriptor descriptor = new RunConfigurationDescriptor(); + descriptor.myType = runConfiguration.getType().getId(); + descriptor.myName = runConfiguration.getName(); + state.myEnabledRunConfigurations.add(descriptor); + } + } + return state; + } + + @Override + public void loadState(State state) { + List configurations = ContainerUtil.newArrayList(); + RunManagerImpl runManager = RunManagerImpl.getInstanceImpl(myProject); + for (RunConfigurationDescriptor descriptor : state.myEnabledRunConfigurations) { + RunnerAndConfigurationSettings settings = runManager.findConfigurationByTypeAndName(descriptor.myType, + descriptor.myName); + RunConfiguration configuration = settings != null ? settings.getConfiguration() : null; + if (configuration != null) { + configurations.add(configuration); + } + } + myEnabledRunProfiles.clear(); + myEnabledRunProfiles.addAll(configurations); + } + + static class State { + @Tag("enabled-run-configurations") + @AbstractCollection(surroundWithTag = false) + List myEnabledRunConfigurations = ContainerUtil.newArrayList(); + } + + @Tag("run-configuration") + static class RunConfigurationDescriptor { + @Attribute("type") + String myType; + + @Attribute("name") + String myName; + } } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 71ab7efa478b..cc338814ad06 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -195,7 +195,7 @@ debugger.breakpoint.message.full.trace.description='Log message to console' brea for the thread that hit the breakpoint. debugger.batch.evaluation=false debugger.compiling.evaluator=true -debugger.watches.in.variables=false +debugger.watches.in.variables=true debugger.auto.fetch.icons=true debugger.close.dialog.on.navigate=true debugger.close.dialog.on.navigate.description=Close evaluate dialog on Jump to (type) source action diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index f954137a570f..2b19021c1685 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -2407,7 +2407,7 @@ public class ContainerUtil extends ContainerUtilRt { return true; } - @Nullable + @Contract("null -> null; !null -> !null") public static List trimToSize(@Nullable List list) { if (list == null) return null; if (list.isEmpty()) return emptyList(); diff --git a/platform/util/testSrc/com/intellij/util/text/EditDistanceTest.java b/platform/util/testSrc/com/intellij/util/text/EditDistanceTest.java index 084d1791b007..57b9d4671125 100644 --- a/platform/util/testSrc/com/intellij/util/text/EditDistanceTest.java +++ b/platform/util/testSrc/com/intellij/util/text/EditDistanceTest.java @@ -40,6 +40,7 @@ public class EditDistanceTest { @Test public void optimalAlignment() { + assertEquals(0, EditDistance.optimalAlignment("", "", true)); assertEquals(1, EditDistance.optimalAlignment("ab", "ba", true)); assertEquals(2, EditDistance.optimalAlignment("AB", "ba", true)); assertEquals(3, EditDistance.optimalAlignment("ca", "abc", true)); @@ -48,6 +49,7 @@ public class EditDistanceTest { @Test public void optimalAlignmentCaseInsensitive() { + assertEquals(0, EditDistance.optimalAlignment("", "", false)); assertEquals(1, EditDistance.optimalAlignment("ab", "ba", false)); assertEquals(1, EditDistance.optimalAlignment("AB", "ba", false)); assertEquals(3, EditDistance.optimalAlignment("ca", "abc", false)); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/BinaryDiffRequestFromChange.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/BinaryDiffRequestFromChange.java deleted file mode 100644 index db57d5319961..000000000000 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/BinaryDiffRequestFromChange.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2000-2011 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.openapi.vcs.changes; - -import com.intellij.openapi.diff.DiffContent; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.actions.DiffRequestFromChange; -import com.intellij.openapi.vcs.changes.actions.ShowDiffAction; -import com.intellij.util.BeforeAfter; - -import java.util.Collections; -import java.util.List; - -/** - * @author irengrig - * Date: 6/15/11 - * Time: 5:48 PM - */ -public class BinaryDiffRequestFromChange implements DiffRequestFromChange { - private final Project myProject; - - public BinaryDiffRequestFromChange(Project project) { - myProject = project; - } - - @Override - public boolean canCreateRequest(Change change) { - return ShowDiffAction.isBinaryChangeAndCanShow(myProject, change); - } - - @Override - public List> createRequestForChange(Change change, int extraLines) throws VcsException { - return Collections.singletonList(ShowDiffAction.createBinaryDiffContents(myProject, change)); - } -} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/DiffRequestFromChange.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/DiffRequestFromChange.java deleted file mode 100644 index 70257d4f2d06..000000000000 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/DiffRequestFromChange.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2000-2011 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.openapi.vcs.changes.actions; - -import com.intellij.openapi.diff.DiffContent; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.util.BeforeAfter; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -/** - * @author irengrig - * Date: 6/10/11 - * Time: 6:39 PM - */ -public interface DiffRequestFromChange { - boolean canCreateRequest(final Change change); - @Nullable - List> createRequestForChange(final Change change, int extraLines) throws VcsException; -} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java deleted file mode 100644 index 597780a6b3de..000000000000 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffAction.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2000-2009 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.openapi.vcs.changes.actions; - -import com.intellij.icons.AllIcons; -import com.intellij.idea.ActionsBundle; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.diff.*; -import com.intellij.openapi.diff.impl.external.BinaryDiffTool; -import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.VcsBundle; -import com.intellij.openapi.vcs.VcsDataKeys; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.*; -import com.intellij.util.ArrayUtil; -import com.intellij.util.BeforeAfter; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.util.*; - -/** - * @author max - */ -public class ShowDiffAction extends AnAction implements DumbAware { - private static final Logger LOG = Logger.getInstance(ShowDiffAction.class); - - private static final String ourText = ActionsBundle.actionText("ChangesView.Diff"); - - public ShowDiffAction() { - super(ourText, - ActionsBundle.actionDescription("ChangesView.Diff"), - AllIcons.Actions.Diff); - } - - public void update(AnActionEvent e) { - Change[] changes = e.getData(VcsDataKeys.CHANGES); - Project project = e.getData(CommonDataKeys.PROJECT); - e.getPresentation().setEnabled(project != null && canShowDiff(changes)); - } - - protected static boolean canShowDiff(Change[] changes) { - if (changes == null || changes.length == 0) return false; - for (Change change : changes) { - if (!ChangesUtil.getFilePath(change).isDirectory() || change.hasOtherLayers()) return true; - } - return false; - } - - public void actionPerformed(final AnActionEvent e) { - final Project project = e.getData(CommonDataKeys.PROJECT); - if (project == null) return; - if (ChangeListManager.getInstance(project).isFreezedWithNotification(null)) return; - final Change[] changes = e.getData(VcsDataKeys.CHANGES); - if (changes == null) return; - - final boolean needsConvertion = checkIfThereAreFakeRevisions(project, changes); - final List changesInList = e.getData(VcsDataKeys.CHANGES_IN_LIST_KEY); - - // this trick is essential since we are under some conditions to refresh changes; - // but we can only rely on callback after refresh - final Runnable performer = new Runnable() { - public void run() { - Change[] convertedChanges; - if (needsConvertion) { - convertedChanges = loadFakeRevisions(project, changes); - } else { - convertedChanges = changes; - } - - if (convertedChanges == null || convertedChanges.length == 0) { - return; - } - - List changesInListCopy = changesInList; - - int index = 0; - if (convertedChanges.length == 1) { - final Change selectedChange = convertedChanges[0]; - ChangeList changeList = ((ChangeListManagerImpl) ChangeListManager.getInstance(project)).getIdentityChangeList(selectedChange); - if (changeList != null) { - if (changesInListCopy == null) { - changesInListCopy = new ArrayList(changeList.getChanges()); - Collections.sort(changesInListCopy, new Comparator() { - public int compare(final Change o1, final Change o2) { - return ChangesUtil.getFilePath(o1).getName().compareToIgnoreCase(ChangesUtil.getFilePath(o2).getName()); - } - }); - } - convertedChanges = changesInListCopy.toArray(new Change[changesInListCopy.size()]); - index = Math.max(0, ContainerUtil.indexOfIdentity(changesInListCopy, selectedChange)); - } - } - - showDiffForChange(convertedChanges, index, project); - } - }; - - if (needsConvertion) { - ChangeListManager.getInstance(project).invokeAfterUpdate(performer, InvokeAfterUpdateMode.BACKGROUND_CANCELLABLE, ourText, ModalityState.current()); - } else { - performer.run(); - } - } - - public static void showDiffForChange(final Change[] changes, final int index, final Project project) { - showDiffForChange(changes, index, project, new ShowDiffUIContext(true)); - } - - private static boolean checkIfThereAreFakeRevisions(final Project project, final Change[] changes) { - boolean needsConversion = false; - for(Change change: changes) { - final ContentRevision beforeRevision = change.getBeforeRevision(); - final ContentRevision afterRevision = change.getAfterRevision(); - if (beforeRevision instanceof FakeRevision) { - VcsDirtyScopeManager.getInstance(project).fileDirty(beforeRevision.getFile()); - needsConversion = true; - } - if (afterRevision instanceof FakeRevision) { - VcsDirtyScopeManager.getInstance(project).fileDirty(afterRevision.getFile()); - needsConversion = true; - } - } - return needsConversion; - } - - @Nullable - private static Change[] loadFakeRevisions(final Project project, final Change[] changes) { - List matchingChanges = new ArrayList(); - for(Change change: changes) { - matchingChanges.addAll(ChangeListManager.getInstance(project).getChangesIn(ChangesUtil.getFilePath(change))); - } - return matchingChanges.toArray(new Change[matchingChanges.size()]); - } - - public static void showDiffForChange(final Iterable changes, final Condition selectionChecker, - final Project project, @NotNull ShowDiffUIContext context) { - int newIndex = -1; - ChangeForDiffConvertor convertor = new ChangeForDiffConvertor(project, true); - final List changeList = ContainerUtil.newArrayList(); - for (Change change : changes) { - if (! directoryOrBinary(change)) { //todo - DiffRequestPresentable presentable = convertor.convert(change); - if (presentable != null) { - if ((newIndex == -1) && selectionChecker.value(change)) { - newIndex = changeList.size(); - } - changeList.add(presentable); - } - } - } - if (changeList.isEmpty()) { - return; - } - if (newIndex < 0) { - newIndex = 0; - } - - showDiffImpl(project, changeList, newIndex, context); - } - - public static void showDiffForChange(final Change[] changes, int index, final Project project, @NotNull ShowDiffUIContext context) { - final Change selected = index >= 0 ? changes[index] : null; - /*if (isBinaryDiff(project, changes, index)) { - showBinaryDiff(project, changes[index]); - return; - }*/ - showDiffForChange(Arrays.asList(changes), new Condition() { - @Override - public boolean value(final Change change) { - return selected != null && selected.equals(change); - } - }, project, context); - } - - private static FileContent createBinaryFileContent(final Project project, final ContentRevision contentRevision, final String fileName) - throws VcsException, IOException { - final FileContent fileContent; - if (contentRevision == null) { - fileContent = FileContent.createFromTempFile(project, - fileName, - fileName, - ArrayUtil.EMPTY_BYTE_ARRAY); - } else { - byte[] content = ((BinaryContentRevision)contentRevision).getBinaryContent(); - fileContent = FileContent.createFromTempFile(project, - contentRevision.getFile().getName(), - contentRevision.getFile().getName(), - content == null ? ArrayUtil.EMPTY_BYTE_ARRAY : content); - } - return fileContent; - } - - private static SimpleDiffRequest createBinaryDiffRequest(final Project project, final Change change) throws VcsException { - final FilePath filePath = ChangesUtil.getFilePath(change); - final SimpleDiffRequest request = new SimpleDiffRequest(project, filePath.getPath()); - try { - request.setContents(createBinaryFileContent(project, change.getBeforeRevision(), filePath.getName()), - createBinaryFileContent(project, change.getAfterRevision(), filePath.getName())); - return request; - } - catch (IOException e) { - throw new VcsException(e); - } - } - - public static BeforeAfter createBinaryDiffContents(final Project project, final Change change) throws VcsException { - final FilePath filePath = ChangesUtil.getFilePath(change); - try { - return new BeforeAfter(createBinaryFileContent(project, change.getBeforeRevision(), filePath.getName()), - createBinaryFileContent(project, change.getAfterRevision(), filePath.getName())); - } - catch (IOException e) { - throw new VcsException(e); - } - } - - private static void showBinaryDiff(Project project, Change change) { - try { - final SimpleDiffRequest request = createBinaryDiffRequest(project, change); - if (DiffManager.getInstance().getDiffTool().canShow(request)) { - DiffManager.getInstance().getDiffTool().show(request); - } - } - catch (VcsException e) { - Messages.showWarningDialog(e.getMessage(), "Show Diff"); - LOG.info(e); - } - } - - private static boolean isBinaryDiff(Project project, Change[] changes, int index) { - if (index >= 0 && index < changes.length) { - final Change change = changes[index]; - return isBinaryChangeAndCanShow(project, change); - } - return false; - } - - public static boolean isBinaryChange(Change change) { - if (change.hasOtherLayers()) return false; // +- - final ContentRevision bRev = change.getBeforeRevision(); - final ContentRevision aRev = change.getAfterRevision(); - - return (aRev == null || aRev instanceof BinaryContentRevision) - && (bRev == null || bRev instanceof BinaryContentRevision); - } - - public static boolean isBinaryChangeAndCanShow(Project project, Change change) { - // todo bug here would appear when there would be another diff providers for bimary revisions - return isBinaryChange(change) && (change.getAfterRevision() == null || BinaryDiffTool.canShow(project, change.getVirtualFile())); - } - - public static void showDiffImpl(final Project project, @NotNull List changeList, int index, - @NotNull final ShowDiffUIContext context) { - final ChangeDiffRequest request = new ChangeDiffRequest(project, changeList, context.getActionsFactory(), context.isShowFrame()); - final DiffTool tool = DiffManager.getInstance().getDiffTool(); - final DiffRequest simpleRequest; - try { - request.quickCheckHaveStuff(); - simpleRequest = request.init(index); - } - catch (VcsException e) { - Messages.showWarningDialog(e.getMessage(), "Show Diff"); - LOG.info(e); - return; - } - - if (simpleRequest != null) { - final DiffNavigationContext navigationContext = context.getDiffNavigationContext(); - if (navigationContext != null) { - simpleRequest.passForDataContext(DiffTool.SCROLL_TO_LINE, navigationContext); - } - tool.show(simpleRequest); - } - } - - private static boolean directoryOrBinary(final Change change) { - // todo instead for repository tab, filter directories (? ask remotely ? non leaf nodes) - /*if ((change.getBeforeRevision() instanceof BinaryContentRevision) || (change.getAfterRevision() instanceof BinaryContentRevision)) { - changesList.remove(i); - continue; - }*/ - final FilePath path = ChangesUtil.getFilePath(change); - if (path.isDirectory()) { - return ! change.hasOtherLayers(); - } - /*final FileType type = path.getFileType(); - if ((! FileTypes.UNKNOWN.equals(type)) && (type.isBinary())) { - return true; - }*/ - return false; - } - - private static boolean checkNotifyBinaryDiff(final Change selectedChange) { - final ContentRevision beforeRevision = selectedChange.getBeforeRevision(); - final ContentRevision afterRevision = selectedChange.getAfterRevision(); - if (beforeRevision instanceof BinaryContentRevision && - afterRevision instanceof BinaryContentRevision) { - try { - byte[] beforeContent = ((BinaryContentRevision)beforeRevision).getBinaryContent(); - byte[] afterContent = ((BinaryContentRevision)afterRevision).getBinaryContent(); - if (Arrays.equals(beforeContent, afterContent)) { - Messages.showInfoMessage(VcsBundle.message("message.text.binary.versions.are.identical"), VcsBundle.message("message.title.diff")); - } else { - Messages.showInfoMessage(VcsBundle.message("message.text.binary.versions.are.different"), VcsBundle.message("message.title.diff")); - } - } - catch (VcsException e) { - Messages.showInfoMessage(e.getMessage(), VcsBundle.message("message.title.diff")); - } - return true; - } - return false; - } -} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffUIContext.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffUIContext.java deleted file mode 100644 index 937b81ead9e5..000000000000 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ShowDiffUIContext.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.vcs.changes.actions; - -import com.intellij.openapi.diff.DiffNavigationContext; -import org.jetbrains.annotations.NotNull; - -public class ShowDiffUIContext { - private DiffExtendUIFactory myActionsFactory; - private boolean myShowFrame; - private DiffNavigationContext myDiffNavigationContext; - - public ShowDiffUIContext() { - myActionsFactory = DiffExtendUIFactory.NONE; - } - - public ShowDiffUIContext(boolean showFrame) { - myShowFrame = showFrame; - myActionsFactory = DiffExtendUIFactory.NONE; - } - - public DiffExtendUIFactory getActionsFactory() { - return myActionsFactory; - } - - public void setActionsFactory(@NotNull DiffExtendUIFactory actionsFactory) { - this.myActionsFactory = actionsFactory; - } - - public DiffNavigationContext getDiffNavigationContext() { - return myDiffNavigationContext; - } - - public void setDiffNavigationContext(DiffNavigationContext diffNavigationContext) { - myDiffNavigationContext = diffNavigationContext; - } - - public boolean isShowFrame() { - return myShowFrame; - } - - public void setShowFrame(boolean showFrame) { - this.myShowFrame = showFrame; - } -} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/ShowDiffAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/ShowDiffAction.java index 55bec3ec9451..379007ffbac6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/ShowDiffAction.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/diff/ShowDiffAction.java @@ -15,7 +15,6 @@ */ package com.intellij.openapi.vcs.changes.actions.diff; -import com.intellij.diff.DiffDialogHints; import com.intellij.diff.DiffManager; import com.intellij.diff.chains.DiffRequestChain; import com.intellij.diff.util.DiffUserDataKeys; @@ -33,7 +32,6 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.*; -import com.intellij.openapi.vcs.changes.actions.ShowDiffUIContext; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -219,16 +217,4 @@ public class ShowDiffAction extends AnAction implements DumbAware { DiffManager.getInstance().showDiff(project, chain, context.getDialogHints()); } - - // - // Compatibility - // - - @NotNull - public static ShowDiffContext convertContext(@NotNull ShowDiffUIContext uiContext) { - if (uiContext.getActionsFactory() != null) LOG.warn("DiffExtendUIFactory ignored"); - if (uiContext.getDiffNavigationContext() != null) LOG.warn("DiffNavigationContext ignored"); - - return new ShowDiffContext(uiContext.isShowFrame() ? DiffDialogHints.FRAME : DiffDialogHints.MODAL); - } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/GoToHashOrRefPopup.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/GoToHashOrRefPopup.java index b085efb224c5..e89226b4974f 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/GoToHashOrRefPopup.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/GoToHashOrRefPopup.java @@ -15,10 +15,9 @@ */ package com.intellij.vcs.log.ui.actions; -import com.intellij.codeInsight.completion.CompletionParameters; +import com.intellij.codeInsight.completion.CompletionResultSet; import com.intellij.codeInsight.completion.InsertHandler; import com.intellij.codeInsight.completion.InsertionContext; -import com.intellij.codeInsight.completion.PlainPrefixMatcher; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.application.ApplicationManager; @@ -30,10 +29,11 @@ import com.intellij.openapi.ui.popup.JBPopupListener; import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.TextFieldWithAutoCompletionListProvider; import com.intellij.ui.components.JBLabel; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.textCompletion.DefaultTextCompletionValueDescriptor; +import com.intellij.util.textCompletion.ValuesCompletionProvider; import com.intellij.util.ui.ColorIcon; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.VcsRef; @@ -46,8 +46,10 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; -import java.util.*; -import java.util.List; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -72,7 +74,7 @@ public class GoToHashOrRefPopup { myOnSelectedHash = onSelectedHash; myOnSelectedRef = onSelectedRef; myTextField = - new TextFieldWithProgress(project, new VcsRefCompletionProvider(project, variants, roots, colorManager, comparator)) { + new TextFieldWithProgress(project, new VcsRefCompletionProvider(project, variants, roots, colorManager, comparator)) { @Override public void onOk() { if (myFuture == null) { @@ -154,47 +156,64 @@ public class GoToHashOrRefPopup { myPopup.showInCenterOf(anchor); } - private class VcsRefCompletionProvider extends TextFieldWithAutoCompletionListProvider { - @NotNull private final Project myProject; - @NotNull private final VcsLogColorManager myColorManager; - @NotNull private final Comparator myReferenceComparator; - @NotNull private final Map myCachedRootNames = ContainerUtil.newHashMap(); + private class VcsRefCompletionProvider extends ValuesCompletionProvider { public VcsRefCompletionProvider(@NotNull Project project, @NotNull Collection variants, @NotNull Collection roots, @NotNull VcsLogColorManager colorManager, @NotNull Comparator comparator) { - super(variants); + super(new VcsRefDescriptor(project, colorManager, comparator, roots), variants); + } + + @NotNull + @Override + protected Collection getValues(@NotNull String prefix, @NotNull CompletionResultSet result) { + return ContainerUtil.filter(myValues, new Condition() { + @Override + public boolean value(VcsRef vcsRef) { + return result.getPrefixMatcher().prefixMatches(vcsRef.getName()); + } + }); + } + } + + private class VcsRefDescriptor extends DefaultTextCompletionValueDescriptor { + @NotNull private final Project myProject; + @NotNull private final VcsLogColorManager myColorManager; + @NotNull private final Comparator myReferenceComparator; + @NotNull private final Map myCachedRootNames = ContainerUtil.newHashMap(); + + private VcsRefDescriptor(@NotNull Project project, + @NotNull VcsLogColorManager manager, + @NotNull Comparator comparator, + @NotNull Collection roots) { myProject = project; - myColorManager = colorManager; + myColorManager = manager; myReferenceComparator = comparator; + for (VirtualFile root : roots) { String text = VcsImplUtil.getShortVcsRootName(myProject, root); myCachedRootNames.put(root, text); } } + @NotNull @Override public LookupElementBuilder createLookupBuilder(@NotNull VcsRef item) { LookupElementBuilder lookupBuilder = super.createLookupBuilder(item); if (myColorManager.isMultipleRoots()) { lookupBuilder = lookupBuilder - .withTypeText(getTypeText(item), new ColorIcon(15, VcsLogGraphTable.getRootBackgroundColor(item.getRoot(), myColorManager)), + .withTypeText(getTypeText(item), + new ColorIcon(15, VcsLogGraphTable.getRootBackgroundColor(item.getRoot(), myColorManager)), true); } return lookupBuilder; } - @Nullable - @Override - protected Icon getIcon(@NotNull VcsRef item) { - return null; - } - @NotNull @Override - protected String getLookupString(@NotNull VcsRef item) { + public String getLookupString(@NotNull VcsRef item) { return item.getName(); } @@ -244,28 +263,5 @@ public class GoToHashOrRefPopup { } }; } - - @NotNull - @Override - public Collection getItems(String prefix, boolean cached, CompletionParameters parameters) { - if (prefix == null) { - return Collections.emptyList(); - } - - List items = new ArrayList(getMatched(myVariants, prefix)); - Collections.sort(items, this); - - return items; - } - - private List getMatched(@NotNull Collection refs, @NotNull String prefix) { - final PlainPrefixMatcher prefixMatcher = new PlainPrefixMatcher(prefix); - return ContainerUtil.filter(refs, new Condition() { - @Override - public boolean value(VcsRef vcsRef) { - return prefixMatcher.prefixMatches(vcsRef.getName()); - } - }); - } } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/TextFieldWithProgress.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/TextFieldWithProgress.java index ae7a3e9c6c4d..0f861b13809f 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/TextFieldWithProgress.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/actions/TextFieldWithProgress.java @@ -15,14 +15,10 @@ */ package com.intellij.vcs.log.ui.actions; -import com.intellij.codeInsight.AutoPopupController; -import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider; -import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; -import com.intellij.ui.EditorCustomization; import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.TextFieldWithAutoCompletion; -import com.intellij.ui.TextFieldWithAutoCompletionListProvider; +import com.intellij.util.textCompletion.TextCompletionProvider; +import com.intellij.util.textCompletion.TextFieldWithCompletion; import com.intellij.util.ui.AsyncProcessIcon; import org.jetbrains.annotations.NotNull; @@ -30,34 +26,23 @@ import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; -public abstract class TextFieldWithProgress extends JPanel { - @NotNull private final TextFieldWithAutoCompletion myTextField; +public abstract class TextFieldWithProgress extends JPanel { + @NotNull private final TextFieldWithCompletion myTextField; @NotNull private final AsyncProcessIcon myProgressIcon; public TextFieldWithProgress(@NotNull Project project, - @NotNull TextFieldWithAutoCompletionListProvider completionProvider) { + @NotNull TextCompletionProvider completionProvider) { super(new BorderLayout()); setBorder(IdeBorderFactory.createEmptyBorder(3)); myProgressIcon = new AsyncProcessIcon("Loading commits"); - myTextField = new TextFieldWithAutoCompletion(project, completionProvider, false, null) { + myTextField = new TextFieldWithCompletion(project, completionProvider, "", true, true, false) { @Override public void setBackground(Color bg) { super.setBackground(bg); myProgressIcon.setBackground(bg); } - @Override - protected EditorEx createEditor() { - EditorEx editor = super.createEditor(); - editor.putUserData(AutoPopupController.ALWAYS_AUTO_POPUP, true); - EditorCustomization customization = SpellCheckingEditorCustomizationProvider.getInstance().getDisabledCustomization(); - if (customization != null) { - customization.customize(editor); - } - return editor; - } - @Override protected boolean processKeyBinding(KeyStroke ks, final KeyEvent e, int condition, boolean pressed) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultilinePopupBuilder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultilinePopupBuilder.java index 728bd2fc9045..62c2ef8d8af0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultilinePopupBuilder.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultilinePopupBuilder.java @@ -15,15 +15,11 @@ */ package com.intellij.vcs.log.ui.filter; -import com.intellij.codeInsight.AutoPopupController; -import com.intellij.codeInsight.completion.CompletionResultSet; -import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.google.common.primitives.Chars; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonShortcuts; -import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider; import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; @@ -31,14 +27,16 @@ import com.intellij.openapi.ui.popup.ComponentPopupBuilder; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.EditorCustomization; import com.intellij.ui.EditorTextField; -import com.intellij.ui.LanguageTextField; import com.intellij.ui.SoftWrapsEditorCustomization; import com.intellij.util.Function; -import com.intellij.util.TextFieldCompletionProviderDumbAware; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.textCompletion.DefaultTextCompletionValueDescriptor; +import com.intellij.util.textCompletion.TextFieldWithCompletion; +import com.intellij.util.textCompletion.ValuesCompletionProvider; +import com.intellij.util.textCompletion.ValuesCompletionProvider.ValuesCompletionProviderDumbAware; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.CompoundBorder; @@ -46,7 +44,6 @@ import java.awt.*; import java.util.Collection; class MultilinePopupBuilder { - private static final char[] SEPARATORS = {',', '|', '\n'}; @NotNull private final EditorTextField myTextField; @@ -63,20 +60,16 @@ class MultilinePopupBuilder { Collection values, boolean supportsNegativeValues, @NotNull String initialValue) { - EditorTextField textField = new LanguageTextField(FileTypes.PLAIN_TEXT.getLanguage(), project, "") { - @Override - protected EditorEx createEditor() { - EditorEx editor = super.createEditor(); - SoftWrapsEditorCustomization.ENABLED.customize(editor); - EditorCustomization disableSpellChecking = SpellCheckingEditorCustomizationProvider.getInstance().getDisabledCustomization(); - if (disableSpellChecking != null) disableSpellChecking.customize(editor); - editor.putUserData(AutoPopupController.ALWAYS_AUTO_POPUP, true); - return editor; - } - }; - new MyCompletionProvider(values, supportsNegativeValues).apply(textField, initialValue); + TextFieldWithCompletion textField = + new TextFieldWithCompletion(project, new MyCompletionProvider(values, supportsNegativeValues), initialValue, false, true, false) { + @Override + protected EditorEx createEditor() { + EditorEx editor = super.createEditor(); + SoftWrapsEditorCustomization.ENABLED.customize(editor); + return editor; + } + }; textField.setBorder(new CompoundBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2), textField.getBorder())); - textField.setOneLineMode(false); return textField; } @@ -115,45 +108,16 @@ class MultilinePopupBuilder { }); } - private static class MyCompletionProvider extends TextFieldCompletionProviderDumbAware { - - @NotNull private final Collection myValues; - private final boolean mySupportsNegativeValues; - + private static class MyCompletionProvider extends ValuesCompletionProviderDumbAware { MyCompletionProvider(@NotNull Collection values, boolean supportsNegativeValues) { - super(true); - myValues = values; - mySupportsNegativeValues = supportsNegativeValues; + super(new DefaultTextCompletionValueDescriptor.StringValueDescriptor(), + supportsNegativeValues ? ContainerUtil.append(Chars.asList(SEPARATORS), '-') : Chars.asList(SEPARATORS), values, false); } - @NotNull + @Nullable @Override - protected String getPrefix(@NotNull String currentTextPrefix) { - final int separatorPosition = lastSeparatorPosition(currentTextPrefix); - String prefix = separatorPosition == -1 ? currentTextPrefix : currentTextPrefix.substring(separatorPosition + 1).trim(); - return mySupportsNegativeValues && prefix.startsWith("-") ? prefix.substring(1) : prefix; - } - - private static int lastSeparatorPosition(@NotNull String text) { - int lastPosition = -1; - for (char separator : SEPARATORS) { - int lio = text.lastIndexOf(separator); - if (lio > lastPosition) { - lastPosition = lio; - } - } - return lastPosition; - } - - @SuppressWarnings("StringToUpperCaseOrToLowerCaseWithoutLocale") - @Override - protected void addCompletionVariants(@NotNull String text, int offset, @NotNull String prefix, - @NotNull CompletionResultSet result) { - result.addLookupAdvertisement("Select one or more users separated with comma, | or new lines"); - for (String completionVariant : myValues) { - final LookupElementBuilder element = LookupElementBuilder.create(completionVariant); - result.addElement(element.withLookupString(completionVariant.toLowerCase())); - } + public String getAdvertisement() { + return "Select one or more values separated with | or new lines"; } } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java index 362bac2ac83b..dd59735b763c 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/WatchNodeImpl.java @@ -16,6 +16,7 @@ package com.intellij.xdebugger.impl.ui.tree.nodes; import com.intellij.icons.AllIcons; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.util.ThreeState; import com.intellij.xdebugger.Obsolescent; import com.intellij.xdebugger.XExpression; @@ -42,7 +43,8 @@ public class WatchNodeImpl extends XValueNodeImpl implements WatchNode { @NotNull WatchesRootNode parent, @NotNull XExpression expression, @Nullable XStackFrame stackFrame) { - super(tree, parent, expression.getExpression(), new XWatchValue(expression, tree.isShowing() ? stackFrame : null)); + super(tree, parent, expression.getExpression(), + new XWatchValue(expression, tree.isShowing() || ApplicationManager.getApplication().isUnitTestMode() ? stackFrame : null)); myExpression = expression; } diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java index a8b998665084..a654a1745692 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java +++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java @@ -16,14 +16,11 @@ package git4idea.checkin; import com.intellij.CommonBundle; -import com.intellij.codeInsight.AutoPopupController; import com.intellij.dvcs.DvcsCommitAdditionalComponent; import com.intellij.dvcs.DvcsUtil; import com.intellij.dvcs.push.ui.VcsPushDialog; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider; -import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; @@ -37,12 +34,18 @@ import com.intellij.openapi.vcs.checkin.CheckinChangeListSpecificComponent; import com.intellij.openapi.vcs.checkin.CheckinEnvironment; import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.*; +import com.intellij.ui.EditorTextField; +import com.intellij.ui.GuiUtils; import com.intellij.util.Function; import com.intellij.util.FunctionUtil; import com.intellij.util.NullableFunction; import com.intellij.util.PairConsumer; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.textCompletion.DefaultTextCompletionValueDescriptor; +import com.intellij.util.textCompletion.TextCompletionProvider; +import com.intellij.util.textCompletion.TextFieldWithCompletion; +import com.intellij.util.textCompletion.ValuesCompletionProvider; +import com.intellij.util.textCompletion.ValuesCompletionProvider.ValuesCompletionProviderDumbAware; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsUser; @@ -89,7 +92,9 @@ public class GitCheckinEnvironment implements CheckinEnvironment { private Boolean myNextCommitIsPushed = null; // The push option of the next commit private Date myNextCommitAuthorDate; - public GitCheckinEnvironment(@NotNull Project project, @NotNull final VcsDirtyScopeManager dirtyScopeManager, final GitVcsSettings settings) { + public GitCheckinEnvironment(@NotNull Project project, + @NotNull final VcsDirtyScopeManager dirtyScopeManager, + final GitVcsSettings settings) { myProject = project; myDirtyScopeManager = dirtyScopeManager; mySettings = settings; @@ -249,14 +254,13 @@ public class GitCheckinEnvironment implements CheckinEnvironment { /** * Preform a merge commit * - * - * @param project a project - * @param root a vcs root - * @param added added files - * @param removed removed files - * @param messageFile a message file for commit - * @param author an author - * @param exceptions the list of exceptions to report + * @param project a project + * @param root a vcs root + * @param added added files + * @param removed removed files + * @param messageFile a message file for commit + * @param author an author + * @param exceptions the list of exceptions to report * @param partialOperation * @return true if merge commit was successful */ @@ -284,7 +288,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment { return false; } String rootPath = root.getPath(); - for (StringTokenizer lines = new StringTokenizer(output, "\n", false); lines.hasMoreTokens();) { + for (StringTokenizer lines = new StringTokenizer(output, "\n", false); lines.hasMoreTokens(); ) { String line = lines.nextToken().trim(); if (line.length() == 0) { continue; @@ -365,7 +369,6 @@ public class GitCheckinEnvironment implements CheckinEnvironment { /** * Check if commit has failed due to unfinished merge or cherry-pick. * - * * @param ex an exception to examine * @return true if exception means that there is a partial commit during merge */ @@ -619,19 +622,9 @@ public class GitCheckinEnvironment implements CheckinEnvironment { @NotNull private EditorTextField createTextField(@NotNull Project project, @NotNull List list) { - TextFieldWithAutoCompletionListProvider completionProvider = new TextFieldWithAutoCompletion.StringsCompletionProvider(list, null); - return new TextFieldWithAutoCompletion(project, completionProvider, true, null) { - @Override - protected EditorEx createEditor() { - EditorEx editor = super.createEditor(); - editor.putUserData(AutoPopupController.ALWAYS_AUTO_POPUP, true); - EditorCustomization customization = SpellCheckingEditorCustomizationProvider.getInstance().getDisabledCustomization(); - if (customization != null) { - customization.customize(editor); - } - return editor; - } - }; + TextCompletionProvider completionProvider = + new ValuesCompletionProviderDumbAware<>(new DefaultTextCompletionValueDescriptor.StringValueDescriptor(), list); + return new TextFieldWithCompletion(project, completionProvider, "", true, true, true); } @Override diff --git a/plugins/git4idea/src/git4idea/update/GitFetcher.java b/plugins/git4idea/src/git4idea/update/GitFetcher.java index cc5fb3dd4b9c..531cd9a1c84a 100644 --- a/plugins/git4idea/src/git4idea/update/GitFetcher.java +++ b/plugins/git4idea/src/git4idea/update/GitFetcher.java @@ -256,7 +256,7 @@ public class GitFetcher { */ public boolean fetchRootsAndNotify(@NotNull Collection roots, @Nullable String errorNotificationTitle, boolean notifySuccess) { - MultiRootMessage additionalInfo = new MultiRootMessage(myProject, GitUtil.getRootsFromRepositories(roots)); + MultiRootMessage additionalInfo = new MultiRootMessage(myProject, GitUtil.getRootsFromRepositories(roots), true); for (GitRepository repository : roots) { LOG.info("fetching " + repository); GitFetchResult result = fetch(repository); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushTargetPanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushTargetPanel.java index 4b5644758f63..c6740a13bb91 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushTargetPanel.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushTargetPanel.java @@ -28,6 +28,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.TextFieldWithAutoCompletion; +import com.intellij.util.textCompletion.TextFieldWithCompletion; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.repo.HgRepository; @@ -41,7 +42,7 @@ public class HgPushTargetPanel extends PushTargetPanel { private final static String ENTER_REMOTE = "Enter Remote"; private final HgRepository myRepository; private final String myBranchName; - private final TextFieldWithAutoCompletion myDestTargetPanel; + private final TextFieldWithCompletion myDestTargetPanel; private final VcsEditableTextComponent myTargetRenderedComponent; public HgPushTargetPanel(@NotNull HgRepository repository, @Nullable HgTarget defaultTarget) { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java index 3ceb99cafc60..1b8188a3f0c5 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java @@ -224,20 +224,20 @@ public class InvocationExprent extends Exprent { else { if (instance != null && instance.type == Exprent.EXPRENT_VAR) { - VarExprent instvar = (VarExprent)instance; - VarVersionPair varpaar = new VarVersionPair(instvar); + VarExprent instVar = (VarExprent)instance; + VarVersionPair varPair = new VarVersionPair(instVar); - VarProcessor vproc = instvar.getProcessor(); - if (vproc == null) { - MethodWrapper current_meth = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); - if (current_meth != null) { - vproc = current_meth.varproc; + VarProcessor varProc = instVar.getProcessor(); + if (varProc == null) { + MethodWrapper currentMethod = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); + if (currentMethod != null) { + varProc = currentMethod.varproc; } } String this_classname = null; - if (vproc != null) { - this_classname = vproc.getThisVars().get(varpaar); + if (varProc != null) { + this_classname = varProc.getThisVars().get(varPair); } if (this_classname != null) { @@ -334,7 +334,7 @@ public class InvocationExprent extends Exprent { boolean firstParameter = true; int start = isEnum ? 2 : 0; for (int i = start; i < lstParameters.size(); i++) { - if (sigFields == null) { + if (sigFields == null || sigFields.get(i) == null) { if (!firstParameter) { buf.append(", "); } @@ -512,43 +512,35 @@ public class InvocationExprent extends Exprent { // ***************************************************************************** // IMatchable implementation // ***************************************************************************** - - public boolean match(MatchNode matchNode, MatchEngine engine) { - if(!super.match(matchNode, engine)) { + @Override + public boolean match(MatchNode matchNode, MatchEngine engine) { + if (!super.match(matchNode, engine)) { return false; } - - for(Entry rule : matchNode.getRules().entrySet()) { + + for (Entry rule : matchNode.getRules().entrySet()) { RuleValue value = rule.getValue(); - - switch(rule.getKey()) { - case EXPRENT_INVOCATION_PARAMETER: - if(value.isVariable()) { - if(value.parameter < lstParameters.size()) { - if(!engine.checkAndSetVariableValue(value.value.toString(), lstParameters.get(value.parameter))) { - return false; - } - } else { - return false; - } + + MatchProperties key = rule.getKey(); + if (key == MatchProperties.EXPRENT_INVOCATION_PARAMETER) { + if (value.isVariable() && (value.parameter >= lstParameters.size() || + !engine.checkAndSetVariableValue(value.value.toString(), lstParameters.get(value.parameter)))) { + return false; } - break; - case EXPRENT_INVOCATION_CLASS: - if(!value.value.equals(this.classname)) { + } + else if (key == MatchProperties.EXPRENT_INVOCATION_CLASS) { + if (!value.value.equals(this.classname)) { + return false; + } + } + else if (key == MatchProperties.EXPRENT_INVOCATION_SIGNATURE) { + if (!value.value.equals(this.name + this.stringDescriptor)) { return false; } - break; - case EXPRENT_INVOCATION_SIGNATURE: - if(!value.value.equals(this.name + this.stringDescriptor)) { - return false; - } - break; } - } - + return true; } - -} +} \ No newline at end of file diff --git a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java index e905fb373014..100deeba6282 100644 --- a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -84,6 +84,7 @@ public class SingleClassesTest { @Test public void testMethodReferenceLetterClass() { doTest("pkg/TestMethodReferenceLetterClass"); } @Test public void testMemberAnnotations() { doTest("pkg/TestMemberAnnotations"); } @Test public void testStaticNameClash() { doTest("pkg/TestStaticNameClash"); } + @Test public void testExtendingSubclass() { doTest("pkg/TestExtendingSubclass"); } protected void doTest(String testFile, String... companionFiles) { ConsoleDecompiler decompiler = fixture.getDecompiler(); diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestExtendingSubclass$Subclass1.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestExtendingSubclass$Subclass1.class new file mode 100644 index 000000000000..fbf2ce2b4220 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestExtendingSubclass$Subclass1.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestExtendingSubclass$Subclass2.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestExtendingSubclass$Subclass2.class new file mode 100644 index 000000000000..d30cc61f5272 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestExtendingSubclass$Subclass2.class differ diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestExtendingSubclass.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestExtendingSubclass.class new file mode 100644 index 000000000000..eb4f049285b0 Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestExtendingSubclass.class differ diff --git a/plugins/java-decompiler/engine/testData/results/TestExtendingSubclass.dec b/plugins/java-decompiler/engine/testData/results/TestExtendingSubclass.dec new file mode 100644 index 000000000000..5e1398580832 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/results/TestExtendingSubclass.dec @@ -0,0 +1,35 @@ +package pkg; + +public class TestExtendingSubclass { + class Subclass2 extends TestExtendingSubclass.Subclass1 { + Subclass2(String name) { + super(name);// 14 + }// 15 + } + + class Subclass1 { + Subclass1(String name) { + }// 9 + } +} + +class 'pkg/TestExtendingSubclass$Subclass2' { + method ' (Lpkg/TestExtendingSubclass;Ljava/lang/String;)V' { + 8 5 + b 6 + } +} + +class 'pkg/TestExtendingSubclass$Subclass1' { + method ' (Lpkg/TestExtendingSubclass;Ljava/lang/String;)V' { + 9 11 + } +} + +Lines mapping: +9 <-> 12 +14 <-> 6 +15 <-> 7 +Not mapped: +8 +13 diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestExtendingSubclass.java b/plugins/java-decompiler/engine/testData/src/pkg/TestExtendingSubclass.java new file mode 100644 index 000000000000..f63baedce1f5 --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestExtendingSubclass.java @@ -0,0 +1,18 @@ +package pkg; + +import java.math.BigDecimal; + +public class TestExtendingSubclass { + + class Subclass1 { + Subclass1(String name) { + } + } + + class Subclass2 extends Subclass1 { + Subclass2(String name) { + super(name); + } + } + +} diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxEventHandlerInspectionTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxEventHandlerInspectionTest.java index d7548ba56ba9..b16ff99fff5b 100644 --- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxEventHandlerInspectionTest.java +++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxEventHandlerInspectionTest.java @@ -1,6 +1,8 @@ package org.jetbrains.plugins.javaFX.fxml; +import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.application.PluginPathManager; +import com.intellij.testFramework.PlatformTestUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections.JavaFxEventHandlerInspection; @@ -30,11 +32,19 @@ public class JavaFxEventHandlerInspectionTest extends AbstractJavaFXTestCase { doHighlightingTest(); } - public void testHighlightSimpleGeneric() throws Exception { + public void testHighlightGeneric() throws Exception { doHighlightingTest(); } - public void testHighlightMixedGeneric() throws Exception { + public void testHighlightRaw() throws Exception { + doHighlightingTest(); + } + + public void testHighlightHalfRaw() throws Exception { + doHighlightingTest(); + } + + public void testHighlightSpecific() throws Exception { doHighlightingTest(); } @@ -42,11 +52,31 @@ public class JavaFxEventHandlerInspectionTest extends AbstractJavaFXTestCase { doHighlightingTest(); } + public void testQuickfixRaw() throws Exception { + doQuickfixTest("Create method 'void onSort(SortEvent)'"); + } + + public void testQuickfixHalfRaw() throws Exception { + doQuickfixTest("Create method 'void onSort(SortEvent)'"); + } + + public void testQuickfixSpecific() throws Exception { + doQuickfixTest("Create method 'void onSort(SortEvent)'"); + } + private void doHighlightingTest() throws Exception { - myFixture.configureByFiles(getTestName(true) + ".fxml", getTestName(false) + "Controller.java"); + myFixture.configureByFiles(getTestName(true) + ".fxml", getTestName(false) + ".java"); myFixture.checkHighlighting(); } + private void doQuickfixTest(final String actionName) throws Exception { + String path = getTestName(true) + ".fxml"; + final IntentionAction intention = myFixture.getAvailableIntention(actionName, path, getTestName(false) + ".java"); + assertNotNull(intention); + myFixture.launchAction(intention); + myFixture.checkResultByFile(getTestName(false) + ".java", getTestName(false) + "_after.java", true); + } + @NotNull @Override protected String getTestDataPath() { diff --git a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml index 4254ed7768e6..ab49b0351667 100644 --- a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml +++ b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml @@ -26,7 +26,7 @@ enabledByDefault="true" level="WARNING" displayName="JavaFX redundant property values" groupName="JavaFX"/> - diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java index 74ace5e83b0d..59516d09cc67 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java @@ -112,7 +112,8 @@ public class JavaFxPsiUtil { for (String anImport : imports) { if (StringUtil.getShortName(anImport).equals(name)) { psiClass = psiFacade.findClass(anImport, file.getResolveScope()); - } else if (StringUtil.endsWith(anImport, ".*")) { + } + else if (StringUtil.endsWith(anImport, ".*")) { psiClass = psiFacade.findClass(StringUtil.trimEnd(anImport, "*") + name, file.getResolveScope()); } if (psiClass != null) { @@ -133,7 +134,8 @@ public class JavaFxPsiUtil { final XmlProlog prolog = document.getProlog(); if (prolog != null) { prolog.add(processingInstruction); - } else { + } + else { document.addBefore(processingInstruction, document.getRootTag()); } PostprocessReformattingAspect.getInstance(xmlFile.getProject()).doPostponedFormatting(xmlFile.getViewProvider()); @@ -223,6 +225,7 @@ public class JavaFxPsiUtil { private static final Key> INJECTED_CONTROLLER = Key.create("javafx.injected.controller"); private static final RecursionGuard ourGuard = RecursionManager.createGuard("javafx.controller"); + public static PsiClass getControllerClass(final PsiFile containingFile) { if (containingFile instanceof XmlFile) { final XmlTag rootTag = ((XmlFile)containingFile).getRootTag(); @@ -262,7 +265,7 @@ public class JavaFxPsiUtil { final String attributeValue = attribute.getValue(); if (!StringUtil.isEmptyOrSpaces(attributeValue)) { final GlobalSearchScope customScope = GlobalSearchScope.projectScope(project).intersectWith(containingFile.getResolveScope()); - return JavaPsiFacade.getInstance(project).findClass(attributeValue, customScope); + return JavaPsiFacade.getInstance(project).findClass(attributeValue, customScope); } return null; } @@ -373,7 +376,8 @@ public class JavaFxPsiUtil { } public static PsiType getDefaultPropertyExpectedType(PsiClass aClass) { - final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy(aClass, Collections.singleton(JavaFxCommonNames.JAVAFX_BEANS_DEFAULT_PROPERTY)); + final PsiAnnotation annotation = + AnnotationUtil.findAnnotationInHierarchy(aClass, Collections.singleton(JavaFxCommonNames.JAVAFX_BEANS_DEFAULT_PROPERTY)); if (annotation != null) { final PsiAnnotationMemberValue memberValue = annotation.findAttributeValue(null); if (memberValue != null) { @@ -392,7 +396,8 @@ public class JavaFxPsiUtil { return null; } final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy(aClass, - Collections.singleton(JavaFxCommonNames.JAVAFX_BEANS_DEFAULT_PROPERTY)); + Collections.singleton( + JavaFxCommonNames.JAVAFX_BEANS_DEFAULT_PROPERTY)); if (annotation != null) { final PsiAnnotationMemberValue memberValue = annotation.findAttributeValue(null); if (memberValue != null) { @@ -403,7 +408,7 @@ public class JavaFxPsiUtil { } public static String isAbleToInstantiate(final PsiClass psiClass) { - if(psiClass.getConstructors().length > 0) { + if (psiClass.getConstructors().length > 0) { for (PsiMethod constr : psiClass.getConstructors()) { final PsiParameter[] parameters = constr.getParameterList().getParameters(); if (parameters.length == 0) return null; @@ -496,7 +501,7 @@ public class JavaFxPsiUtil { final String qualifiedName = baseClass.getQualifiedName(); if (qualifiedName != null && !Comparing.strEqual(qualifiedName, CommonClassNames.JAVA_LANG_STRING)) { if (!InheritanceUtil.isInheritor(aClass, qualifiedName)) { - return unableToCoerceMessage(aClass, qualifiedName); + return unableToCoerceMessage(aClass, qualifiedName); } } } @@ -505,7 +510,7 @@ public class JavaFxPsiUtil { } private static String unableToCoerceMessage(PsiClass aClass, String qualifiedName) { - return "Unable to coerce " + HighlightUtil.formatClass(aClass)+ " to " + qualifiedName; + return "Unable to coerce " + HighlightUtil.formatClass(aClass) + " to " + qualifiedName; } public static boolean isOutOfHierarchy(final XmlAttributeValue element) { @@ -835,10 +840,10 @@ public class JavaFxPsiUtil { } @Nullable - public static PsiSubstitutor getTagClassSubstitutor(@NotNull XmlTag xmlTag, - @Nullable PsiClass fieldClass, - @Nullable PsiClass controllerClass) { - if (fieldClass != null && controllerClass != null) { + public static PsiSubstitutor getTagClassSubstitutor(@NotNull XmlAttribute xmlAttribute, @NotNull PsiClass controllerClass) { + final XmlTag xmlTag = xmlAttribute.getParent(); + final PsiClass tagClass = getTagClass(xmlTag); + if (tagClass != null) { final String tagFieldName = xmlTag.getAttributeValue(FxmlConstants.FX_ID); if (tagFieldName != null) { final PsiField tagField = controllerClass.findFieldByName(tagFieldName, true); @@ -846,7 +851,7 @@ public class JavaFxPsiUtil { final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(tagField.getType()); final PsiClass resolvedClass = resolveResult.getElement(); if (resolvedClass != null) { - return TypeConversionUtil.getClassSubstitutor(fieldClass, resolvedClass, resolveResult.getSubstitutor()); + return TypeConversionUtil.getClassSubstitutor(tagClass, resolvedClass, resolveResult.getSubstitutor()); } } } @@ -854,6 +859,38 @@ public class JavaFxPsiUtil { return null; } + @Nullable + public static PsiType getEventHandlerPropertyType(@NotNull PsiClass tagClass, @NotNull String eventName) { + final PsiMethod[] handlerSetterCandidates = tagClass.findMethodsByName(PropertyUtil.suggestSetterName(eventName), true); + for (PsiMethod handlerSetter : handlerSetterCandidates) { + if (!handlerSetter.hasModifierProperty(PsiModifier.STATIC) && + handlerSetter.hasModifierProperty(PsiModifier.PUBLIC)) { + final PsiType propertyType = PropertyUtil.getPropertyType(handlerSetter); + if (InheritanceUtil.isInheritor(propertyType, JavaFxCommonNames.JAVAFX_EVENT_EVENT_HANDLER)) { + return propertyType; + } + } + } + final PsiField handlerField = tagClass.findFieldByName(eventName, true); + final PsiClassType propertyType = getPropertyClassType(handlerField); + if (InheritanceUtil.isInheritor(propertyType, JavaFxCommonNames.JAVAFX_EVENT_EVENT_HANDLER)) { + return propertyType; + } + return null; + } + + @Nullable + public static PsiType substituteEventType(@NotNull PsiClassType eventHandlerClass, @NotNull Project project) { + final PsiClass eventHandlerInterface = + JavaPsiFacade.getInstance(project).findClass(JavaFxCommonNames.JAVAFX_EVENT_EVENT_HANDLER, GlobalSearchScope.allScope(project)); + if (eventHandlerInterface == null) return null; + final PsiTypeParameter[] typeParameters = eventHandlerInterface.getTypeParameters(); + if (typeParameters.length != 1) return null; + final PsiTypeParameter typeParameter = typeParameters[0]; + final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(eventHandlerInterface, eventHandlerClass); + return substitutor.substitute(typeParameter); + } + private static class JavaFxControllerCachedValueProvider implements CachedValueProvider { private final Project myProject; private final PsiFile myContainingFile; diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxEventHandlerInspection.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxEventHandlerInspection.java index 6fce1ce6d307..962abbd1eb7d 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxEventHandlerInspection.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/inspections/JavaFxEventHandlerInspection.java @@ -1,18 +1,17 @@ package org.jetbrains.plugins.javaFX.fxml.codeInsight.inspections; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.intention.QuickFixFactory; +import com.intellij.codeInspection.IntentionWrapper; +import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.XmlSuppressableInspectionTool; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; -import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.psi.xml.XmlFile; -import com.intellij.psi.xml.XmlTag; -import com.intellij.xml.XmlElementDescriptor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonNames; @@ -20,11 +19,12 @@ import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory; import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil; import javax.swing.*; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import static org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil.isNotFullyResolvedGeneric; +import static org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil.getTagClass; /** * @author Pavel.Dolgov @@ -43,11 +43,12 @@ public class JavaFxEventHandlerInspection extends XmlSuppressableInspectionTool } @Override - public void visitXmlAttribute(XmlAttribute attribute) { - super.visitXmlAttribute(attribute); - - final PsiFile containingFile = attribute.getContainingFile(); - final PsiClass controllerClass = JavaFxPsiUtil.getControllerClass(containingFile); + public void visitXmlAttributeValue(XmlAttributeValue xmlAttributeValue) { + super.visitXmlAttributeValue(xmlAttributeValue); + final PsiElement valueParent = xmlAttributeValue.getParent(); + if (!(valueParent instanceof XmlAttribute)) return; + final XmlAttribute attribute = (XmlAttribute)valueParent; + final PsiClass controllerClass = JavaFxPsiUtil.getControllerClass(attribute.getContainingFile()); if (controllerClass == null) return; final String valueText = attribute.getValue(); @@ -61,7 +62,7 @@ public class JavaFxEventHandlerInspection extends XmlSuppressableInspectionTool .collect(Collectors.toList()); if (eventHandlerMethods.size() == 0) return; if (eventHandlerMethods.size() != 1) { - holder.registerProblem(getHighlightedElement(attribute), "Ambiguous event handler name: more than one matching method found"); + holder.registerProblem(xmlAttributeValue, "Ambiguous event handler name: more than one matching method found"); } if (myDetectNonVoidReturnType) { @@ -69,136 +70,77 @@ public class JavaFxEventHandlerInspection extends XmlSuppressableInspectionTool .map(PsiMethod::getReturnType) .filter(returnType -> !PsiType.VOID.equals(returnType)) .findAny() - .ifPresent(ignored -> holder.registerProblem(getHighlightedElement(attribute), "Return type of event handler should be void")); + .ifPresent(ignored -> holder.registerProblem(xmlAttributeValue, "Return type of event handler should be void")); } - final PsiClassType eventClassType = getHandlerArgumentClassType(attribute, controllerClass); - if (eventClassType == null) return; - final boolean eventClassTypeNotFullyResolved = isNotFullyResolvedGeneric(eventClassType); + final PsiSubstitutor tagClassSubstitutor = JavaFxPsiUtil.getTagClassSubstitutor(attribute, controllerClass); + final PsiClassType declaredType = getDeclaredEventType(attribute, tagClassSubstitutor); + if (declaredType == null) return; - eventHandlerMethods.stream() - .map(method -> method.getParameterList().getParameters()) - .filter(parameters -> parameters.length == 1) - .map(parameters -> parameters[0].getType()) - .forEach(argType -> { - if (argType instanceof PsiClassType) { - final boolean assignable; - if (eventClassTypeNotFullyResolved || isNotFullyResolvedGeneric((PsiClassType)argType)) { - assignable = isAssignableFromIgnoringUnresolved((PsiClassType)argType, eventClassType); - } - else { - assignable = argType.isAssignableFrom(eventClassType); - } - if (!assignable) { - holder.registerProblem(getHighlightedElement(attribute), - "Incompatible event handler argument: " + argType.getPresentableText() + - " is not assignable from " + eventClassType.getPresentableText()); + for (PsiMethod method : eventHandlerMethods) { + final PsiParameter[] parameters = method.getParameterList().getParameters(); + if (parameters.length == 1) { + final PsiType actualType = parameters[0].getType(); + if (actualType instanceof PsiClassType) { + if (!actualType.isAssignableFrom(declaredType)) { + final LocalQuickFix quickFix = createChangeArgumentTypeQuickFix(controllerClass, declaredType, method, tagClassSubstitutor); + + final PsiClassType actualRawType = ((PsiClassType)actualType).rawType(); + final PsiClassType expectedRawType = declaredType.rawType(); + if (actualRawType.isAssignableFrom(expectedRawType)) { + holder.registerProblem(xmlAttributeValue, + "Incompatible generic parameter of event handler argument: " + actualType.getCanonicalText() + + " is not assignable from " + declaredType.getCanonicalText(), + quickFix); + } + else { + holder.registerProblem(xmlAttributeValue, + "Incompatible event handler argument: " + actualRawType.getCanonicalText() + + " is not assignable from " + expectedRawType.getCanonicalText(), + quickFix); + } } } - else { - holder.registerProblem(getHighlightedElement(attribute), - "Unresolved event handler argument type " + argType.getCanonicalText()); - } - }); + } + } } }; } - private static boolean isAssignableFromIgnoringUnresolved(@Nullable PsiClassType left, @Nullable PsiClassType right) { - if (left == null || right == null) return true; - final PsiClassType.ClassResolveResult leftResolveResult = left.resolveGenerics(); - final PsiClassType.ClassResolveResult rightResolveResult = right.resolveGenerics(); - - final PsiClass leftClass = leftResolveResult.getElement(); - final PsiClass rightClass = rightResolveResult.getElement(); - - if (leftClass == null || rightClass == null || leftClass instanceof PsiTypeParameter || rightClass instanceof PsiTypeParameter) { - return true; - } - if (leftClass.getManager().areElementsEquivalent(leftClass, rightClass)) { - // generic args are assignable or unresolved - if (!leftClass.hasTypeParameters()) return true; - final PsiSubstitutor leftSubstitutor = leftResolveResult.getSubstitutor(); - final PsiSubstitutor rightSubstitutor = rightResolveResult.getSubstitutor(); - final PsiTypeParameter[] typeParameters = leftClass.getTypeParameters(); - for (PsiTypeParameter typeParameter : typeParameters) { - final PsiType leftParameter = leftSubstitutor.substitute(typeParameter); - if (leftParameter == null || leftParameter instanceof PsiTypeParameter) continue; - final PsiType rightParameter = rightSubstitutor.substitute(typeParameter); - if (rightParameter == null || rightParameter instanceof PsiTypeParameter) continue; - final PsiClassType leftParameterClass = getBoundClassType(leftParameter, true); - final PsiClassType rightParameterClass = getBoundClassType(rightParameter, false); - if (!isAssignableFromIgnoringUnresolved(leftParameterClass, rightParameterClass)) { - return false; - } - } - return true; - } - else if (leftClass.isInheritor(rightClass, true)) { - // generic args are equal - final PsiType rightSubstitute = leftResolveResult.getSubstitutor().substitute(right); - return rightSubstitute.isAssignableFrom(left); - } - return false; + @NotNull + private static LocalQuickFix createChangeArgumentTypeQuickFix(@NotNull PsiClass controllerClass, + @NotNull PsiClassType declaredType, + @NotNull PsiMethod method, + @Nullable PsiSubstitutor tagClassSubstitutor) { + final PsiElementFactory psiElementFactory = JavaPsiFacade.getElementFactory(controllerClass.getProject()); + final PsiExpression expression = psiElementFactory.createExpressionFromText("new " + declaredType.getCanonicalText() + "(){}", method); + final IntentionAction intentionAction = QuickFixFactory.getInstance() + .createChangeMethodSignatureFromUsageFix(method, new PsiExpression[]{expression}, + tagClassSubstitutor != null ? tagClassSubstitutor : PsiSubstitutor.EMPTY, + controllerClass, false, 2); + return new IntentionWrapper(intentionAction, method.getContainingFile()); } @Nullable - private static PsiClassType getBoundClassType(PsiType psiType, boolean isSuper) { - if (psiType instanceof PsiClassType) { - return (PsiClassType)psiType; - } - if (psiType instanceof PsiWildcardType) { - PsiWildcardType wildcardType = (PsiWildcardType)psiType; - if (isSuper && wildcardType.isSuper() || !isSuper && wildcardType.isExtends()) { - final PsiType bound = wildcardType.getBound(); - if (bound instanceof PsiClassType) return (PsiClassType)bound; + private static PsiClassType getDeclaredEventType(@NotNull XmlAttribute attribute, @Nullable PsiSubstitutor tagClassSubstitutor) { + final PsiClass tagClass = getTagClass(attribute.getParent()); + if (tagClass == null) return null; + + final PsiType eventHandlerPropertyType = JavaFxPsiUtil.getEventHandlerPropertyType(tagClass, attribute.getName()); + if (eventHandlerPropertyType == null) return null; + + final PsiType handlerType = + tagClassSubstitutor != null ? tagClassSubstitutor.substitute(eventHandlerPropertyType) : eventHandlerPropertyType; + if (handlerType instanceof PsiClassType) { + final PsiType eventType = JavaFxPsiUtil.substituteEventType((PsiClassType)handlerType, tagClass.getProject()); + if (eventType instanceof PsiClassType) { + return (PsiClassType)eventType; } - } - return null; - } - - private static PsiElement getHighlightedElement(XmlAttribute attribute) { - final XmlAttributeValue valueElement = attribute.getValueElement(); - return valueElement != null ? valueElement : attribute; - } - - @Nullable - private static PsiClassType getHandlerArgumentClassType(@NotNull XmlAttribute attribute, PsiClass controllerClass) { - final XmlTag xmlTag = attribute.getParent(); - final XmlElementDescriptor descriptor = xmlTag.getDescriptor(); - if (descriptor == null) return null; - final PsiElement declaration = descriptor.getDeclaration(); - if (!(declaration instanceof PsiClass)) return null; - final PsiClass tagClass = (PsiClass)declaration; - - final String handlerSetterName = PropertyUtil.suggestSetterName(attribute.getName()); - final PsiMethod[] handlerSetterCandidates = tagClass.findMethodsByName(handlerSetterName, true); - if (handlerSetterCandidates.length == 0) return null; - - final Project project = attribute.getProject(); - final PsiClass javaFxEventHandlerClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonNames.JAVAFX_EVENT_EVENT_HANDLER, - GlobalSearchScope.allScope(project)); - if (javaFxEventHandlerClass != null) { - final PsiTypeParameter[] typeParameters = javaFxEventHandlerClass.getTypeParameters(); - if (typeParameters.length == 1) { - final PsiTypeParameter javaFxEventHandlerTypeParameter = typeParameters[0]; - final PsiSubstitutor tagClassSubstitutor = JavaFxPsiUtil.getTagClassSubstitutor(xmlTag, tagClass, controllerClass); - for (PsiMethod handlerSetter : handlerSetterCandidates) { - if (handlerSetter.hasModifierProperty(PsiModifier.STATIC) || !handlerSetter.hasModifierProperty(PsiModifier.PUBLIC)) continue; - final PsiParameter[] parameters = handlerSetter.getParameterList().getParameters(); - if (parameters.length == 1) { - PsiType handlerParameterType = parameters[0].getType(); - if (tagClassSubstitutor != null) { - handlerParameterType = tagClassSubstitutor.substitute(handlerParameterType); - } - if (handlerParameterType instanceof PsiClassType && - InheritanceUtil.isInheritorOrSelf(((PsiClassType)handlerParameterType).resolve(), javaFxEventHandlerClass, true)) { - final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)handlerParameterType).resolveGenerics(); - final PsiType eventType = resolveResult.getSubstitutor().substitute(javaFxEventHandlerTypeParameter); - PsiClassType eventClassType = getBoundClassType(eventType, true); - if (eventClassType != null) return eventClassType; - } - } + if (eventType instanceof PsiWildcardType) { + PsiWildcardType wildcardType = (PsiWildcardType)eventType; + if (wildcardType.isSuper()) { + final PsiType bound = wildcardType.getBound(); + if (bound instanceof PsiClassType) return (PsiClassType)bound; } } } diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java index 387dde67d20a..28b92236fd79 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxEventHandlerReference.java @@ -18,15 +18,11 @@ package org.jetbrains.plugins.javaFX.fxml.refs; import com.intellij.codeInsight.daemon.QuickFixActionRegistrar; import com.intellij.codeInsight.daemon.impl.quickfix.CreateMethodQuickFix; import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.TypeConversionUtil; import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; -import com.intellij.psi.xml.XmlTag; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -108,35 +104,21 @@ public class JavaFxEventHandlerReference extends PsiReferenceBase list; public void onEditStart(ListView.EditEvent e) {} diff --git a/plugins/javaFX/testData/inspections/eventHandler/HighlightHalfRaw.java b/plugins/javaFX/testData/inspections/eventHandler/HighlightHalfRaw.java new file mode 100644 index 000000000000..a66d653be29a --- /dev/null +++ b/plugins/javaFX/testData/inspections/eventHandler/HighlightHalfRaw.java @@ -0,0 +1,15 @@ +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.util.Pair; + +import java.util.Map; + +public class HighlightHalfRaw { + @FXML TableView positive; + @FXML TableView negative; + public void sortPositive(SortEvent> e) {} + public void scrollPositive(ScrollToEvent> e) {} + + public void sortNegative(SortEvent e) {} + public void scrollNegative(ScrollToEvent> e) {} +} diff --git a/plugins/javaFX/testData/inspections/eventHandler/HighlightMixedGenericController.java b/plugins/javaFX/testData/inspections/eventHandler/HighlightMixedGenericController.java deleted file mode 100644 index 32c5e07d3f3c..000000000000 --- a/plugins/javaFX/testData/inspections/eventHandler/HighlightMixedGenericController.java +++ /dev/null @@ -1,37 +0,0 @@ -import javafx.fxml.FXML; -import javafx.scene.control.*; -import javafx.util.Pair; -import java.util.Map; - -public class HighlightMixedGenericController { - @FXML TableView> specificTable; - @FXML TableView> specificTableHalfRawArg; - @FXML TableView> specificTableIncompatibleArg; - @FXML TableView> specificTableIncompatibleHalfRawArg; - - @FXML TableView halfRawTable; - @FXML TableView halfRawTableHalfRawArg; - @FXML TableView halfRawTableIncompatibleArg; - @FXML TableView halfRawTableIncompatibleHalfRawArg; - - @FXML TableView rawTable; - @FXML TableView rawTableHalfRawArg; - @FXML TableView rawTableIncompatibleArg; - @FXML TableView rawTableIncompatibleHalfRawArg; - - public void onSort(SortEvent>> e) {} - public void onScrollTo(ScrollToEvent e) {} - public void onScrollToColumn(ScrollToEvent, ?>> e) {} - - public void onSortHalfRawArg(SortEvent e) {} - public void onScrollToHalfRawArg(ScrollToEvent e) {} - public void onScrollToColumnHalfRawArg(ScrollToEvent e) {} - - public void onSortIncompatibleArg(SortEvent>> e) {} - public void onScrollToIncompatibleArg(ScrollToEvent e) {} - public void onScrollToColumnIncompatibleArg(ScrollToEvent, ?>> e) {} - - public void onSortIncompatibleHalfRawArg(SortEvent> e) {} - public void onScrollToIncompatibleHalfRawArg(ScrollToEvent e) {} - public void onScrollToColumnIncompatibleHalfRawArg(ScrollToEvent> e) {} -} diff --git a/plugins/javaFX/testData/inspections/eventHandler/HighlightNonVoidController.java b/plugins/javaFX/testData/inspections/eventHandler/HighlightNonVoid.java similarity index 84% rename from plugins/javaFX/testData/inspections/eventHandler/HighlightNonVoidController.java rename to plugins/javaFX/testData/inspections/eventHandler/HighlightNonVoid.java index d14be2642bd5..fb246bca9199 100644 --- a/plugins/javaFX/testData/inspections/eventHandler/HighlightNonVoidController.java +++ b/plugins/javaFX/testData/inspections/eventHandler/HighlightNonVoid.java @@ -1,7 +1,7 @@ import javafx.event.ActionEvent; import javafx.event.Event; -public class HighlightNonVoidController { +public class HighlightNonVoid { public String onSameArgNotVoid(ActionEvent e) {return "";} public Boolean onSuperArgNotVoid(Event e) {return false;} public int onNoArgNotVoid() {return 1;} diff --git a/plugins/javaFX/testData/inspections/eventHandler/HighlightRaw.java b/plugins/javaFX/testData/inspections/eventHandler/HighlightRaw.java new file mode 100644 index 000000000000..fee21b0a7793 --- /dev/null +++ b/plugins/javaFX/testData/inspections/eventHandler/HighlightRaw.java @@ -0,0 +1,13 @@ +import javafx.fxml.FXML; +import javafx.scene.control.*; + +public class HighlightRaw { + @FXML TableView positive; + @FXML TableView negative; + + public void sortPositive(SortEvent e) {} + public void scrollPositive(ScrollToEvent e) {} + + public void sortNegative(ScrollToEvent e) {} + public void scrollNegative(ScrollToEvent e) {} +} diff --git a/plugins/javaFX/testData/inspections/eventHandler/HighlightSpecific.java b/plugins/javaFX/testData/inspections/eventHandler/HighlightSpecific.java new file mode 100644 index 000000000000..461aecc03310 --- /dev/null +++ b/plugins/javaFX/testData/inspections/eventHandler/HighlightSpecific.java @@ -0,0 +1,15 @@ +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.util.Pair; + +import java.util.Map; + +public class HighlightSpecific { + @FXML TableView> positive; + @FXML TableView> negative; + public void sortPositive(SortEvent>> e) {} + public void scrollPositive(ScrollToEvent, ?>> e) {} + + public void sortNegative(SortEvent e) {} + public void scrollNegative(ScrollToEvent, ?>> e) {} +} diff --git a/plugins/javaFX/testData/inspections/eventHandler/HighlightWildcardController.java b/plugins/javaFX/testData/inspections/eventHandler/HighlightWildcard.java similarity index 90% rename from plugins/javaFX/testData/inspections/eventHandler/HighlightWildcardController.java rename to plugins/javaFX/testData/inspections/eventHandler/HighlightWildcard.java index 4bb1b0f45474..40c969b14e88 100644 --- a/plugins/javaFX/testData/inspections/eventHandler/HighlightWildcardController.java +++ b/plugins/javaFX/testData/inspections/eventHandler/HighlightWildcard.java @@ -4,7 +4,7 @@ import javafx.scene.control.SortEvent; import javafx.scene.input.MouseDragEvent; import javafx.scene.input.MouseEvent; -public class HighlightWildcardController { +public class HighlightWildcard { @FXML private void onSameArg(MouseEvent e) {} @FXML private void onSuperArg(Event e) {} @FXML private void onNoArg() {} diff --git a/plugins/javaFX/testData/inspections/eventHandler/QuickfixHalfRaw.java b/plugins/javaFX/testData/inspections/eventHandler/QuickfixHalfRaw.java new file mode 100644 index 000000000000..3db6b6a54a77 --- /dev/null +++ b/plugins/javaFX/testData/inspections/eventHandler/QuickfixHalfRaw.java @@ -0,0 +1,7 @@ +import javafx.fxml.FXML; +import javafx.scene.control.TableView; +import javafx.util.Pair; + +public class QuickfixHalfRaw { + @FXML TableView table; +} diff --git a/plugins/javaFX/testData/inspections/eventHandler/QuickfixHalfRaw_after.java b/plugins/javaFX/testData/inspections/eventHandler/QuickfixHalfRaw_after.java new file mode 100644 index 000000000000..c6dd5f73ae91 --- /dev/null +++ b/plugins/javaFX/testData/inspections/eventHandler/QuickfixHalfRaw_after.java @@ -0,0 +1,12 @@ +import javafx.fxml.FXML; +import javafx.scene.control.SortEvent; +import javafx.scene.control.TableView; +import javafx.util.Pair; + +public class QuickfixHalfRaw { + @FXML TableView table; + + public void onSort(SortEvent sortEvent) { + + } +} diff --git a/plugins/javaFX/testData/inspections/eventHandler/QuickfixRaw.java b/plugins/javaFX/testData/inspections/eventHandler/QuickfixRaw.java new file mode 100644 index 000000000000..d11b3be7b70b --- /dev/null +++ b/plugins/javaFX/testData/inspections/eventHandler/QuickfixRaw.java @@ -0,0 +1,6 @@ +import javafx.fxml.FXML; +import javafx.scene.control.TableView; + +public class QuickfixRaw { + @FXML TableView table; +} diff --git a/plugins/javaFX/testData/inspections/eventHandler/QuickfixRaw_after.java b/plugins/javaFX/testData/inspections/eventHandler/QuickfixRaw_after.java new file mode 100644 index 000000000000..5a0886c9dfca --- /dev/null +++ b/plugins/javaFX/testData/inspections/eventHandler/QuickfixRaw_after.java @@ -0,0 +1,11 @@ +import javafx.fxml.FXML; +import javafx.scene.control.SortEvent; +import javafx.scene.control.TableView; + +public class QuickfixRaw { + @FXML TableView table; + + public void onSort(SortEvent sortEvent) { + + } +} diff --git a/plugins/javaFX/testData/inspections/eventHandler/QuickfixSpecific.java b/plugins/javaFX/testData/inspections/eventHandler/QuickfixSpecific.java new file mode 100644 index 000000000000..9d7b7e9ec760 --- /dev/null +++ b/plugins/javaFX/testData/inspections/eventHandler/QuickfixSpecific.java @@ -0,0 +1,8 @@ +import javafx.fxml.FXML; +import javafx.scene.control.TableView; +import javafx.util.Pair; + +public class QuickfixSpecific { + @FXML + TableView> table; +} \ No newline at end of file diff --git a/plugins/javaFX/testData/inspections/eventHandler/QuickfixSpecific_after.java b/plugins/javaFX/testData/inspections/eventHandler/QuickfixSpecific_after.java new file mode 100644 index 000000000000..9ad1f4c4332f --- /dev/null +++ b/plugins/javaFX/testData/inspections/eventHandler/QuickfixSpecific_after.java @@ -0,0 +1,13 @@ +import javafx.fxml.FXML; +import javafx.scene.control.SortEvent; +import javafx.scene.control.TableView; +import javafx.util.Pair; + +public class QuickfixSpecific { + @FXML + TableView> table; + + public void onSort(SortEvent>> tableViewSortEvent) { + + } +} \ No newline at end of file diff --git a/plugins/javaFX/testData/inspections/eventHandler/highlightAmbiguous.fxml b/plugins/javaFX/testData/inspections/eventHandler/highlightAmbiguous.fxml index 56b8dab341dc..84274cc22494 100644 --- a/plugins/javaFX/testData/inspections/eventHandler/highlightAmbiguous.fxml +++ b/plugins/javaFX/testData/inspections/eventHandler/highlightAmbiguous.fxml @@ -1,6 +1,6 @@ - +