diff --git a/.idea/libraries/builder_model.xml b/.idea/libraries/builder_model.xml
deleted file mode 100644
index 194983c4ed4c..000000000000
--- a/.idea/libraries/builder_model.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/dexlib2.xml b/.idea/libraries/dexlib2.xml
new file mode 100644
index 000000000000..b38e3790e09d
--- /dev/null
+++ b/.idea/libraries/dexlib2.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/google_analytics_library.xml b/.idea/libraries/google_analytics_library.xml
new file mode 100644
index 000000000000..4065f2b9e542
--- /dev/null
+++ b/.idea/libraries/google_analytics_library.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/sherpa_solver.xml b/.idea/libraries/sherpa_solver.xml
index b0cca4264467..dafc23b05b18 100644
--- a/.idea/libraries/sherpa_solver.xml
+++ b/.idea/libraries/sherpa_solver.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/.idea/libraries/studio_profiler_grpc_1_0_jarjar.xml b/.idea/libraries/studio_profiler_grpc_1_0_jarjar.xml
new file mode 100644
index 000000000000..16ebb4312e9c
--- /dev/null
+++ b/.idea/libraries/studio_profiler_grpc_1_0_jarjar.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 3455ca934d71..40c5ad631ac4 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -3,6 +3,7 @@
+
@@ -12,15 +13,17 @@
+
-
+
-
-
+
+
+
@@ -65,6 +68,7 @@
+
@@ -190,7 +194,9 @@
+
+
@@ -200,6 +206,8 @@
+
+
@@ -211,6 +219,7 @@
+
@@ -236,14 +245,13 @@
-
+
-
-
+
@@ -252,7 +260,6 @@
-
@@ -290,6 +297,7 @@
+
@@ -307,7 +315,6 @@
-
\ No newline at end of file
diff --git a/.idea/runConfigurations/Android_Studio.xml b/.idea/runConfigurations/Android_Studio.xml
new file mode 100644
index 000000000000..8019da516f41
--- /dev/null
+++ b/.idea/runConfigurations/Android_Studio.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build/conf/jreVersions.properties b/build/conf/jreVersions.properties
deleted file mode 100644
index 2b58cecdd81e..000000000000
--- a/build/conf/jreVersions.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-trunk=481
-eap=481
-release=408
\ No newline at end of file
diff --git a/build/dependencies/setupJdk.gradle b/build/dependencies/setupJdk.gradle
index 8736f2627f21..dd9ae49fe6c9 100644
--- a/build/dependencies/setupJdk.gradle
+++ b/build/dependencies/setupJdk.gradle
@@ -120,8 +120,20 @@ task setupJdk16(dependsOn: configurations.jdk16) {
doLast {
logger.info("Setting up JDK 1.6 to compile")
unpackJdk(jdkArchive.call(), outputDir)
+ deleteBrokenSymlink(outputDir)
}
}
+
+// Gradle dies on tring to process broken links: https://issues.gradle.org/browse/GRADLE-1843
+private void deleteBrokenSymlink(def outputDir) {
+ if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) {
+ def pluginJar = file("$outputDir/Home/lib/plugin.jar")
+ if (!pluginJar.exists()) {
+ pluginJar.delete()
+ }
+ }
+}
+
setupJdk16.onlyIf { inJetBrainsNetwork }
def intellijProjectDir() {
diff --git a/build/groovy/org/jetbrains/intellij/build/BaseIdeaProperties.groovy b/build/groovy/org/jetbrains/intellij/build/BaseIdeaProperties.groovy
index 837dd3668a0d..82a78e76ae37 100644
--- a/build/groovy/org/jetbrains/intellij/build/BaseIdeaProperties.groovy
+++ b/build/groovy/org/jetbrains/intellij/build/BaseIdeaProperties.groovy
@@ -65,7 +65,7 @@ abstract class BaseIdeaProperties extends ProductProperties {
"tasks-core", "tasks-java",
"maven", "gradle",
"git4idea", "remote-servers-git", "remote-servers-git-java", "svn4idea", "hg4idea", "github", "cvs-plugin",
- "jetgroovy", "junit", "testng", "xpath", "xslt-debugger", "android", "javaFX-CE",
+ "jetgroovy", "junit", "testng", "xpath", "xslt-debugger", "android-plugin", "javaFX-CE",
"java-i18n", "ant", "ui-designer", "ByteCodeViewer", "coverage", "java-decompiler-plugin", "devkit", "eclipse",
"IntelliLang", "IntelliLang-java", "IntelliLang-xml", "intellilang-jps-plugin"
]
diff --git a/build/scripts/download_jre.gant b/build/scripts/download_jre.gant
deleted file mode 100644
index 3437c08b9d81..000000000000
--- a/build/scripts/download_jre.gant
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2000-2017 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.
- */
-
-import com.intellij.openapi.util.SystemInfo
-
-import java.util.regex.Pattern
-
-target('default': 'Downloads custom JRE build from Teamcity server') {
- def platform = SystemInfo.isMac ? "mac" : SystemInfo.isWindows ? "win" : SystemInfo.isLinux ? "linux" : ""
- if (platform == "") {
- echo "Unsupported platform, JRE download skipped"
- return
- }
- if (jreArchitecture == "disable") {
- echo "JRE update disabled"
- return
- }
- if (!(jreArchitecture == "64" || jreArchitecture == "32" && platform == "win")) {
- echo "Acceptable architecture (32 or 64 bit) is not defined, JRE download skipped"
- return
- }
-
- def majorBuildNumber = ideBuildNumber.split(/\./)[0]
- def buildConfiguration = jreBuildTypeId.replaceAll(/#build#/, majorBuildNumber)
-
- String buildId, buildNumber
- try {
- buildId = new URL("$jreTeamcityUrl/buildTypes/id:$buildConfiguration/builds/tags:$jreBuildTag/id").text
- buildNumber = new URL("$jreTeamcityUrl/builds/id:$buildId/number").text
- }
- catch (IOException e) {
- echo "Build server connection failed: ${e.message}, JRE download skipped"
- return
- }
-
- java(jvm: SystemInfo.isMac ? "$workIdeaHome/jdk/Contents/Home/jre/bin/java" : "$workIdeaHome/jre/jre/bin/java",
- fork: "true", classname: "dummy", outputproperty: "jvmVersionOutput") {
- jvmarg(value: "-version")
- }
- try {
- if (jvmVersionOutput =~ /\(build .*release-${Pattern.quote(buildNumber.replace(".", "-b"))}\)/ &&
- jvmVersionOutput =~ (jreArchitecture == "64" ? /OpenJDK 64-Bit Server VM/ : /OpenJDK Server VM/)) {
- echo "Latest version of custom JRE is installed, no update is required"
- return
- }
- }
- catch (MissingPropertyException ignored) {
- echo "Could'nt determine existing JRE version"
- }
- def files = new XmlSlurper().parse("$jreTeamcityUrl/builds/id:$buildId/artifacts/children/$platform")
- def artifact = files.children().collect { it.@name.text() }.find {
- it.startsWith(jreArtifactPrefix) && it.endsWith(jreArchitecture == "64" ? "_x64.tar.gz" : "_x86.tar.gz") && !it.contains("debug")
- }
- get src: "$jreTeamcityUrl/builds/id:$buildId/artifacts/content/$platform/$artifact", dest: deployDir
- if (SystemInfo.isWindows) {
- mkdir dir: "$deployDir/jre"
- untar src: "$deployDir/$artifact", dest: "$deployDir/jre", compression: "gzip"
- }
- else if (SystemInfo.isMac) {
- // untar task doesn't support symlinks, so we need to use native tar executable
- exec(executable: "tar", dir: "$deployDir") {
- arg(value: "-xf")
- arg(value: "$artifact")
- }
- }
- else if (SystemInfo.isLinux) {
- mkdir dir: "$deployDir/jre"
- // untar task doesn't support symlinks, so we need to use native tar executable
- exec(executable: "tar", dir: "$deployDir") {
- arg(value: "-xf")
- arg(value: "$artifact")
- arg(value: "--directory")
- arg(value: "jre")
- }
- }
- delete file: "$deployDir/$artifact"
-}
\ No newline at end of file
diff --git a/build/scripts/download_kotlin.gant b/build/scripts/download_kotlin.gant
deleted file mode 100644
index c6f2a57364f5..000000000000
--- a/build/scripts/download_kotlin.gant
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright 2000-2017 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.
- */
-
-import com.intellij.openapi.util.text.StringUtil
-import com.intellij.util.text.VersionComparatorUtil
-import groovyjarjarasm.asm.AnnotationVisitor
-import groovyjarjarasm.asm.ClassReader
-import groovyjarjarasm.asm.ClassVisitor
-import groovyjarjarasm.asm.Opcodes
-
-import java.util.jar.JarFile
-
-import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
-
-includeTargets << new File("${guessHome(this)}/build/scripts/utils.gant")
-
-String kotlinBuildConfigurationOnPublicTeamCity = "Kotlin_110_CompilerAndPlugin_NoTests"
-
-target('default': 'Ensures that build/kotlinc directory contains JARs from Kotlin plugin compatible with current IDEA sources. These JARs are used by build scripts.') {
- def communityHome = guessHome(this)
- def classVersionOfCompiledClasses = readKotlinClassVersionOfCompiledClasses()
- def reasonToUpdate = getReasonToUpdate(communityHome, new File(communityHome, "build/kotlinc/plugin/Kotlin"), classVersionOfCompiledClasses)
- if (reasonToUpdate == null) {
- if (isDefined("workIdeaHome")) {
- def workKotlinVersionFile = new File(workIdeaHome, "plugins/Kotlin/kotlinc/build.txt")
- if (workKotlinVersionFile.exists()) {
- try {
- def currentKotlinVersionFile = new File(communityHome, "build/kotlinc/build.txt")
- if (VersionComparatorUtil.compare(currentKotlinVersionFile.text, workKotlinVersionFile.text) < 0) {
- reasonToUpdate = "a newer version is installed in $workIdeaHome"
- }
- }
- catch (IOException e) {
- reasonToUpdate = "cannot read Kotlin version: $e"
- }
- }
- }
-
- if (reasonToUpdate == null) {
- projectBuilder.info("Compatible Kotlin plugin already installed, no update is required")
- return
- }
- }
-
- projectBuilder.info("Kotlin plugin will be updated: $reasonToUpdate")
-
- if (isDefined("workIdeaHome")) {
- if (updatePluginFromWorkIdeaInstallation(communityHome, workIdeaHome, classVersionOfCompiledClasses)) {
- return
- }
- }
-
- if (isDefined("kotlin.teamcity.host")) {
- if (downloadAndExtract(new TeamCityBuildLocator(p("kotlin.teamcity.host"), p("kotlin.build.type.id"), p("kotlin.build.selector")),
- communityHome, classVersionOfCompiledClasses)) {
- return
- }
- }
- if (!downloadAndExtract(new TeamCityBuildLocator("https://teamcity.jetbrains.com", kotlinBuildConfigurationOnPublicTeamCity, "status:SUCCESS"),
- communityHome, classVersionOfCompiledClasses)) {
- projectBuilder.error("Failed to install Kotlin plugin")
- }
-}
-
-private boolean updatePluginFromWorkIdeaInstallation(String communityHome, String workIdeaHome, String classVersionOfCompiledClasses) {
- def kotlinPluginFromWorkIdea = new File(workIdeaHome, "plugins/Kotlin")
- if (!kotlinPluginFromWorkIdea.exists()) {
- projectBuilder.info("Cannot use Kotlin from $workIdeaHome: the plugin directory doesn't exist")
- return false
- }
-
- def reasonToUpdate = getReasonToUpdate(communityHome, kotlinPluginFromWorkIdea, classVersionOfCompiledClasses)
- if (reasonToUpdate != null) {
- projectBuilder.info("Cannot use Kotlin from $workIdeaHome: $reasonToUpdate")
- return false
- }
-
- ant.delete(dir: "$communityHome/build/kotlinc")
- ant.copy(todir: "$communityHome/build/kotlinc/plugin/Kotlin") {
- ant.fileset(dir: kotlinPluginFromWorkIdea)
- }
- ant.copy(todir: "$communityHome/build/kotlinc") {
- ant.fileset(dir: "$kotlinPluginFromWorkIdea/kotlinc")
- }
- ant.copy(todir: "$communityHome/build/kotlinc/jps") {
- ant.fileset(dir: "$kotlinPluginFromWorkIdea/lib/jps")
- }
- projectBuilder.info("Kotlin plugin updated from $workIdeaHome installation")
- return true
-}
-
-private String getReasonToUpdate(String communityHome, File kotlinPluginHome, String classVersionOfCompiledClasses) {
- def kotlincHome = new File(kotlinPluginHome, "kotlinc")
- def buildTxt = new File(kotlincHome, "build.txt")
- if (!buildTxt.exists()) {
- return "Kotlin binaries aren't found at $kotlincHome"
- }
-
- if (classVersionOfCompiledClasses != null) {
- def currentKotlinClassVersion = detectKotlinClassVersionForKotlinDist(kotlincHome)
- if (currentKotlinClassVersion == null) {
- projectBuilder.info("Cannot detect Kotlin class file version for $kotlincHome, class file versions compatibility won't be checked")
- }
- else if (VersionComparatorUtil.compare(currentKotlinClassVersion, classVersionOfCompiledClasses) < 0) {
- return "Kotlin compiler produces class-files of version $currentKotlinClassVersion, but IDEA classes have version $classVersionOfCompiledClasses"
- }
- }
-
- String currentKotlinVersion
- try {
- currentKotlinVersion = buildTxt.text
- }
- catch (IOException e) {
- return "cannot read Kotlin version from $buildTxt.absolutePath: $e"
- }
-
- def externalDependenciesXml = new File(communityHome, ".idea/externalDependencies.xml")
- if (!externalDependenciesXml.exists()) {
- return "cannot read required Kotlin version from $externalDependenciesXml.absolutePath: the file doesn't exist"
- }
-
- def root = new XmlParser().parse(externalDependenciesXml)
- def pluginTag = root.component?.find { it.@name == "ExternalDependencies" }?.plugin?.find { it.@id == "org.jetbrains.kotlin" }
- if (pluginTag == null) return "cannot find Kotlin plugin in $externalDependenciesXml.absolutePath"
-
- String minVersion = pluginTag['@min-version']
- if (minVersion == null) return "minimum required version for Kotlin plugin isn't specified in $externalDependenciesXml.absolutePath"
- String maxVersion = pluginTag['@max-version']
- if (maxVersion == null) return "maximum required version for Kotlin plugin isn't specified in $externalDependenciesXml.absolutePath"
-
- if (VersionComparatorUtil.compare(currentKotlinVersion, minVersion) < 0) {
- return "Kotlin version is $currentKotlinVersion, but at least $minVersion is required";
- }
- if (VersionComparatorUtil.compare(currentKotlinVersion, maxVersion) > 0) {
- return "Kotlin version is $currentKotlinVersion, but at most $maxVersion is required";
- }
-
- String ideVersion
- def ideVersionFile = new File(communityHome, "build.txt")
- try {
- ideVersion = ideVersionFile.text
- }
- catch (IOException e) {
- return "cannot read IDE version from $ideVersionFile: $e"
- }
- def pluginJar = new File(kotlinPluginHome, "lib/kotlin-plugin.jar")
- String pluginUntilBuild
- try {
- def jarFile = new JarFile(pluginJar)
- try {
- def pluginXmlEntry = jarFile.getEntry("META-INF/plugin.xml")
- if (pluginXmlEntry == null) {
- return "cannot check Kotlin plugin compatibility (META-INF/plugin.xml not found in $pluginJar)"
- }
- def pluginXml = new XmlParser().parse(jarFile.getInputStream(pluginXmlEntry))
- pluginUntilBuild = pluginXml."idea-version"?.first()?."@until-build"
- if (pluginUntilBuild != null) {
- String ideVersionBaseLine = StringUtil.substringBefore(ideVersion, ".")
- String pluginUntilBuildBaseLine = StringUtil.substringBefore(pluginUntilBuild, ".")
- if (ideVersionBaseLine > pluginUntilBuildBaseLine) {
- return "Kotlin plugin isn't compatible with $ideVersion (its 'until-build' is $pluginUntilBuild)"
- }
- }
- }
- finally {
- jarFile.close()
- }
- }
- catch (Exception e) {
- return "cannot check Kotlin plugin compatibility: $e"
- }
- return null
-}
-
-private String detectKotlinClassVersionForKotlinDist(File kotlincHome) {
- def kotlinRuntimeFile = new File(kotlincHome, "lib/kotlin-runtime.jar")
- def kotlinRuntimeJar = new JarFile(kotlinRuntimeFile)
- try {
- try {
- def unitClassPath = "kotlin/Unit.class"
- def entry = kotlinRuntimeJar.getJarEntry(unitClassPath)
- if (entry == null) {
- projectBuilder.warning("Cannot find $unitClassPath in $kotlinRuntimeJar")
- return null
- }
- return readKotlinClassFileVersion(kotlinRuntimeJar.getInputStream(entry))
- }
- finally {
- kotlinRuntimeJar.close()
- }
- }
- catch (IOException e) {
- projectBuilder.warning("Cannot detect Kotlin class file version for Kotlin distribution: $e")
- return null
- }
-}
-
-
-private String readKotlinClassVersionOfCompiledClasses() {
- if (!isDefined("modulesOutput")) return null
-
- def kotlinClassFile = new File("$modulesOutput/production/execution-impl/com/intellij/execution/ui/DefaultJreSelector.class")
- if (!kotlinClassFile.exists()) {
- projectBuilder.warning("Cannot detect Kotlin class file version of IDEA classes: $kotlinClassFile doesn't exist")
- return null
- }
-
- try {
- return kotlinClassFile.withInputStream { readKotlinClassFileVersion(it) }
- }
- catch (IOException e) {
- projectBuilder.warning("Cannot detect Kotlin class file version of IDEA classes: $e")
- return null
- }
-}
-
-private static String readKotlinClassFileVersion(InputStream classFileStream) {
- def reader = new ClassReader(classFileStream)
- String kotlinBytecodeVersion = null
- String kotlinMetaDataVersion = null
- reader.accept(new ClassVisitor(Opcodes.ASM5) {
- AnnotationVisitor visitAnnotation(String annotationName, boolean b) {
- if (annotationName == "Lkotlin/jvm/internal/KotlinClass;") {
- return new AnnotationVisitor(Opcodes.ASM5) {
- void visit(String name, Object value) {
- if (name == "version") {
- kotlinBytecodeVersion = (value as Integer[]).join(".")
- }
- }
- }
- }
- else if (annotationName == "Lkotlin/Metadata;") {
- return new AnnotationVisitor(Opcodes.ASM5) {
- void visit(String name, Object value) {
- if (name == "mv") {
- //strip patch number of metadata version because changes in patch updates are forward and backward compatible
- kotlinMetaDataVersion = (value as Integer[]).toList().dropRight(1).join(".")
- }
- else if (name == "bv") {
- kotlinBytecodeVersion = (value as Integer[]).join(".")
- }
- }
- }
- }
- return null
- }
- }, 0)
- if (kotlinBytecodeVersion != null && kotlinMetaDataVersion != null) {
- kotlinBytecodeVersion = kotlinBytecodeVersion + "." + kotlinMetaDataVersion
- }
- return kotlinBytecodeVersion
-}
-
-private boolean downloadAndExtract(TeamCityBuildLocator buildLocator, String communityHome, String classVersionOfCompiledClasses) {
- String buildNumber;
- try {
- buildNumber = new URL(buildLocator.buildNumberUrl).text
- }
- catch (Exception e) {
- projectBuilder.info("Cannot get Kotlin build number from $buildLocator.buildNumberUrl: $e")
- return false
- }
-
-
- def pluginZip = new File(communityHome, "build/kotlin-plugin-${buildNumber}.zip")
- def pluginZipPath = pluginZip.absolutePath
- if (!pluginZip.exists()) {
- ant.delete(dir: "$communityHome/build", includes: "kotlin-plugin-*.zip")
- projectBuilder.info("Downloading Kotlin build $buildNumber")
- ant.get(src: buildLocator.getDownloadUrl(buildNumber), dest: pluginZipPath)
- }
- else {
- projectBuilder.info("Extracting Kotlin build $buildNumber")
- }
-
- def kotlincDir = "$communityHome/build/kotlinc"
- ant.delete(dir: kotlincDir)
- ant.unzip(src: pluginZipPath, dest: "$kotlincDir/plugin")
- ant.unzip(src: pluginZipPath, dest: "$kotlincDir") {
- ant.patternset(includes: "Kotlin/kotlinc/**")
- ant.globmapper(from: "Kotlin/kotlinc/*", to: "*")
- }
- ant.unzip(src: pluginZipPath, dest: "$kotlincDir/jps") {
- ant.patternset(includes: "Kotlin/lib/jps/**")
- ant.globmapper(from: "Kotlin/lib/jps/*", to: "*")
- }
- def reasonToUpdate = getReasonToUpdate(communityHome, new File(kotlincDir, "plugin/Kotlin"), classVersionOfCompiledClasses)
- if (reasonToUpdate != null) {
- projectBuilder.warning("Cannot use the downloaded Kotlin plugin: $reasonToUpdate")
- }
- return true
-}
-
-class TeamCityBuildLocator {
- String host;
- String buildTypeId;
- String buildSelector;
-
- TeamCityBuildLocator(String host, String buildTypeId, String buildSelector) {
- this.host = host
- this.buildTypeId = buildTypeId
- this.buildSelector = buildSelector
- }
-
- String getBuildNumberUrl() {
- return "$host/guestAuth/app/rest/buildTypes/id:$buildTypeId/builds/$buildSelector,count:1/number"
- }
-
- String getDownloadUrl(String buildNumber) {
- String encodedBuildNumber = URLEncoder.encode(buildNumber, "UTF-8")
- int index = encodedBuildNumber.lastIndexOf('-')
- String releaseBuildNumber = encodedBuildNumber.substring(0, index)
- return "$host/guestAuth/repository/download/$buildTypeId/$encodedBuildNumber/kotlin-plugin-$releaseBuildNumber-IJ2017.1-1.zip"
- }
-}
diff --git a/build/scripts/unpackJdks.gant b/build/scripts/unpackJdks.gant
deleted file mode 100644
index d938fcc6b960..000000000000
--- a/build/scripts/unpackJdks.gant
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2000-2017 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.
- */
-import org.apache.tools.ant.BuildException
-
-target(default: "Unpack JDKs") {
- def workingDirectory = getDependenciesProjectDir()
- def gradleScript = System.getProperty('os.name').toLowerCase().contains('windows') ? "gradlew.bat" : "gradlew"
- def process = new ProcessBuilder("${workingDirectory.absolutePath}/$gradleScript", 'setupJdks', '--stacktrace', '--info')
- .directory(workingDirectory)
- .start()
- process.consumeProcessOutputStream((OutputStream)System.out)
- process.consumeProcessErrorStream((OutputStream)System.err)
- process.waitFor()
- if (process.exitValue() != 0) {
- throw new BuildException("Cannot unpack JDK")
- }
-}
-
-private File getDependenciesProjectDir() {
- String home = guessHome(this)
- File community = new File(home, 'community')
- return new File(community.exists() ? community : new File(home), "build/dependencies")
-}
-
-static String guessHome(Script script) {
- File home = new File(script["gant.file"].substring("file:".length()))
-
- while (home != null) {
- if (home.isDirectory()) {
- if (new File(home, ".idea").exists()) return home.getCanonicalPath()
- }
-
- home = home.getParentFile()
- }
-
- return null
-}
\ No newline at end of file
diff --git a/community-main.iml b/community-main.iml
index 8f57ec84e1cc..ba81bf74570e 100644
--- a/community-main.iml
+++ b/community-main.iml
@@ -123,5 +123,6 @@
+
\ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/codeinsight/JavaWithRuntimeCastSurrounder.java b/java/debugger/impl/src/com/intellij/debugger/codeinsight/JavaWithRuntimeCastSurrounder.java
index 730a0d7241bd..06312d385d56 100644
--- a/java/debugger/impl/src/com/intellij/debugger/codeinsight/JavaWithRuntimeCastSurrounder.java
+++ b/java/debugger/impl/src/com/intellij/debugger/codeinsight/JavaWithRuntimeCastSurrounder.java
@@ -28,7 +28,7 @@ import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.util.ProgressWindowWithNotification;
+import com.intellij.openapi.progress.util.ProgressWindow;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
@@ -63,7 +63,7 @@ public class JavaWithRuntimeCastSurrounder extends JavaExpressionSurrounder {
DebuggerContextImpl debuggerContext = (DebuggerManagerEx.getInstanceEx(project)).getContext();
DebuggerSession debuggerSession = debuggerContext.getDebuggerSession();
if (debuggerSession != null) {
- final ProgressWindowWithNotification progressWindow = new ProgressWindowWithNotification(true, expr.getProject());
+ final ProgressWindow progressWindow = new ProgressWindow(true, expr.getProject());
SurroundWithCastWorker worker = new SurroundWithCastWorker(editor, expr, debuggerContext, progressWindow);
progressWindow.setTitle(DebuggerBundle.message("title.evaluating"));
debuggerContext.getDebugProcess().getManagerThread().startProgress(worker, progressWindow);
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java
index 514f2622316a..55b308317020 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebuggerManagerThreadImpl.java
@@ -26,6 +26,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.util.ProgressIndicatorListenerAdapter;
+import com.intellij.openapi.progress.util.ProgressWindow;
import com.intellij.openapi.progress.util.ProgressWindowWithNotification;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
@@ -160,13 +161,18 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread ProgressManager.getInstance().runProcess(() -> invokeAndWait(command), progressWindow));
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java
index dc1cbdd76922..fd37398eed70 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValueModifier.java
@@ -27,7 +27,7 @@ import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
-import com.intellij.openapi.progress.util.ProgressWindowWithNotification;
+import com.intellij.openapi.progress.util.ProgressWindow;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
@@ -197,7 +197,7 @@ public abstract class JavaValueModifier extends XValueModifier {
}
protected void set(@NotNull final String expression, final XModificationCallback callback, final DebuggerContextImpl debuggerContext, final SetValueRunnable setValueRunnable) {
- final ProgressWindowWithNotification progressWindow = new ProgressWindowWithNotification(true, debuggerContext.getProject());
+ final ProgressWindow progressWindow = new ProgressWindow(true, debuggerContext.getProject());
final EvaluationContextImpl evaluationContext = myJavaValue.getEvaluationContext();
SuspendContextCommandImpl askSetAction = new DebuggerContextCommandImpl(debuggerContext) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java
index da776d39b2bf..4c9e8cb5a2d4 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/MethodBreakpoint.java
@@ -40,7 +40,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.util.ProgressWindowWithNotification;
+import com.intellij.openapi.progress.util.ProgressWindow;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
@@ -135,15 +135,15 @@ public class MethodBreakpoint extends BreakpointWithHighlighter indicatorRef = new AtomicReference<>();
+ AtomicReference indicatorRef = new AtomicReference<>();
ApplicationManager.getApplication().invokeAndWait(
() -> {
- ProgressWindowWithNotification progress =
- new ProgressWindowWithNotification(true, false, debugProcess.getProject(), "Cancel emulation");
+ ProgressWindow progress =
+ new ProgressWindow(true, false, debugProcess.getProject(), "Cancel emulation");
progress.setDelayInMillis(2000);
indicatorRef.set(progress);
});
- ProgressWindowWithNotification indicator = indicatorRef.get();
+ ProgressWindow indicator = indicatorRef.get();
AtomicBoolean changed = new AtomicBoolean();
XBreakpointListener> listener = new XBreakpointListener>() {
diff --git a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java
index 59149f132d9d..a89bc6392904 100644
--- a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java
+++ b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java
@@ -291,6 +291,9 @@ public abstract class QuickFixFactory {
@NotNull
public abstract IntentionAction createInsertMethodCallFix(@NotNull PsiMethodCallExpression call, PsiMethod method);
+ @NotNull
+ public abstract LocalQuickFixAndIntentionActionOnPsiElement createAccessStaticViaInstanceFix(PsiReferenceExpression methodRef, JavaResolveResult result);
+
@NotNull
public abstract IntentionAction createWrapStringWithFileFix(@Nullable PsiType type, @NotNull PsiExpression expression);
}
\ No newline at end of file
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
index 7e9e22850c1e..654dedd48022 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
@@ -390,6 +390,7 @@ public class HighlightMethodUtil {
if (highlightInfo != null) {
registerMethodCallIntentions(highlightInfo, methodCall, list, resolveHelper);
registerMethodReturnFixAction(highlightInfo, (MethodCandidateInfo)resolveResult, methodCall);
+ registerTargetTypeFixesBasedOnApplicabilityInference(methodCall, (MethodCandidateInfo)resolveResult, (PsiMethod)resolved, highlightInfo);
}
}
}
@@ -430,6 +431,7 @@ public class HighlightMethodUtil {
if (highlightInfo != null) {
registerMethodCallIntentions(highlightInfo, methodCall, list, resolveHelper);
registerMethodReturnFixAction(highlightInfo, candidateInfo, methodCall);
+ registerTargetTypeFixesBasedOnApplicabilityInference(methodCall, candidateInfo, resolvedMethod, highlightInfo);
}
}
else {
@@ -472,6 +474,36 @@ public class HighlightMethodUtil {
return highlightInfo;
}
+ private static void registerTargetTypeFixesBasedOnApplicabilityInference(@NotNull PsiMethodCallExpression methodCall,
+ MethodCandidateInfo resolveResult,
+ PsiMethod resolved,
+ HighlightInfo highlightInfo) {
+ PsiElement parent = PsiUtil.skipParenthesizedExprUp(methodCall.getParent());
+ PsiVariable variable = null;
+ if (parent instanceof PsiVariable) {
+ variable = (PsiVariable)parent;
+ }
+ else if (parent instanceof PsiAssignmentExpression) {
+ PsiExpression lExpression = ((PsiAssignmentExpression)parent).getLExpression();
+ if (lExpression instanceof PsiReferenceExpression) {
+ PsiElement resolve = ((PsiReferenceExpression)lExpression).resolve();
+ if (resolve instanceof PsiVariable) {
+ variable = (PsiVariable)resolve;
+ }
+ }
+ }
+
+ if (variable != null) {
+ PsiType rType = methodCall.getType();
+ if (rType != null && !variable.getType().isAssignableFrom(rType)) {
+ PsiType expectedTypeByApplicabilityConstraints = resolveResult.getSubstitutor(false).substitute(resolved.getReturnType());
+ if (expectedTypeByApplicabilityConstraints != null && !expectedTypeByApplicabilityConstraints.equals(rType)) {
+ HighlightUtil.registerChangeVariableTypeFixes(variable, expectedTypeByApplicabilityConstraints, methodCall, highlightInfo);
+ }
+ }
+ }
+ }
+
/* see also PsiReferenceExpressionImpl.hasValidQualifier() */
@Nullable
private static String checkStaticInterfaceMethodCallQualifier(PsiReferenceExpression ref, PsiElement scope, PsiClass containingClass) {
@@ -625,33 +657,32 @@ public class HighlightMethodUtil {
return null;
}
String description;
- PsiElement elementToHighlight;
+ PsiElement elementToHighlight = ObjectUtils.notNull(referenceToMethod.getReferenceNameElement(), referenceToMethod);
if (element != null && !resolveResult.isAccessible()) {
description = HighlightUtil.buildProblemWithAccessDescription(referenceToMethod, resolveResult);
- elementToHighlight = referenceToMethod.getReferenceNameElement();
}
else if (element != null && !resolveResult.isStaticsScopeCorrect()) {
- description = null;
- elementToHighlight = ObjectUtils.notNull(referenceToMethod.getReferenceNameElement(), referenceToMethod);
-
if (element instanceof PsiMethod && ((PsiMethod)element).hasModifierProperty(PsiModifier.STATIC)) {
PsiClass containingClass = ((PsiMethod)element).getContainingClass();
if (containingClass != null && containingClass.isInterface()) {
HighlightInfo info = HighlightUtil.checkFeature(elementToHighlight, HighlightUtil.Feature.STATIC_INTERFACE_CALLS, languageLevel, file);
if (info != null) return info;
description = checkStaticInterfaceMethodCallQualifier(referenceToMethod, resolveResult.getCurrentFileResolveScope(), containingClass);
+ if (description != null) {
+ HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(highlightInfoType).range(elementToHighlight).description(description)
+ .escapedToolTip(XmlStringUtil.escapeString(description)).create();
+ QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createAccessStaticViaInstanceFix(referenceToMethod, resolveResult));
+ return highlightInfo;
+ }
}
}
- if (description == null) {
- description = HighlightUtil.buildProblemWithStaticDescription(element);
- }
+ description = HighlightUtil.buildProblemWithStaticDescription(element);
}
else {
String methodName = referenceToMethod.getReferenceName() + buildArgTypesList(list);
description = JavaErrorMessages.message("cannot.resolve.method", methodName);
if (candidates.length == 0) {
- elementToHighlight = referenceToMethod.getReferenceNameElement();
highlightInfoType = HighlightInfoType.WRONG_REF;
}
else {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
index 467f71c2a18d..6aeb04a5bbf9 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
@@ -200,6 +200,7 @@ public class HighlightUtil extends HighlightUtilBase {
/**
* make element protected/package-private/public suggestion
+ * for private method in the interface it should add default modifier as well
*/
static void registerAccessQuickFixAction(@NotNull PsiMember refElement,
@NotNull PsiJavaCodeReferenceElement place,
@@ -238,6 +239,10 @@ public class HighlightUtil extends HighlightUtilBase {
if (refElement.hasModifierProperty(PsiModifier.PROTECTED)) {
minModifier = PsiModifier.PUBLIC;
}
+ PsiClass containingClass = refElement.getContainingClass();
+ if (containingClass != null && containingClass.isInterface()) {
+ minModifier = PsiModifier.PUBLIC;
+ }
String[] modifiers = {PsiModifier.PACKAGE_LOCAL, PsiModifier.PROTECTED, PsiModifier.PUBLIC,};
for (int i = ArrayUtil.indexOf(modifiers, minModifier); i < modifiers.length; i++) {
@PsiModifier.ModifierConstant String modifier = modifiers[i];
@@ -967,7 +972,7 @@ public class HighlightUtil extends HighlightUtilBase {
if (PsiModifier.PRIVATE.equals(modifier)) {
isAllowed &= modifierOwnerParent instanceof PsiClass &&
- (!((PsiClass)modifierOwnerParent).isInterface() || PsiUtil.isLanguageLevel9OrHigher(modifierOwner));
+ (!((PsiClass)modifierOwnerParent).isInterface() || PsiUtil.isLanguageLevel9OrHigher(modifierOwner) && !((PsiClass)modifierOwnerParent).isAnnotationType());
}
else if (PsiModifier.STRICTFP.equals(modifier)) {
isAllowed &= modifierOwnerParent instanceof PsiClass && (!((PsiClass)modifierOwnerParent).isInterface() || PsiUtil.isLanguageLevel8OrHigher(modifierOwner));
@@ -1793,13 +1798,7 @@ public class HighlightUtil extends HighlightUtilBase {
PsiModifierList modifierList = variable.getModifierList();
if (modifierList != null && modifierList.hasModifierProperty(PsiModifier.FINAL)) return null;
- PsiElement scope = null;
- if (variable instanceof PsiParameter) scope = ((PsiParameter)variable).getDeclarationScope();
- else if (variable instanceof PsiResourceVariable) scope = variable.getParent().getParent();
- else if (variable instanceof PsiLocalVariable) scope = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class);
- if (scope != null) {
- if (HighlightControlFlowUtil.isEffectivelyFinal(variable, scope, null)) return null;
- }
+ if (!(variable instanceof PsiField) && HighlightControlFlowUtil.isEffectivelyFinal(variable, resource, (PsiJavaCodeReferenceElement)expression)) return null;
}
String text = JavaErrorMessages.message("resource.variable.must.be.final");
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/EmptyQuickFixFactory.java b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/EmptyQuickFixFactory.java
index 7fe3c51a17c5..b3544def540e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/intention/EmptyQuickFixFactory.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/intention/EmptyQuickFixFactory.java
@@ -669,6 +669,13 @@ public class EmptyQuickFixFactory extends QuickFixFactory {
return QuickFixes.EMPTY_FIX;
}
+ @NotNull
+ @Override
+ public LocalQuickFixAndIntentionActionOnPsiElement createAccessStaticViaInstanceFix(PsiReferenceExpression methodRef,
+ JavaResolveResult result) {
+ return QuickFixes.EMPTY_FIX;
+ }
+
@NotNull
@Override
public IntentionAction createWrapStringWithFileFix(@Nullable PsiType type, @NotNull PsiExpression expression) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/accessStaticViaInstance/AccessStaticViaInstanceBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/accessStaticViaInstance/AccessStaticViaInstanceBase.java
index 748bce25fc53..a1addd4f5ae4 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/accessStaticViaInstance/AccessStaticViaInstanceBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/accessStaticViaInstance/AccessStaticViaInstanceBase.java
@@ -84,6 +84,10 @@ public class AccessStaticViaInstanceBase extends BaseJavaBatchLocalInspectionToo
}
if (!((PsiMember)resolved).hasModifierProperty(PsiModifier.STATIC)) return;
+ //don't report warnings on compilation errors
+ PsiClass containingClass = ((PsiMember)resolved).getContainingClass();
+ if (containingClass != null && containingClass.isInterface()) return;
+
String description = JavaErrorMessages.message("static.member.accessed.via.instance.reference",
JavaHighlightUtil.formatType(qualifierExpression.getType()),
HighlightMessageUtil.getSymbolName(resolved, result.getSubstitutor()));
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavadocHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavadocHighlightUtil.java
index 90d0d9c261c7..ee93d1e8e5de 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavadocHighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavadocHighlightUtil.java
@@ -46,6 +46,7 @@ public class JavadocHighlightUtil {
private static final TokenSet SEE_TAG_REFS = TokenSet.create(
JavaDocElementType.DOC_REFERENCE_HOLDER, JavaDocElementType.DOC_METHOD_OR_FIELD_REF);
+ @SuppressWarnings("SameParameterValue")
public interface ProblemHolder {
Project project();
JavaDocLocalInspectionBase inspection();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspectionBase.java
index 7a0ade4c627a..153d4b35cca0 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspectionBase.java
@@ -25,6 +25,7 @@ import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.intellij.util.ObjectUtils;
+import com.intellij.util.VisibilityUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,6 +36,11 @@ import java.util.List;
* @author max
*/
public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionTool {
+ @PsiModifier.ModifierConstant
+ private static final String DEFAULT_HIGHEST_MODIFIER = PsiModifier.PROTECTED;
+ @PsiModifier.ModifierConstant
+ public String highestModifier = DEFAULT_HIGHEST_MODIFIER;
+
@Override
@Nullable
public CommonProblemDescriptor[] checkElement(@NotNull RefEntity refEntity,
@@ -46,9 +52,9 @@ public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionT
if (refEntity instanceof RefMethod) {
final RefMethod refMethod = (RefMethod)refEntity;
- if (refMethod.hasSuperMethods()) return null;
-
- if (refMethod.isEntry()) return null;
+ if (refMethod.hasSuperMethods() ||
+ VisibilityUtil.compare(refMethod.getAccessModifier(), highestModifier) < 0 ||
+ refMethod.isEntry()) return null;
RefParameter[] parameters = refMethod.getParameters();
for (RefParameter refParameter : parameters) {
@@ -176,7 +182,7 @@ public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionT
@Override
public void visitMethod(PsiMethod method) {
- if (method.isConstructor()) return;
+ if (method.isConstructor() || VisibilityUtil.compare(VisibilityUtil.getVisibilityModifier(method.getModifierList()), highestModifier) < 0) return;
PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length == 0) return;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AccessStaticViaInstanceFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AccessStaticViaInstanceFix.java
index d41e92b9522c..78b9445ec247 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AccessStaticViaInstanceFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AccessStaticViaInstanceFix.java
@@ -96,7 +96,7 @@ public class AccessStaticViaInstanceFix extends LocalQuickFixAndIntentionActionO
try {
PsiElement newQualifier = qualifierExpression.replace(factory.createReferenceExpression(containingClass));
PsiElement qualifiedWithClassName = myExpression.copy();
- if (myExpression.getTypeParameters().length == 0) {
+ if (myExpression.getTypeParameters().length == 0 && !(containingClass.isInterface() && !containingClass.equals(PsiTreeUtil.getParentOfType(myExpression, PsiClass.class)))) {
newQualifier.delete();
if (myExpression.resolve() != myMember) {
myExpression.replace(qualifiedWithClassName);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
index 3f3948ce123c..068000712f53 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
@@ -200,11 +200,21 @@ public class ModifierFix extends LocalQuickFixAndIntentionActionOnPsiElement {
ApplicationManager.getApplication().runWriteAction(() -> {
changeModifierList(modifierList);
- if (myShouldHave && owner instanceof PsiMethod && PsiModifier.ABSTRACT.equals(myModifier)) {
- final PsiMethod method = (PsiMethod)owner;
- final PsiClass aClass = method.getContainingClass();
- if (aClass != null && !aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
- changeModifierList(aClass.getModifierList());
+ if (myShouldHave && owner instanceof PsiMethod) {
+ if (PsiModifier.ABSTRACT.equals(myModifier)) {
+ final PsiMethod method = (PsiMethod)owner;
+ final PsiClass aClass = method.getContainingClass();
+ if (aClass != null && !aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
+ changeModifierList(aClass.getModifierList());
+ }
+ }
+ else if (PsiModifier.PUBLIC.equals(myModifier) &&
+ ((PsiMethod)owner).getBody() != null &&
+ !((PsiMethod)owner).hasModifierProperty(PsiModifier.STATIC)) {
+ PsiClass containingClass = ((PsiMethod)owner).getContainingClass();
+ if (containingClass != null && containingClass.isInterface()) {
+ modifierList.setModifierProperty(PsiModifier.DEFAULT, true);
+ }
}
}
UndoUtil.markPsiFileForUndo(containingFile);
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java
index 93ec1bfd0293..50992a935694 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java
@@ -851,6 +851,13 @@ public class QuickFixFactoryImpl extends QuickFixFactory {
return new InsertMethodCallFix(call, method);
}
+ @NotNull
+ @Override
+ public LocalQuickFixAndIntentionActionOnPsiElement createAccessStaticViaInstanceFix(PsiReferenceExpression methodRef,
+ JavaResolveResult result) {
+ return new AccessStaticViaInstanceFix(methodRef, result, true);
+ }
+
@NotNull
@Override
public IntentionAction createWrapStringWithFileFix(@Nullable PsiType type, @NotNull PsiExpression expression) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
index ed9b38668a05..0643e66efe0a 100644
--- a/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/sameParameterValue/SameParameterValueInspection.java
@@ -18,9 +18,11 @@ package com.intellij.codeInspection.sameParameterValue;
import com.intellij.codeInspection.InspectionsBundle;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.unusedSymbol.VisibilityModifierChooser;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -35,8 +37,12 @@ import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.InlineUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.MultiMap;
+import com.intellij.util.ui.JBUI;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import javax.swing.*;
+import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -45,7 +51,22 @@ import java.util.List;
* @author max
*/
public class SameParameterValueInspection extends SameParameterValueInspectionBase {
- private static final Logger LOG = Logger.getInstance("#" + SameParameterValueInspectionBase.class.getName());
+ private static final Logger LOG = Logger.getInstance(SameParameterValueInspectionBase.class);
+
+ @Nullable
+ @Override
+ public JComponent createOptionsPanel() {
+ LabeledComponent component = LabeledComponent.create(new VisibilityModifierChooser(() -> true,
+ highestModifier,
+ (newModifier) -> highestModifier = newModifier),
+ "Methods to report:",
+ BorderLayout.WEST);
+
+ JPanel panel = new JPanel(new GridBagLayout());
+ panel.add(component, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.FIRST_LINE_START, GridBagConstraints.NORTHEAST, JBUI.emptyInsets(), 0, 0));
+ return panel;
+ }
+
protected LocalQuickFix createFix(String paramName, String value) {
return new InlineParameterValueFix(paramName, value);
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/OptionsPanel.form b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/OptionsPanel.form
index 5b3cac3661f2..ba373af3f2e4 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/OptionsPanel.form
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/OptionsPanel.form
@@ -3,7 +3,7 @@
-
+
@@ -54,9 +54,7 @@
-
-
-
+
@@ -83,9 +81,7 @@
-
-
-
+
@@ -110,9 +106,7 @@
-
-
-
+
@@ -139,9 +133,7 @@
-
-
-
+
@@ -168,18 +160,14 @@
-
-
-
+
-
-
-
+
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
index 83385f4687cb..f4d2557abaff 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
@@ -16,37 +16,13 @@
package com.intellij.codeInspection.unusedSymbol;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.ui.popup.JBPopup;
-import com.intellij.openapi.ui.popup.JBPopupAdapter;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.ui.popup.LightweightWindowEvent;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiModifier;
-import com.intellij.ui.ClickListener;
-import com.intellij.ui.UI;
-import com.intellij.ui.UserActivityProviderComponent;
-import com.intellij.ui.awt.RelativePoint;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.Consumer;
-import com.intellij.util.Producer;
-import com.intellij.util.VisibilityUtil;
-import com.intellij.util.containers.HashSet;
-import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.awt.event.MouseEvent;
-import java.util.Hashtable;
-import java.util.Set;
-import java.util.function.Supplier;
/**
* User: anna
@@ -107,13 +83,7 @@ public class UnusedSymbolLocalInspection extends UnusedSymbolLocalInspectionBase
myCheckParametersCheckBox.addActionListener(listener);
myInnerClassesCheckBox.addActionListener(listener);
myAccessors.addActionListener(listener);
-
- ((MyLabel)myClassVisibilityCb).setupVisibilityLabel(() -> myClassVisibility, modifier -> setClassVisibility(modifier), new String[]{PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC});
- ((MyLabel)myInnerClassVisibilityCb).setupVisibilityLabel(() -> myInnerClassVisibility, modifier -> setInnerClassVisibility(modifier));
- ((MyLabel)myFieldVisibilityCb).setupVisibilityLabel(() -> myFieldVisibility, modifier -> setFieldVisibility(modifier));
- ((MyLabel)myMethodVisibilityCb).setupVisibilityLabel(() -> myMethodVisibility, modifier -> setMethodVisibility(modifier));
- ((MyLabel)myMethodParameterVisibilityCb).setupVisibilityLabel(() -> myParameterVisibility, modifier -> setParameterVisibility(modifier));
- }
+ }
private void updateEnableState() {
UIUtil.setEnabled(myClassVisibilityCb, CLASS, true);
@@ -129,11 +99,27 @@ public class UnusedSymbolLocalInspection extends UnusedSymbolLocalInspectionBase
}
private void createUIComponents() {
- myClassVisibilityCb = new MyLabel(() -> CLASS);
- myInnerClassVisibilityCb = new MyLabel(() -> INNER_CLASS);
- myFieldVisibilityCb = new MyLabel(() -> FIELD);
- myMethodVisibilityCb = new MyLabel(() -> METHOD);
- myMethodParameterVisibilityCb = new MyLabel(() -> PARAMETER);
+ myClassVisibilityCb = new VisibilityModifierChooser(() -> CLASS,
+ myClassVisibility,
+ modifier -> setClassVisibility(modifier),
+ new String[]{PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC});
+
+ myInnerClassVisibilityCb = new VisibilityModifierChooser(() -> INNER_CLASS,
+ myInnerClassVisibility,
+ modifier -> setInnerClassVisibility(modifier));
+
+ myFieldVisibilityCb = new VisibilityModifierChooser(() -> FIELD,
+ myFieldVisibility,
+ modifier -> setFieldVisibility(modifier));
+
+ myMethodVisibilityCb = new VisibilityModifierChooser(() -> METHOD,
+ myMethodVisibility,
+ modifier -> setMethodVisibility(modifier));
+
+ myMethodParameterVisibilityCb = new VisibilityModifierChooser(() -> PARAMETER,
+ myParameterVisibility,
+ modifier -> setParameterVisibility(modifier));
+
myAccessors = new JCheckBox() {
@Override
public void setEnabled(boolean b) {
@@ -143,94 +129,6 @@ public class UnusedSymbolLocalInspection extends UnusedSymbolLocalInspectionBase
}
}
- private static class MyLabel extends JLabel implements UserActivityProviderComponent {
-
- @PsiModifier.ModifierConstant private static final String[] MODIFIERS =
- new String[]{PsiModifier.PRIVATE, PsiModifier.PACKAGE_LOCAL, PsiModifier.PROTECTED, PsiModifier.PUBLIC};
- private final Supplier myCanBeEnabled;
-
- private Set myListeners = new HashSet<>();
-
- public MyLabel(Supplier canBeEnabled) {
- myCanBeEnabled = canBeEnabled;
- setIcon(AllIcons.General.Combo2);
- setDisabledIcon(AllIcons.General.Combo2);
- setIconTextGap(0);
- setHorizontalTextPosition(SwingConstants.LEFT);
- }
-
- private void fireStateChanged() {
- for (ChangeListener listener : myListeners) {
- listener.stateChanged(new ChangeEvent(this));
- }
- }
-
- private static String getPresentableText(String modifier) {
- return StringUtil.capitalize(VisibilityUtil.toPresentableText(modifier));
- }
-
- private void setupVisibilityLabel(Producer visibilityProducer, Consumer setter) {
- setupVisibilityLabel(visibilityProducer, setter, MODIFIERS);
- }
-
- private void setupVisibilityLabel(Producer visibilityProducer, Consumer setter, final String[] modifiers) {
- setText(getPresentableText(visibilityProducer.produce()));
- new ClickListener() {
- @Override
- public boolean onClick(@NotNull MouseEvent e, int clickCount) {
- if (!isEnabled()) return true;
- @SuppressWarnings("UseOfObsoleteCollectionType")
- Hashtable sliderLabels = new Hashtable<>();
- for (int i = 0; i < modifiers.length; i++) {
- sliderLabels.put(i + 1, new JLabel(getPresentableText(modifiers[i])));
- }
-
- JSlider slider = new JSlider(SwingConstants.VERTICAL, 1, modifiers.length, 1);
- slider.addChangeListener(val -> {
- final String modifier = modifiers[slider.getValue() - 1];
- setter.consume(modifier);
- setText(getPresentableText(modifier));
- fireStateChanged();
- });
- slider.setLabelTable(sliderLabels);
- slider.putClientProperty(UIUtil.JSLIDER_ISFILLED, Boolean.TRUE);
- slider.setPreferredSize(JBUI.size(150, modifiers.length * 25));
- slider.setPaintLabels(true);
- slider.setSnapToTicks(true);
- slider.setValue(ArrayUtil.find(modifiers, visibilityProducer.produce()) + 1);
- final JBPopup popup = JBPopupFactory.getInstance()
- .createComponentPopupBuilder(slider, null)
- .setTitle("Effective Visibility")
- .setCancelOnClickOutside(true)
- .setMovable(true)
- .createPopup();
- popup.show(new RelativePoint(MyLabel.this, new Point(getWidth(), 0)));
- return true;
- }
- }.installOn(this);
- }
-
- @Override
- public void setForeground(Color fg) {
- super.setForeground(isEnabled() ? UI.getColor("link.foreground") : fg);
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- super.setEnabled(enabled && myCanBeEnabled.get());
- }
-
- @Override
- public void addChangeListener(ChangeListener changeListener) {
- myListeners.add(changeListener);
- }
-
- @Override
- public void removeChangeListener(ChangeListener changeListener) {
- myListeners.remove(changeListener);
- }
- }
-
@Override
@Nullable
public JComponent createOptionsPanel() {
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/VisibilityModifierChooser.java b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/VisibilityModifierChooser.java
new file mode 100644
index 000000000000..b64097fe159a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/VisibilityModifierChooser.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInspection.unusedSymbol;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.ui.popup.JBPopup;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiModifier;
+import com.intellij.ui.ClickListener;
+import com.intellij.ui.UI;
+import com.intellij.ui.UserActivityProviderComponent;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Consumer;
+import com.intellij.util.VisibilityUtil;
+import com.intellij.util.containers.HashSet;
+import com.intellij.util.ui.JBUI;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.util.Hashtable;
+import java.util.Set;
+import java.util.function.Supplier;
+
+public class VisibilityModifierChooser extends JLabel implements UserActivityProviderComponent {
+
+ @PsiModifier.ModifierConstant private static final String[] MODIFIERS =
+ new String[]{PsiModifier.PRIVATE, PsiModifier.PACKAGE_LOCAL, PsiModifier.PROTECTED, PsiModifier.PUBLIC};
+ private final Supplier myCanBeEnabled;
+
+ private final Set myListeners = new HashSet<>();
+ private String myCurrentModifier;
+
+ public VisibilityModifierChooser(@NotNull Supplier canBeEnabled,
+ @NotNull String modifier,
+ @NotNull Consumer modifierChangedConsumer) {
+ this(canBeEnabled, modifier, modifierChangedConsumer, MODIFIERS);
+ }
+
+
+ @Override
+ public void setText(String text) {
+ super.setText(text);
+ }
+
+ public VisibilityModifierChooser(@NotNull Supplier canBeEnabled,
+ @NotNull String modifier,
+ @NotNull Consumer modifierChangedConsumer,
+ @NotNull String[] modifiers) {
+ myCanBeEnabled = canBeEnabled;
+ setIcon(AllIcons.General.Combo2);
+ setDisabledIcon(AllIcons.General.Combo2);
+ setIconTextGap(0);
+ setHorizontalTextPosition(SwingConstants.LEFT);
+ myCurrentModifier = modifier;
+ setText(getPresentableText(myCurrentModifier));
+ new ClickListener() {
+ @Override
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
+ if (!isEnabled()) return true;
+ @SuppressWarnings("UseOfObsoleteCollectionType")
+ Hashtable sliderLabels = new Hashtable<>();
+ for (int i = 0; i < modifiers.length; i++) {
+ sliderLabels.put(i + 1, new JLabel(getPresentableText(modifiers[i])));
+ }
+
+ JSlider slider = new JSlider(SwingConstants.VERTICAL, 1, modifiers.length, 1);
+ slider.addChangeListener(val -> {
+ final String modifier = modifiers[slider.getValue() - 1];
+ if (myCurrentModifier != modifier) {
+ myCurrentModifier = modifier;
+ modifierChangedConsumer.consume(modifier);
+ setText(getPresentableText(modifier));
+ fireStateChanged();
+ }
+ });
+ slider.setLabelTable(sliderLabels);
+ slider.putClientProperty(UIUtil.JSLIDER_ISFILLED, Boolean.TRUE);
+ slider.setPreferredSize(JBUI.size(150, modifiers.length * 25));
+ slider.setPaintLabels(true);
+ slider.setSnapToTicks(true);
+ slider.setValue(ArrayUtil.find(modifiers, myCurrentModifier) + 1);
+ final JBPopup popup = JBPopupFactory.getInstance()
+ .createComponentPopupBuilder(slider, null)
+ .setTitle("Effective Visibility")
+ .setCancelOnClickOutside(true)
+ .setMovable(true)
+ .createPopup();
+ popup.show(new RelativePoint(VisibilityModifierChooser.this, new Point(getWidth(), 0)));
+ return true;
+ }
+ }.installOn(this);
+ }
+
+ private void fireStateChanged() {
+ for (ChangeListener listener : myListeners) {
+ listener.stateChanged(new ChangeEvent(this));
+ }
+ }
+
+ private static String getPresentableText(String modifier) {
+ return StringUtil.capitalize(VisibilityUtil.toPresentableText(modifier));
+ }
+
+ @Override
+ public void setForeground(Color fg) {
+ super.setForeground(isEnabled() ? UI.getColor("link.foreground") : fg);
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled && myCanBeEnabled.get());
+ }
+
+ @Override
+ public void addChangeListener(ChangeListener changeListener) {
+ myListeners.add(changeListener);
+ }
+
+ @Override
+ public void removeChangeListener(ChangeListener changeListener) {
+ myListeners.remove(changeListener);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
index 483056038191..302bd6c5f96b 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java
@@ -1616,39 +1616,7 @@ public class ExtractMethodProcessor implements MatchProvider {
throws PrepareFailedException {
myStatic = shouldBeStatic();
final Set fields = new LinkedHashSet<>();
- if (!PsiUtil.isLocalOrAnonymousClass(myTargetClass) && (myTargetClass.getContainingClass() == null || myTargetClass.hasModifierProperty(PsiModifier.STATIC))) {
- boolean canBeStatic = true;
- if (myTargetClass.isInterface()) {
- final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(myCodeFragmentMember, PsiMethod.class, false);
- canBeStatic = containingMethod == null || containingMethod.hasModifierProperty(PsiModifier.STATIC);
- }
- if (canBeStatic) {
- ElementNeedsThis needsThis = new ElementNeedsThis(myTargetClass) {
- @Override
- protected void visitClassMemberReferenceElement(PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) {
- if (classMember instanceof PsiField && !classMember.hasModifierProperty(PsiModifier.STATIC)) {
- final PsiExpression expression = PsiTreeUtil.getParentOfType(classMemberReference, PsiExpression.class, false);
- if (expression == null || !PsiUtil.isAccessedForWriting(expression)) {
- fields.add((PsiField)classMember);
- return;
- }
- }
- super.visitClassMemberReferenceElement(classMember, classMemberReference);
- }
- };
- for (int i = 0; i < myElements.length && !needsThis.usesMembers(); i++) {
- PsiElement element = myElements[i];
- element.accept(needsThis);
- }
- myCanBeStatic = !needsThis.usesMembers();
- }
- else {
- myCanBeStatic = false;
- }
- }
- else {
- myCanBeStatic = false;
- }
+ myCanBeStatic = canBeStatic(myTargetClass, myCodeFragmentMember, myElements, fields);
myInputVariables = new InputVariables(inputVariables, myProject, new LocalSearchScope(myElements), isFoldingApplicable());
myInputVariables.setUsedInstanceFields(fields);
@@ -1665,6 +1633,37 @@ public class ExtractMethodProcessor implements MatchProvider {
return true;
}
+ public static boolean canBeStatic(final PsiClass targetClass, final PsiElement place, final PsiElement[] elements, Set usedFields) {
+ if (!PsiUtil.isLocalOrAnonymousClass(targetClass) && (targetClass.getContainingClass() == null || targetClass.hasModifierProperty(PsiModifier.STATIC))) {
+ boolean canBeStatic = true;
+ if (targetClass.isInterface()) {
+ final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(place, PsiMethod.class, false);
+ canBeStatic = containingMethod == null || containingMethod.hasModifierProperty(PsiModifier.STATIC);
+ }
+ if (canBeStatic) {
+ ElementNeedsThis needsThis = new ElementNeedsThis(targetClass) {
+ @Override
+ protected void visitClassMemberReferenceElement(PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) {
+ if (classMember instanceof PsiField && !classMember.hasModifierProperty(PsiModifier.STATIC)) {
+ final PsiExpression expression = PsiTreeUtil.getParentOfType(classMemberReference, PsiExpression.class, false);
+ if (expression == null || !PsiUtil.isAccessedForWriting(expression)) {
+ usedFields.add((PsiField)classMember);
+ return;
+ }
+ }
+ super.visitClassMemberReferenceElement(classMember, classMemberReference);
+ }
+ };
+ for (int i = 0; i < elements.length && !needsThis.usesMembers(); i++) {
+ PsiElement element = elements[i];
+ element.accept(needsThis);
+ }
+ return !needsThis.usesMembers();
+ }
+ }
+ return false;
+ }
+
protected boolean isFoldingApplicable() {
return true;
}
diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java
index c34722cafebd..96532f8c8076 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -61,6 +61,8 @@ import com.intellij.usageView.UsageViewUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.VisibilityUtil;
+import com.intellij.util.text.UniqueNameGenerator;
+import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -86,6 +88,8 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
private PsiClass myInnerClass;
private boolean myChangeReturnType;
private Runnable myCopyMethodToInner;
+ private final UniqueNameGenerator myFieldNameGenerator = new UniqueNameGenerator();
+ private String myResultFieldName = null;
private static final Key GENERATED_RETURN = new Key<>("GENERATED_RETURN");
@@ -163,8 +167,9 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
}
if (myExtractProcessor.generatesConditionalExit()) {
- myInnerClass.add(myElementFactory.createField("myResult", PsiPrimitiveType.BOOLEAN));
- myInnerClass.add(myElementFactory.createMethodFromText("boolean is(){return myResult;}", myInnerClass));
+ myResultFieldName = uniqueFieldName(new String[]{"myResult"});
+ myInnerClass.add(myElementFactory.createField(myResultFieldName, PsiType.BOOLEAN));
+ myInnerClass.add(myElementFactory.createMethodFromText("boolean is(){return " + myResultFieldName + ";}", myInnerClass));
}
final PsiParameter[] parameters = getMethod().getParameterList().getParameters();
@@ -285,7 +290,8 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
for (int i = 0; i < returnStatements.size() - 1; i++) {
final PsiReturnStatement condition = returnStatements.get(i);
final PsiElement container = condition.getParent();
- final PsiStatement resultStmt = myElementFactory.createStatementFromText("myResult = true;", container);
+ LOG.assertTrue(myResultFieldName != null);
+ final PsiStatement resultStmt = myElementFactory.createStatementFromText(myResultFieldName + " = true;", container);
if (!RefactoringUtil.isLoopOrIf(container)) {
container.addBefore(resultStmt, condition);
} else {
@@ -296,7 +302,8 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
LOG.assertTrue(!returnStatements.isEmpty());
final PsiReturnStatement returnStatement = returnStatements.get(returnStatements.size() - 1);
final PsiElement container = returnStatement.getParent();
- final PsiStatement resultStmt = myElementFactory.createStatementFromText("myResult = false;", container);
+ LOG.assertTrue(myResultFieldName != null);
+ final PsiStatement resultStmt = myElementFactory.createStatementFromText(myResultFieldName + " = false;", container);
if (!RefactoringUtil.isLoopOrIf(container)) {
container.addBefore(resultStmt, returnStatement);
} else {
@@ -332,15 +339,7 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
for (PsiVariable variable : outputVariables) {
PsiVariable var = (PsiVariable)declaredElement;
if (Comparing.strEqual(var.getName(), variable.getName())) {
- PsiExpression initializer = var.getInitializer();
- if (initializer == null) {
- replacementMap.put(var, null);
- }
- else {
- PsiStatement assignmentStatement = myElementFactory
- .createStatementFromText(var2FieldNames.get(variable.getName()) + " = " + initializer.getText() + ";", statement);
- replacementMap.put(var, assignmentStatement);
- }
+ replacementMap.put(var, var.getInitializer());
}
}
}
@@ -405,11 +404,14 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
}
}
else if (statement instanceof PsiLocalVariable) {
- PsiLocalVariable variable = (PsiLocalVariable)statement;
+ final PsiLocalVariable variable = (PsiLocalVariable)statement;
variable.normalizeDeclaration();
- PsiDeclarationStatement declaration = PsiTreeUtil.getParentOfType(statement, PsiDeclarationStatement.class);
+ final PsiExpression initializer = variable.getInitializer();
+ LOG.assertTrue(initializer != null);
+ final PsiStatement assignmentStatement = myElementFactory.createStatementFromText(var2FieldNames.get(variable.getName()) + " = " + initializer.getText() + ";", statement);
+ final PsiDeclarationStatement declaration = PsiTreeUtil.getParentOfType(statement, PsiDeclarationStatement.class);
LOG.assertTrue(declaration != null);
- declaration.replace(replacement);
+ declaration.replace(assignmentStatement);
}
else {
if (statement instanceof PsiReturnStatement) {
@@ -635,7 +637,8 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
if (type instanceof PsiEllipsisType) type = ((PsiEllipsisType)type).toArrayType();
try {
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(getMethod().getProject());
- final String fieldName = styleManager.suggestVariableName(VariableKind.FIELD, styleManager.variableNameToPropertyName(parameterName, VariableKind.PARAMETER), null, type).names[0];
+ String fieldName = uniqueFieldName(styleManager.suggestVariableName(
+ VariableKind.FIELD, styleManager.variableNameToPropertyName(parameterName, VariableKind.PARAMETER), null, type).names);
PsiField field = myElementFactory.createField(fieldName, type);
final PsiModifierList modifierList = field.getModifierList();
@@ -725,6 +728,15 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
return true;
}
+ private String uniqueFieldName(String[] candidates) {
+ String name = StreamEx.of(candidates).findFirst(myFieldNameGenerator::isUnique).orElse(null);
+ if (name == null) {
+ name = myFieldNameGenerator.generateUniqueName(candidates[0]);
+ }
+ myFieldNameGenerator.addExistingName(name);
+ return name;
+ }
+
public class MyExtractMethodProcessor extends ExtractMethodProcessor {
public MyExtractMethodProcessor(Project project,
@@ -767,9 +779,8 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor {
for (int i = 0; i < myOutputVariables.length; i++) {
PsiVariable variable = myOutputVariables[i];
if (!myInputVariables.contains(variable)) { //one field creation
- final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(myProject);
- final String fieldName =
- styleManager.suggestVariableName(VariableKind.FIELD, getPureName(variable), null, variable.getType()).names[0];
+ String fieldName = uniqueFieldName(JavaCodeStyleManager.getInstance(myProject)
+ .suggestVariableName(VariableKind.FIELD, getPureName(variable), null, variable.getType()).names);
try {
myOutputFields[i] = myElementFactory.createField(fieldName, variable.getType());
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java
index 27b21d3ac3b5..5a1b21416507 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java
@@ -17,7 +17,6 @@ package com.intellij.psi.impl.source;
import com.intellij.codeInsight.AnnotationTargetUtil;
import com.intellij.lang.ASTNode;
-import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.intellij.psi.augment.PsiAugmentProvider;
import com.intellij.psi.impl.CheckUtil;
@@ -158,9 +157,11 @@ public class PsiModifierListImpl extends JavaStubPsiElement
else if (parent instanceof PsiMethod) {
PsiClass aClass = ((PsiMethod)parent).getContainingClass();
if (aClass != null && aClass.isInterface()) {
- implicitModifiers.add(PUBLIC);
- if (!explicitModifiers.contains(DEFAULT) && !explicitModifiers.contains(STATIC) && !explicitModifiers.contains(PRIVATE)) {
- implicitModifiers.add(ABSTRACT);
+ if (!explicitModifiers.contains(PRIVATE)) {
+ implicitModifiers.add(PUBLIC);
+ if (!explicitModifiers.contains(DEFAULT) && !explicitModifiers.contains(STATIC)) {
+ implicitModifiers.add(ABSTRACT);
+ }
}
}
else if (aClass != null && aClass.isEnum() && ((PsiMethod)parent).isConstructor()) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java
index a5d63a7ce89f..5e4153c05211 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -48,6 +48,7 @@ public class JavadocManagerImpl implements JavadocManager {
myInfos.add(new SimpleDocTagInfo("apiNote", LanguageLevel.JDK_1_8, false, PsiElement.class));
myInfos.add(new SimpleDocTagInfo("implNote", LanguageLevel.JDK_1_8, false, PsiElement.class));
myInfos.add(new SimpleDocTagInfo("implSpec", LanguageLevel.JDK_1_8, false, PsiElement.class));
+ myInfos.add(new SimpleDocTagInfo("moduleGraph", LanguageLevel.JDK_1_9, false, PsiJavaModule.class));
myInfos.add(new SimpleDocTagInfo("docRoot", LanguageLevel.JDK_1_3, true, PsiElement.class));
myInfos.add(new SimpleDocTagInfo("inheritDoc", LanguageLevel.JDK_1_4, true, PsiElement.class));
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
index 64a4bddb7700..80074749c1ee 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
@@ -1146,9 +1146,7 @@ public class InferenceSession {
}
}
- if (myContext != null) {
- myContext.putUserData(ERASED, myErased);
- }
+ setUncheckedInContext();
final Map map = substitutor.getSubstitutionMap();
for (PsiTypeParameter parameter : map.keySet()) {
@@ -1169,6 +1167,12 @@ public class InferenceSession {
}
}
+ public void setUncheckedInContext() {
+ if (myContext != null) {
+ myContext.putUserData(ERASED, myErased);
+ }
+ }
+
private boolean initFreshVariables(PsiSubstitutor substitutor, List vars) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(getManager().getProject());
PsiSubstitutor ySubstitutor = PsiSubstitutor.EMPTY;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
index 918c07fda6b6..4a6ef5c74700 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
@@ -106,9 +106,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
if (callSession != session) {
session.getInferenceSessionContainer().registerNestedSession(callSession);
session.propagateVariables(callSession.getInferenceVariables(), callSession.getRestoreNameSubstitution());
-/* if (callSession.isErased()) {
- session.setErased();
- }*/
+ callSession.setUncheckedInContext();
}
return true;
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/PrivateInInterfaces.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/PrivateInInterfaces.java
index 4998dae837eb..d0f2e08ea6ba 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/PrivateInInterfaces.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/PrivateInInterfaces.java
@@ -20,4 +20,9 @@ interface E {
interface F {
private int m = 0;
+}
+
+@interface G {
+ private String m();
+ private String m1() {return "";}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/PrivateInInterfacesOverriding.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/PrivateInInterfacesOverriding.java
new file mode 100644
index 000000000000..091b779ac2a6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/PrivateInInterfacesOverriding.java
@@ -0,0 +1,25 @@
+interface A {
+ void m();
+}
+interface A1 extends A {
+ private static void m() {}
+}
+interface A2 extends A {
+ private void m() {}
+}
+
+interface B {
+ private void m() {}
+}
+interface B1 extends B {
+ private void m() {}
+}
+interface B2 extends B {
+ private static void m() {}
+}
+interface B3 extends B {
+ default void m() {}
+}
+interface B4 extends B {
+ void m();
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/TryWithResources.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/TryWithResources.java
index e7665f8facda..753fe56ffa90 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/TryWithResources.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/TryWithResources.java
@@ -13,7 +13,8 @@ class TryWithResources {
final AutoCloseable r1 = null;
AutoCloseable r2 = null;
AutoCloseable r3 = null;
- try (r1; r2; r3) { }
+ AutoCloseable r4; r4 = null;
+ try (r1; r2; r4; r3) { }
r3 = null;
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/BadCharacters.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/BadCharacters.java
index 1bfd88961182..050443d3b604 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/BadCharacters.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/BadCharacters.java
@@ -1,10 +1,10 @@
import java.util.*;
-class Test {
- public void read(List list){}
+class Test {
+ public void read(List list) {}
/**
- * @see #read(java.util.List<T>)
+ * @see #read(java.util.List<T>)
*/
- public void write(){}
+ public void write() {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/BadReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/BadReference.java
index 36c2c8581051..ff20c956461b 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/BadReference.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/BadReference.java
@@ -1,8 +1,8 @@
class Test {
- /**
- * This element was written by {@link Test#write(Object, XmlWriter)}
+ /**
+ * This element was written by {@link Test#write(Object, XmlWriter)}
* method. So read and write methods should be consistent.
*/
- public void read(){}
- public void write(Object o, XmlWriter writer){}
+ public void read() {}
+ public void write(Object o, XmlWriter writer) {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Exception0.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Exception0.java
index 66281ea58bb7..5e9f1c94b34d 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Exception0.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Exception0.java
@@ -1,8 +1,8 @@
class Test {
- /**
- * @throws SomeClass asdfasd
- */
- public void foo() {}
-
- class SomeClass {}
+ /**
+ * @throws SomeClass asdfasd
+ */
+ public void foo() {}
+
+ class SomeClass {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/InheritJavaDoc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/InheritJavaDoc.java
index 75abbd9cb85b..01a2dfe60e2a 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/InheritJavaDoc.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/InheritJavaDoc.java
@@ -1,7 +1,6 @@
class Test {
/**
- * @inheritDoc
- */
- void a() {
- }
+ * @inheritDoc
+ */
+ void a() {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Java18Tags.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Java18Tags.java
index 80a6789e8f50..1f0554cf80e2 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Java18Tags.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Java18Tags.java
@@ -1,8 +1,9 @@
class Test {
- /**
- * @apiNote note1
- * @implNote implNote
- * @implSpec implSpec
- */
- public void i() {}
+ /**
+ * @apiNote note1
+ * @implNote implNote
+ * @implSpec implSpec
+ * @moduleGraph
+ */
+ public void i() {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/JavadocPeriod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/JavadocPeriod.java
index f7ef1c13ea0b..cd7ffafc1d72 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/JavadocPeriod.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/JavadocPeriod.java
@@ -1,6 +1,4 @@
-/**
+/**
* Missing dot
*/
-class Test {
-
-}
\ No newline at end of file
+class Test { }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/JavadocPeriod2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/JavadocPeriod2.java
index 58f70109bfa0..4d6d004acebf 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/JavadocPeriod2.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/JavadocPeriod2.java
@@ -1,7 +1,5 @@
-/**
-* Do smth
-* @author me.
-*/
-class Test {
-
-}
\ No newline at end of file
+/**
+ * Do smth
+ * @author me.
+ */
+class Test { }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Link0.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Link0.java
index 733cec2da1a9..c09a5b45e78e 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Link0.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Link0.java
@@ -1,8 +1,10 @@
class Test {
- /**
- * @param ppp see {@link #Test}
- */
- public void i(int ppp) {}
-
- class A{ public void foo() {}}
+ /**
+ * @param ppp see {@link #Test}
+ */
+ public void i(int ppp) {}
+
+ class A {
+ public void foo() {}
+ }
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/MissingReturnDescription.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/MissingReturnDescription.java
index f542e0d79de8..bf16275f84ea 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/MissingReturnDescription.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/MissingReturnDescription.java
@@ -1,8 +1,8 @@
class MissingRetunDescription {
/**
- * @return
- * @throws Exception in some case
- */
+ * @return
+ * @throws Exception in some case
+ */
public boolean foo() throws Exception {
return false;
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/MultipleThrows.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/MultipleThrows.java
index 6fc69105c3e9..bac7e90b04ac 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/MultipleThrows.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/MultipleThrows.java
@@ -1,9 +1,10 @@
import java.io.IOException;
+
class Test {
/**
- * @throws IOException in some case
- * @throws IOException
- */
+ * @throws IOException in some case
+ * @throws IOException
+ */
void a() throws IOException{
throw new IOException();
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param0.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param0.java
index 485ae4576695..7ac2339bdef9 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param0.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param0.java
@@ -1,5 +1,4 @@
/**
- * @param myParam paramDescription
+ * @param myParam paramDescription
*/
-class Test {
-}
\ No newline at end of file
+class Test { }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param2.java
index b81780d00505..b28d9e471b32 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param2.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param2.java
@@ -1,7 +1,6 @@
class Test {
- /**
- * @param param some param
- */
- public void foo() {
- }
+ /**
+ * @param param some param
+ */
+ public void foo() { }
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param4.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param4.java
index 0e2294a1c9d2..c1daf70f6ef3 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param4.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Param4.java
@@ -1,8 +1,7 @@
class Test {
-
- /**
- * @param i here description goes
- * @return
- */
- int d(){return 1;}
-}
+ /**
+ * @param i here description goes
+ * @return
+ */
+ int d() { return 1; }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Return0.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Return0.java
index 08614e1eae6e..75b9c22faeba 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Return0.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/Return0.java
@@ -1,6 +1,6 @@
class Test {
- /**
- * @return returns
- */
- public void foo() {}
+ /**
+ * @return returns
+ */
+ public void foo() {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See0.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See0.java
index 3b16ac9fd196..b77e3f7ceb60 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See0.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See0.java
@@ -1,8 +1,10 @@
class Test {
- /**
- * @see A#someField
- */
- public void i() {}
+ /**
+ * @see A#someField
+ */
+ public void i() {}
- class A{ public void foo() {}}
+ class A {
+ public void foo() {}
+ }
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/SeeConstants.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/SeeConstants.java
index 1437f1c27e9e..b234250d6e27 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/SeeConstants.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/SeeConstants.java
@@ -1,12 +1,11 @@
public class SeeConstants {
public static final String III = "";
- public static final String UUU="";
+ public static final String UUU = "";
/**
- * @see SeeConstants.III
+ * @see SeeConstants.III
* @see SeeConstants#UUU
* @param args blah-blah
*/
- public static void main(String[] args) {
- }
-}
+ public static void main(String[] args) { }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/UnknownInlineTag.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/UnknownInlineTag.java
index 75a457b97312..df727c30c76c 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/UnknownInlineTag.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/UnknownInlineTag.java
@@ -1,19 +1,19 @@
/**
- * {@linked}
+ * {@linked}
*/
class Foo {
/**
- * @param i some param {@vaaalue #field}
+ * @param i some param {@vaaalue #field}
*/
void foo(int i) {}
/**
- * {@linke}
+ * {@linke}
*/
int field;
/**
- * Don't ever think of going here: {@link/login}
+ * Don't ever think of going here: {@link/login}
*/
void m() {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/UnknownTags.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/UnknownTags.java
index 4c91f3c2d5ec..29dff08ee67d 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/UnknownTags.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/UnknownTags.java
@@ -1,14 +1,14 @@
/**
- * @foo
+ * @foo
*/
class Foo {
/**
- * @foo
+ * @foo
*/
void foo() {}
/**
- * @foo
- */
+ * @foo
+ */
int field;
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueBadReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueBadReference.java
index 1a5b18185041..abb4b66f1da2 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueBadReference.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueBadReference.java
@@ -1,7 +1,7 @@
class Test {
- /**
- * Value is {@value #badReference}
- * @param ppp .
- */
- public void i(int ppp) {}
+ /**
+ * Value is {@value #badReference}
+ * @param ppp .
+ */
+ public void i(int ppp) {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueNotOnField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueNotOnField.java
index 69cc30527921..2e70d9636133 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueNotOnField.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueNotOnField.java
@@ -1,8 +1,8 @@
class Test {
- /**
- * Value is {@value #g}
- */
- public void i() {}
+ /**
+ * Value is {@value #g}
+ */
+ public void i() {}
- public void g() {}
+ public void g() {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueNotOnStaticField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueNotOnStaticField.java
index 9489b82d22d4..712b88cdd0a6 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueNotOnStaticField.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueNotOnStaticField.java
@@ -1,8 +1,8 @@
class Test {
- public int A = 1;
+ public int A = 1;
- /**
- * Value is {@value #A}
- */
- public void i() {}
+ /**
+ * Value is {@value #A}
+ */
+ public void i() {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueOnNotInitializedField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueOnNotInitializedField.java
index a386784bcb6f..fdf397bcbe07 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueOnNotInitializedField.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueOnNotInitializedField.java
@@ -1,8 +1,8 @@
class Test {
- public static int A;
+ public static int A;
- /**
- * Value is {@value #A}
- */
- public void i() {}
+ /**
+ * Value is {@value #A}
+ */
+ public void i() {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueReference14.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueReference14.java
index 3534826a72f0..73ea9106a801 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueReference14.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/ValueReference14.java
@@ -1,9 +1,9 @@
class Test {
- public static final int A = 1;
+ public static final int A = 1;
- /**
- * Value is {@value #A}
- * @param ppp .
- */
- public void i(int ppp) {}
+ /**
+ * Value is {@value #A}
+ * @param ppp .
+ */
+ public void i(int ppp) {}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/module-info.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/module-info.java
new file mode 100644
index 000000000000..c28f08182edc
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/module-info.java
@@ -0,0 +1,5 @@
+/**
+ * @moduleGraph
+ * @since 9
+ */
+module Test { }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/accessStaticViaInstance/afterAccessForStaticMethodInInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/accessStaticViaInstance/afterAccessForStaticMethodInInterface.java
new file mode 100644
index 000000000000..19861c850d9e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/accessStaticViaInstance/afterAccessForStaticMethodInInterface.java
@@ -0,0 +1,10 @@
+// "Access static 'I.m()' via class 'I' reference" "true"
+interface I {
+ static void m() {}
+}
+
+class A implements I {
+ {
+ I.m();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/accessStaticViaInstance/beforeAccessForStaticMethodInInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/accessStaticViaInstance/beforeAccessForStaticMethodInInterface.java
new file mode 100644
index 000000000000..26a1b58499c2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/accessStaticViaInstance/beforeAccessForStaticMethodInInterface.java
@@ -0,0 +1,10 @@
+// "Access static 'I.m()' via class 'I' reference" "true"
+interface I {
+ static void m() {}
+}
+
+class A implements I {
+ {
+ this.m();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier19/afterMakeDefault.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier19/afterMakeDefault.java
new file mode 100644
index 000000000000..c787af2ad7ee
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier19/afterMakeDefault.java
@@ -0,0 +1,10 @@
+// "Make 'I.foo' public" "true"
+interface I {
+ default void foo() { }
+}
+
+class A implements I {
+ {
+ this.foo();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier19/beforeMakeDefault.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier19/beforeMakeDefault.java
new file mode 100644
index 000000000000..76b1c34ebdb9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/modifier19/beforeMakeDefault.java
@@ -0,0 +1,10 @@
+// "Make 'I.foo' public" "true"
+interface I {
+ private void foo() { }
+}
+
+class A implements I {
+ {
+ this.foo();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterFailedInferenceDueToWrongExpectedType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterFailedInferenceDueToWrongExpectedType.java
new file mode 100644
index 000000000000..ccea5e7c4883
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterFailedInferenceDueToWrongExpectedType.java
@@ -0,0 +1,10 @@
+// "Change variable 'foo' type to 'java.util.List'" "true"
+
+import java.util.Arrays;
+import java.util.List;
+
+class MyClass {
+ void bar() {
+ List foo = Arrays.asList("a");
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterFailedInferenceDueToWrongExpectedTypeAssignment.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterFailedInferenceDueToWrongExpectedTypeAssignment.java
new file mode 100644
index 000000000000..a7297a2d5e66
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterFailedInferenceDueToWrongExpectedTypeAssignment.java
@@ -0,0 +1,11 @@
+// "Change variable 'foo' type to 'java.util.List'" "true"
+
+import java.util.Arrays;
+import java.util.List;
+
+class MyClass {
+ void bar() {
+ List foo;
+ foo = (Arrays.asList("a"));
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterFailedInferenceDueToWrongExpectedTypeNotApplicable.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterFailedInferenceDueToWrongExpectedTypeNotApplicable.java
new file mode 100644
index 000000000000..5861eb786683
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterFailedInferenceDueToWrongExpectedTypeNotApplicable.java
@@ -0,0 +1,15 @@
+// "Change variable 'foo' type to 'java.lang.String'" "true"
+
+import java.util.List;
+import java.util.Set;
+
+class MyClass {
+ public static void sort(final List list) {
+ String foo = (findStart(list));
+ }
+
+ private static V findStart(List result) {
+ return result.get(0);
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeFailedInferenceDueToWrongExpectedType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeFailedInferenceDueToWrongExpectedType.java
new file mode 100644
index 000000000000..802171f834a2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeFailedInferenceDueToWrongExpectedType.java
@@ -0,0 +1,10 @@
+// "Change variable 'foo' type to 'java.util.List'" "true"
+
+import java.util.Arrays;
+import java.util.List;
+
+class MyClass {
+ void bar() {
+ String[] foo = Arrays.asList("a");
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeFailedInferenceDueToWrongExpectedTypeAssignment.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeFailedInferenceDueToWrongExpectedTypeAssignment.java
new file mode 100644
index 000000000000..42be9d9e4e0e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeFailedInferenceDueToWrongExpectedTypeAssignment.java
@@ -0,0 +1,11 @@
+// "Change variable 'foo' type to 'java.util.List'" "true"
+
+import java.util.Arrays;
+import java.util.List;
+
+class MyClass {
+ void bar() {
+ String[] foo;
+ foo = (Arrays.asList("a"));
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeFailedInferenceDueToWrongExpectedTypeNotApplicable.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeFailedInferenceDueToWrongExpectedTypeNotApplicable.java
new file mode 100644
index 000000000000..f9612e9aa742
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeFailedInferenceDueToWrongExpectedTypeNotApplicable.java
@@ -0,0 +1,15 @@
+// "Change variable 'foo' type to 'java.lang.String'" "true"
+
+import java.util.List;
+import java.util.Set;
+
+class MyClass {
+ public static void sort(final List list) {
+ Set foo = (findStart(list));
+ }
+
+ private static V findStart(List result) {
+ return result.get(0);
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/sameParameterValue/notReportedDueToHighVisibility/expected.xml b/java/java-tests/testData/inspection/sameParameterValue/notReportedDueToHighVisibility/expected.xml
new file mode 100644
index 000000000000..bdafc52f107c
--- /dev/null
+++ b/java/java-tests/testData/inspection/sameParameterValue/notReportedDueToHighVisibility/expected.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/java/java-tests/testData/inspection/sameParameterValue/notReportedDueToHighVisibility/src/Test.java b/java/java-tests/testData/inspection/sameParameterValue/notReportedDueToHighVisibility/src/Test.java
new file mode 100644
index 000000000000..70af88aaeeee
--- /dev/null
+++ b/java/java-tests/testData/inspection/sameParameterValue/notReportedDueToHighVisibility/src/Test.java
@@ -0,0 +1,11 @@
+public class Test {
+ void m() {
+ mmmmmmmmmm(false);
+ mmmmmmmmmm(false);
+ mmmmmmmmmm(false);
+ }
+
+ public void mmmmmmmmmm(boolean t) {
+
+ }
+}
diff --git a/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/RenameInInitializer.java b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/RenameInInitializer.java
new file mode 100644
index 000000000000..4f1fa3457c20
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/RenameInInitializer.java
@@ -0,0 +1,8 @@
+public class RenameInInitializer {
+ public static void main(String[] args) {
+ int aValue = 100;
+ int result = 1000;
+ int a = IntStream.of(aValue, result).peek(x -> {}).sum();
+ System.out.println(aValue + result + a);
+ }
+}
diff --git a/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/RenameInInitializer.java.after b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/RenameInInitializer.java.after
new file mode 100644
index 000000000000..9d4106c46485
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/RenameInInitializer.java.after
@@ -0,0 +1,35 @@
+public class RenameInInitializer {
+ public static void main(String[] args) {
+ Inner inner = new Inner().invoke();
+ int aValue = inner.getValue();
+ int result = inner.getResult();
+ int a = inner.getA();
+ System.out.println(aValue + result + a);
+ }
+
+ private static class Inner {
+ private int myValue;
+ private int myResult;
+ private int myA;
+
+ public int getValue() {
+ return myValue;
+ }
+
+ public int getResult() {
+ return myResult;
+ }
+
+ public int getA() {
+ return myA;
+ }
+
+ public Inner invoke() {
+ myValue = 100;
+ myResult = 1000;
+ myA = IntStream.of(myValue, myResult).peek(x -> {
+ }).sum();
+ return this;
+ }
+ }
+}
diff --git a/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/SameFieldsWithPrefix.java b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/SameFieldsWithPrefix.java
new file mode 100644
index 000000000000..77c9d80e712f
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/SameFieldsWithPrefix.java
@@ -0,0 +1,10 @@
+public class SameFieldsWithPrefix {
+ public static void main(String[] args) {
+ int aValue = 100;
+ int bValue = 1000;
+
+ IntStream.of(aValue, bValue).peek(x -> {}).sum();
+
+ System.out.println(aValue + bValue);
+ }
+}
diff --git a/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/SameFieldsWithPrefix.java.after b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/SameFieldsWithPrefix.java.after
new file mode 100644
index 000000000000..97c635b2db93
--- /dev/null
+++ b/java/java-tests/testData/refactoring/extractMethodObject/multipleExitPoints/SameFieldsWithPrefix.java.after
@@ -0,0 +1,30 @@
+public class SameFieldsWithPrefix {
+ public static void main(String[] args) {
+ Inner inner = new Inner().invoke();
+ int aValue = inner.getValue();
+ int bValue = inner.getBValue();
+
+ System.out.println(aValue + bValue);
+ }
+
+ private static class Inner {
+ private int myValue;
+ private int myBValue;
+
+ public int getValue() {
+ return myValue;
+ }
+
+ public int getBValue() {
+ return myBValue;
+ }
+
+ public Inner invoke() {
+ myValue = 100;
+ myBValue = 1000;
+
+ IntStream.of(myValue, myBValue).peek(x -> {}).sum();
+ return this;
+ }
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java
index 1eb10eae5df9..5ccc1e7e440a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -19,7 +19,6 @@ import com.intellij.JavaTestUtil;
import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
import com.intellij.codeInspection.javaDoc.JavaDocReferenceInspection;
import com.intellij.openapi.paths.WebReference;
-import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.vcs.IssueNavigationConfiguration;
import com.intellij.openapi.vcs.IssueNavigationLink;
import com.intellij.pom.java.LanguageLevel;
@@ -38,7 +37,6 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
- LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.HIGHEST);
myInspection = new JavaDocLocalInspection();
myInspection.setIgnoreDuplicatedThrows(false);
enableInspectionTools(myInspection, new JavaDocReferenceInspection());
@@ -76,12 +74,12 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testException3() { doTest(); }
public void testException4() { myInspection.METHOD_OPTIONS.ACCESS_JAVADOC_REQUIRED_FOR = "package"; doTest(); }
public void testMultipleThrows() { doTest(); }
- public void testInheritJavaDoc() { doTestWithLangLevel(LanguageLevel.JDK_1_3); }
+ public void testInheritJavaDoc() { setLanguageLevel(LanguageLevel.JDK_1_3); doTest(); }
public void testLink0() { doTest(); }
public void testLinkFromInnerClassToSelfMethod() { doTest(); }
public void testValueBadReference() { doTest(); }
public void testValueGoodReference() { doTest(); }
- public void testValueReference14() { doTestWithLangLevel(LanguageLevel.JDK_1_4); }
+ public void testValueReference14() { setLanguageLevel(LanguageLevel.JDK_1_4); doTest(); }
public void testValueEmpty() { doTest(); }
public void testValueNotOnField() { doTest(); }
public void testValueNotOnStaticField() { doTest(); }
@@ -109,6 +107,7 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIgnoreDuplicateThrows() { myInspection.setIgnoreDuplicatedThrows(true); doTest(); }
public void testIgnoreAccessors() { myInspection.setIgnoreSimpleAccessors(true); doTest(); }
public void testAuthoredMethod() { doTest(); }
+ public void testModuleTags() { doTest("module-info.java", true, false); }
public void testIssueLinksInJavaDoc() {
IssueNavigationConfiguration navigationConfiguration = IssueNavigationConfiguration.getInstance(getProject());
@@ -140,12 +139,7 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase {
assertEquals(expected, refs.stream().map(PsiReferenceBase::getCanonicalText).collect(Collectors.toSet()));
}
- private void doTestWithLangLevel(LanguageLevel level) {
- LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(level);
- doTest();
- }
-
protected void doTest() {
- super.doTest(getTestName(false) + ".java", true, false);
+ doTest(getTestName(false) + ".java", true, false);
}
}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java
index c4b9a08f1e0a..f23c916d42e6 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java
@@ -41,6 +41,7 @@ public class LightAdvHighlightingJdk9Test extends LightDaemonAnalyzerTestCase {
public void testSafeVarargsApplicability() { doTest(true, false); }
public void testPrivateInInterfaces() { doTest(false, false); }
+ public void testPrivateInInterfacesOverriding() { doTest(false, false); }
public void testUnderscore() { doTest(false, false); }
public void testTryWithResources() { doTest(false, false); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Modifier19Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Modifier19Test.java
new file mode 100644
index 000000000000..202de7565669
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Modifier19Test.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInsight.daemon.quickFix;
+
+import com.intellij.testFramework.LightProjectDescriptor;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import org.jetbrains.annotations.NotNull;
+
+public class Modifier19Test extends LightQuickFixParameterizedTestCase {
+ public void test() throws Exception { doAllTests(); }
+
+ @Override
+ protected String getBasePath() {
+ return "/codeInsight/daemonCodeAnalyzer/quickFix/modifier19";
+ }
+
+ @NotNull
+ @Override
+ protected LightProjectDescriptor getProjectDescriptor() {
+ return LightCodeInsightFixtureTestCase.JAVA_9;
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/SameParameterValueLocalTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/SameParameterValueLocalTest.java
index 682d54f93454..85595083d51e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/SameParameterValueLocalTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/SameParameterValueLocalTest.java
@@ -17,10 +17,18 @@ package com.intellij.codeInspection;
import com.intellij.JavaTestUtil;
import com.intellij.codeInspection.sameParameterValue.SameParameterValueInspection;
+import com.intellij.psi.PsiModifier;
import com.intellij.testFramework.InspectionTestCase;
public class SameParameterValueLocalTest extends InspectionTestCase {
- private LocalInspectionTool myTool = new SameParameterValueInspection().getSharedLocalInspectionTool();
+ private final SameParameterValueInspection myGlobalTool = new SameParameterValueInspection();
+ private LocalInspectionTool myTool = myGlobalTool.getSharedLocalInspectionTool();
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ //myGlobalTool.highestModifier = PsiModifier.PUBLIC;
+ }
@Override
protected String getTestDataPath() {
@@ -42,6 +50,16 @@ public class SameParameterValueLocalTest extends InspectionTestCase {
}
public void testMethodWithSuper() {
+ String previous = myGlobalTool.highestModifier;
+ myGlobalTool.highestModifier = PsiModifier.PUBLIC;
+ try {
+ doTest(getGlobalTestDir(), myTool);
+ } finally {
+ myGlobalTool.highestModifier = previous;
+ }
+ }
+
+ public void testNotReportedDueToHighVisibility() {
doTest(getGlobalTestDir(), myTool);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/SameParameterValueTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/SameParameterValueTest.java
index a21817d196e2..b77996f3b947 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/SameParameterValueTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/SameParameterValueTest.java
@@ -2,11 +2,17 @@ package com.intellij.codeInspection;
import com.intellij.JavaTestUtil;
import com.intellij.codeInspection.sameParameterValue.SameParameterValueInspection;
+import com.intellij.psi.PsiModifier;
import com.intellij.testFramework.InspectionTestCase;
public class SameParameterValueTest extends InspectionTestCase {
private SameParameterValueInspection myTool = new SameParameterValueInspection();
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath() + "/inspection";
@@ -27,7 +33,13 @@ public class SameParameterValueTest extends InspectionTestCase {
}
public void testWithoutDeadCode() {
- doTest(getTestDir(), myTool, false, false);
+ String previous = myTool.highestModifier;
+ myTool.highestModifier = PsiModifier.PUBLIC;
+ try {
+ doTest(getTestDir(), myTool, false, false);
+ } finally {
+ myTool.highestModifier = previous;
+ }
}
public void testVarargs() {
@@ -39,6 +51,16 @@ public class SameParameterValueTest extends InspectionTestCase {
}
public void testMethodWithSuper() {
- doTest(getTestDir(), myTool, false, true);
+ String previous = myTool.highestModifier;
+ myTool.highestModifier = PsiModifier.PUBLIC;
+ try {
+ doTest(getTestDir(), myTool, false, true);
+ } finally {
+ myTool.highestModifier = previous;
+ }
+ }
+
+ public void testNotReportedDueToHighVisibility() {
+ doTest(getTestDir(), myTool, false, false);
}
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java
index 27c2bceb8e5b..b0ae8e2f8a4f 100644
--- a/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java
@@ -24,6 +24,7 @@ import com.intellij.lang.FileASTNode;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.diagnostic.DefaultLogger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.EditorModificationUtil;
@@ -41,6 +42,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.PsiFileImpl;
+import com.intellij.psi.impl.source.PsiJavaFileImpl;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StubElement;
@@ -971,6 +973,7 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
}
public void testDoubleRemoveIsAnError() throws Exception {
+ DefaultLogger.disableStderrDumping(getTestRootDisposable());
SmartPointerEx pointer = createPointer(createFile("a.java", "class A {}"));
getPointerManager().removePointer(pointer);
try {
@@ -982,4 +985,16 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
}
}
+ public void testStubSmartPointersAreCreatedEvenInAstPresence() throws Exception {
+ PsiJavaFileImpl file = (PsiJavaFileImpl)createFile("a.java", "class A {}");
+ assertNotNull(file.getNode());
+ SmartPointerEx pointer = createPointer(file.getClasses()[0]);
+
+ PlatformTestUtil.tryGcSoftlyReachableObjects();
+ assertNull(file.getTreeElement());
+
+ assertNotNull(pointer.getElement());
+ assertNull(file.getTreeElement());
+ }
+
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObjectWithMultipleExitPointsTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObjectWithMultipleExitPointsTest.java
index 20f78f6e9b33..8deca9cc7e52 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObjectWithMultipleExitPointsTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObjectWithMultipleExitPointsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,9 +22,10 @@ package com.intellij.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.CodeInsightUtil;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.refactoring.extractMethodObject.ExtractMethodObjectHandler;
import com.intellij.refactoring.extractMethodObject.ExtractMethodObjectProcessor;
import org.jetbrains.annotations.NotNull;
@@ -150,4 +151,27 @@ public class ExtractMethodObjectWithMultipleExitPointsTest extends LightRefactor
public void testAssignReturnValueToForeachParameter() throws Exception {
doTest();
}
+
+ public void testRenameInInitializer() throws Exception {
+ doTestWithIdeaCodeStyleSettings();
+ }
+
+ public void testSameFieldsWithPrefix() throws Exception {
+ doTestWithIdeaCodeStyleSettings();
+ }
+
+ private void doTestWithIdeaCodeStyleSettings() throws Exception {
+ final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
+ String oldPrefix = settings.FIELD_NAME_PREFIX;
+ settings.FIELD_NAME_PREFIX = "my";
+ boolean oldPrefer = settings.PREFER_LONGER_NAMES;
+ settings.PREFER_LONGER_NAMES = false;
+ try {
+ doTest();
+ }
+ finally {
+ settings.FIELD_NAME_PREFIX = oldPrefix;
+ settings.PREFER_LONGER_NAMES = oldPrefer;
+ }
+ }
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ElemType.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ElemType.java
index 3d311b18ee3a..6e4092f3cfbb 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ElemType.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ElemType.java
@@ -52,5 +52,12 @@ public enum ElemType {
*
* @since 1.8
*/
- TYPE_USE
+ TYPE_USE,
+
+ /**
+ * Module declaration.
+ *
+ * @since 9
+ */
+ MODULE
}
diff --git a/license/trove4j_license.txt b/license/trove4j_license.txt
new file mode 100644
index 000000000000..fd4ffe6a6564
--- /dev/null
+++ b/license/trove4j_license.txt
@@ -0,0 +1,21 @@
+The source code for GNU Trove is licensed under the Lesser GNU Public License (LGPL).
+
+ Copyright (c) 2001, Eric D. Friedman All Rights Reserved. This library is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
+ even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+Two classes (HashFunctions and PrimeFinder) included in Trove are licensed under the following terms:
+
+ Copyright (c) 1999 CERN - European Organization for Nuclear Research. Permission to use, copy, modify, distribute and sell this software
+ and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and
+ that both that copyright notice and this permission notice appear in supporting documentation. CERN makes no representations about the
+ suitability of this software for any purpose. It is provided "as is" without expressed or implied warranty.
+
+The source code of modified GNU Trove library is available at
+ https://github.com/JetBrains/intellij-community/blob/master/lib/src/trove4j_src.jar (containing trove4j_changes.txt describing the changes)
+ or
+ https://github.com/JetBrains/trove4j (with trove4j_changes.txt describing the changes)
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/CommonProblemDescriptor.java b/platform/analysis-api/src/com/intellij/codeInspection/CommonProblemDescriptor.java
index 11576b10d4e1..4ca0126c1842 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/CommonProblemDescriptor.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/CommonProblemDescriptor.java
@@ -36,8 +36,11 @@ public interface CommonProblemDescriptor {
if (diff != 0) {
return diff;
}
- return PsiUtilCore.compareElementsByPosition(((ProblemDescriptor)c2).getPsiElement(),
- ((ProblemDescriptor)c1).getPsiElement());
+
+ diff = PsiUtilCore.compareElementsByPosition(((ProblemDescriptor)c2).getPsiElement(), ((ProblemDescriptor)c1).getPsiElement());
+ if (diff != 0) {
+ return diff;
+ }
}
return c1.getDescriptionTemplate().compareTo(c2.getDescriptionTemplate());
};
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java b/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java
index 5aec1c33928d..46bd56e55668 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/ex/InspectionToolWrapper.java
@@ -188,13 +188,13 @@ public abstract class InspectionToolWrapper {
+ checkBox.setEnabled(controller.isEnabled() && controller.isSelected());
+ });
+ checkBox.setEnabled(controller.isEnabled() && controller.isSelected());
+ return checkBox;
}
public void addComponent(JComponent component) {
@@ -68,12 +85,6 @@ public class MultipleCheckboxOptionsPanel extends JPanel {
model.addChangeListener(changeListener);
}
- public static void initAndConfigureCheckbox(InspectionProfileEntry owner, String property, JCheckBox checkBox) {
- OptionAccessor optionAccessor = new OptionAccessor.Default(owner);
- checkBox.setSelected(optionAccessor.getOption(property));
- configureCheckbox(optionAccessor, property, checkBox);
- }
-
private static class CheckboxChangeListener implements ChangeListener {
private final OptionAccessor myAccessor;
private final String property;
@@ -89,6 +100,5 @@ public class MultipleCheckboxOptionsPanel extends JPanel {
public void stateChanged(ChangeEvent e) {
myAccessor.setOption(property, model.isSelected());
}
-
}
}
\ No newline at end of file
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityLibraryLicenses.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityLibraryLicenses.groovy
index cc579576ec08..9a04a5cf841c 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityLibraryLicenses.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityLibraryLicenses.groovy
@@ -40,7 +40,8 @@ class CommunityLibraryLicenses {
new LibraryLicense(name: "Android SDK Tools JPS", libraryName: "android-sdk-tools-jps", license: "Apache 2.0",
url: "http://source.android.com/"),
new LibraryLicense(name: "Android SDK Tools", libraryName: "android-sdk-tools", license: "Apache 2.0", url: "http://source.android.com/"),
- new LibraryLicense(name: "Android Analytics", libraryName: "analytics", license: "Apache 2.0", url: "http://source.android.com/"),
+ new LibraryLicense(name: "Android Analytics", libraryName: "google-analytics-library", license: "Apache 2.0", url: "http://source.android.com/"),
+ new LibraryLicense(name: "Android Profiler", libraryName: "studio-profiler-grpc-1.0-jarjar", license: "Apache 2.0", url: "http://source.android.com/"),
new LibraryLicense(name: "Android Layout Library", libraryName: "layoutlib", license: "Apache 2.0", url: "http://source.android.com/"),
new LibraryLicense(name: "Android DEX library", libraryName: "dexlib2", license: "Apache 2.0", url: "http://source.android.com/"),
new LibraryLicense(name: "Android Sherpa library", libraryName: "sherpa-solver", license: "Apache 2.0", url: "http://source.android.com/"),
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy
index 54896406ad6d..191e75c28f35 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/CommunityRepositoryModules.groovy
@@ -238,18 +238,26 @@ class CommunityRepositoryModules {
]
static PluginLayout androidPlugin(Map additionalModulesToJars) {
- plugin("android") {
+ plugin("android-plugin") {
+ mainJarName = "android.jar"
+ directoryName = "android"
+ withModule("android", "android.jar")
+ withModule("observable", "android.jar")
+ withModule("wizard", "android.jar")
+ withModule("sdk-updates", "android.jar")
+ withModule("designer", "android.jar")
+ withModule("manifest-merger")
+ withModule("repository")
+ withModule("common", "android-base-common.jar")
withModule("android-common", "android-common.jar", false)
withModule("android-rt", "android-rt.jar", false)
withModule("android-annotations", "androidAnnotations.jar")
- withModule("common")
withModule("sdklib", "sdklib.jar")
withModule("sdk-common", "sdk-common.jar")
withModule("layoutlib-api", "layoutlib-api.jar")
withModule("layoutlib", "layoutlib-loader.jar")
- withModule("manifest-merger")
withModule("adt-ui", "adt-ui.jar")
- withModule("repository")
+ withModule("adt-ui-model", "adt-ui.jar")
withModule("sherpa-ui", "constraint-layout.jar")
withModule("pixelprobe", "pixalprobe.jar")
withModule("manifest-merger", "manifest-merger.jar")
@@ -261,7 +269,6 @@ class CommunityRepositoryModules {
withModule("lint-checks", "sdk-tools.jar")
withModule("ninepatch", "sdk-tools.jar")
withModule("perflib", "sdk-tools.jar")
- withModule("rpclib", "sdk-tools.jar")
withModule("builder-model", "sdk-tools.jar")
withModule("builder-test-api", "sdk-tools.jar")
withModule("instant-run-common", "sdk-tools.jar")
@@ -270,37 +277,37 @@ class CommunityRepositoryModules {
withModule("android-gradle-jps", "jps/android-gradle-jps.jar", false)
withModule("android-jps-plugin", "jps/android-jps-plugin.jar", false)
withProjectLibrary("freemarker-2.3.20") //todo[nik] move to module libraries
- withProjectLibrary("builder-model") //todo[nik] move to module libraries
withProjectLibrary("jgraphx-3.4.0.1") //todo[nik] move to module libraries
withProjectLibrary("kxml2") //todo[nik] move to module libraries
withProjectLibrary("lombok-ast") //todo[nik] move to module libraries
withProjectLibrary("layoutlib") //todo[nik] move to module libraries
- withResource("device-art-resources", "lib/device-art-resources")
+ withResource("../android/device-art-resources", "lib/device-art-resources")
withResourceFromModule("layoutlib-resources", ".", "lib/layoutlib")
withResourceFromModule("sdklib", "../templates", "lib/templates")
- withResourceArchive("annotations", "lib/androidAnnotations.jar")
- withResource("lib/antlr4-runtime-4.5.3.jar", "lib")
- withResource("lib/asm-5.0.3.jar", "lib")
- withResource("lib/asm-analysis-5.0.3.jar", "lib")
- withResource("lib/asm-tree-5.0.3.jar", "lib")
- withResource("lib/commons-io-2.4.jar", "lib")
- withResource("lib/commons-compress-1.8.1.jar", "lib")
- withResource("lib/javawriter-2.2.1.jar", "lib")
- withResource("lib/juniversalchardet-1.0.3.jar", "lib")
- withResource("lib/layoutlib.jar", "lib")
- withResource("lib/gluegen-rt.jar", "lib")
- withResource("lib/gluegen-rt-natives-linux-amd64.jar", "lib")
- withResource("lib/gluegen-rt-natives-linux-i586.jar", "lib")
- withResource("lib/gluegen-rt-natives-macosx-universal.jar", "lib")
- withResource("lib/gluegen-rt-natives-windows-amd64.jar", "lib")
- withResource("lib/gluegen-rt-natives-windows-i586.jar", "lib")
+ withResourceArchive("../android/annotations", "lib/androidAnnotations.jar")
+ withResource("../android/lib/antlr4-runtime-4.5.3.jar", "lib")
+ withResource("../android/lib/asm-5.0.3.jar", "lib")
+ withResource("../android/lib/asm-analysis-5.0.3.jar", "lib")
+ withResource("../android/lib/asm-tree-5.0.3.jar", "lib")
+ withResource("../android/lib/commons-io-2.4.jar", "lib")
+ withResource("../android/lib/commons-compress-1.8.1.jar", "lib")
+ withResource("../android/lib/javawriter-2.2.1.jar", "lib")
+ withResource("../android/lib/juniversalchardet-1.0.3.jar", "lib")
+ withResource("../android/lib/layoutlib.jar", "lib")
+ withResource("../android/lib/google-analytics-library.jar", "lib")
+ withResource("../android/lib/gluegen-rt.jar", "lib")
+ withResource("../android/lib/gluegen-rt-natives-linux-amd64.jar", "lib")
+ withResource("../android/lib/gluegen-rt-natives-linux-i586.jar", "lib")
+ withResource("../android/lib/gluegen-rt-natives-macosx-universal.jar", "lib")
+ withResource("../android/lib/gluegen-rt-natives-windows-amd64.jar", "lib")
+ withResource("../android/lib/gluegen-rt-natives-windows-i586.jar", "lib")
withProjectLibrary("jogl-all") //todo[nik] move to module libraries
- withResource("lib/jogl-all-natives-linux-amd64.jar", "lib")
- withResource("lib/jogl-all-natives-linux-i586.jar", "lib")
- withResource("lib/jogl-all-natives-macosx-universal.jar", "lib")
- withResource("lib/jogl-all-natives-windows-amd64.jar", "lib")
- withResource("lib/jogl-all-natives-windows-i586.jar", "lib")
- withResource("lib/androidWidgets", "lib/androidWidgets")
+ withResource("../android/lib/jogl-all-natives-linux-amd64.jar", "lib")
+ withResource("../android/lib/jogl-all-natives-linux-i586.jar", "lib")
+ withResource("../android/lib/jogl-all-natives-macosx-universal.jar", "lib")
+ withResource("../android/lib/jogl-all-natives-windows-amd64.jar", "lib")
+ withResource("../android/lib/jogl-all-natives-windows-i586.jar", "lib")
+ withResource("../android/lib/androidWidgets", "lib/androidWidgets")
additionalModulesToJars.entrySet().each {
withModule(it.key, it.value)
}
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy
index 1fa1d7b2004a..635c44e563e3 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildContextImpl.groovy
@@ -78,7 +78,7 @@ class BuildContextImpl extends BuildContext {
private static void setupDependencies(BuildMessages messages, String communityHome) {
messages.info("Setting up installer dependencies")
- if (!BuildUtils.gradle(new File(communityHome, 'build/dependencies/'), 'cleanSetupJbre', 'setupDependencies')) {
+ if (!BuildUtils.gradle(new File(communityHome, 'build/dependencies/'), 'setupDependencies')) {
messages.error("Cannot setup installer dependencies")
}
}
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BundledJreManager.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BundledJreManager.groovy
index 8cf0694cd348..db6c5120502c 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BundledJreManager.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BundledJreManager.groovy
@@ -118,22 +118,16 @@ class BundledJreManager {
}
private File findJreArchive(String osName, JvmArchitecture arch = JvmArchitecture.x64, JreVendor vendor = JreVendor.JetBrains) {
- def jreDir = new File(buildContext.paths.communityHome, "build/dependencies/build/jbre")
- String suffix = "_$osName${arch == JvmArchitecture.x32 ? '_x86' : '_x64'}.tar.gz"
- String prefix = buildContext.productProperties.toolsJarRequired ? vendor.jreWithToolsJarNamePrefix : vendor.jreNamePrefix
- Collection jreFiles = jreDir.listFiles()?.findAll { it.file && it.name.startsWith(prefix) && it.name.endsWith(suffix) } ?: [] as List
- String errorMessage;
- if (jreFiles.size() > 1) {
- errorMessage = "Cannot extract $osName JRE: several matching files are found ($jreFiles)"
- }
- else if (jreFiles.isEmpty()) {
- errorMessage = "Cannot extract $osName JRE: no '${prefix}...${suffix}' files found in $jreDir"
- }
- else {
- errorMessage = null
- }
+ def dependenciesDir = new File(buildContext.paths.communityHome, 'build/dependencies')
+ def jreDir = new File(dependenciesDir, 'build/jbre')
+ def jreVersion = getExpectedJreVersion(dependenciesDir)
- if (errorMessage != null) {
+ String suffix = "${jreVersion}_$osName${arch == JvmArchitecture.x32 ? '_x86' : '_x64'}.tar.gz"
+ String prefix = buildContext.productProperties.toolsJarRequired ? vendor.jreWithToolsJarNamePrefix : vendor.jreNamePrefix
+ def jreArchive = new File(jreDir, "$prefix$suffix")
+
+ if (!jreArchive.file || !jreArchive.exists()) {
+ def errorMessage = "Cannot extract $osName JRE: file $jreArchive is not found (${jreDir.listFiles()})"
if (buildContext.options.isInDevelopmentMode) {
buildContext.messages.warning(errorMessage)
}
@@ -142,7 +136,19 @@ class BundledJreManager {
}
return null
}
- return jreFiles.first()
+ return jreArchive
+ }
+
+ private static String getExpectedJreVersion(File dependenciesDir) {
+ def properties = new Properties()
+ def stream = new File(dependenciesDir, 'gradle.properties').newInputStream()
+ try {
+ properties.load(stream)
+ return properties.get("jdkBuild", "")
+ }
+ finally {
+ stream.close()
+ }
}
private enum JreVendor {
diff --git a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java
index 20ef2f259b8c..2e47447c8a20 100644
--- a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java
+++ b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.application.ex;
+import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -76,6 +77,16 @@ public class ApplicationUtil {
}
}
+ public static void showDialogAfterWriteAction(@NotNull Runnable runnable) {
+ Application application = ApplicationManager.getApplication();
+ if (application.isWriteAccessAllowed()) {
+ application.invokeLater(runnable);
+ }
+ else {
+ runnable.run();
+ }
+ }
+
public static class CannotRunReadActionException extends ProcessCanceledException {
}
}
\ No newline at end of file
diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java
index a46a47cdc50c..7510d47a1460 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java
@@ -28,10 +28,7 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.FreeThreadedFileViewProvider;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.source.PsiFileImpl;
-import com.intellij.psi.impl.source.PsiFileWithStubSupport;
import com.intellij.psi.impl.source.tree.ForeignLeafPsiElement;
-import com.intellij.psi.stubs.IStubElementType;
-import com.intellij.psi.stubs.StubTree;
import com.intellij.psi.tree.IStubFileElementType;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
@@ -209,18 +206,13 @@ class SmartPsiElementPointerImpl implements SmartPointerEx
@Nullable
private static SmartPointerElementInfo createAnchorInfo(@NotNull PsiElement element, @NotNull PsiFile containingFile) {
- if (element instanceof StubBasedPsiElement && containingFile instanceof PsiFileWithStubSupport) {
- PsiFileWithStubSupport stubFile = (PsiFileWithStubSupport)containingFile;
- StubTree stubTree = stubFile.getStubTree();
- if (stubTree != null) {
- // use stubs when tree is not loaded
+ if (element instanceof StubBasedPsiElement && containingFile instanceof PsiFileImpl) {
+ IStubFileElementType stubType = ((PsiFileImpl)containingFile).getElementTypeForStubBuilder();
+ if (stubType != null && stubType.shouldBuildStubFor(containingFile.getViewProvider().getVirtualFile())) {
StubBasedPsiElement stubPsi = (StubBasedPsiElement)element;
int stubId = PsiAnchor.calcStubIndex(stubPsi);
- IStubElementType myStubElementType = stubPsi.getElementType();
-
- IStubFileElementType elementTypeForStubBuilder = ((PsiFileImpl)containingFile).getElementTypeForStubBuilder();
- if (stubId != -1 && elementTypeForStubBuilder != null) { // TemplateDataElementType is not IStubFileElementType
- return new AnchorElementInfo(element, stubFile, stubId, myStubElementType);
+ if (stubId != -1) {
+ return new AnchorElementInfo(element, (PsiFileImpl)containingFile, stubId, stubPsi.getElementType());
}
}
}
diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java
index 0b72007c6928..2618a34113de 100644
--- a/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java
+++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java
@@ -22,7 +22,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.WindowWrapper;
import com.intellij.openapi.ui.WindowWrapperBuilder;
import com.intellij.openapi.util.Disposer;
-import com.intellij.util.ImageLoader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -58,7 +57,7 @@ public abstract class DiffWindowBase {
myProcessor.updateRequest();
})
.build();
- myWrapper.setImage(ImageLoader.loadFromResource("/diff/Diff.png"));
+ myWrapper.setImages(DiffUtil.DIFF_FRAME_ICONS);
Disposer.register(myWrapper, myProcessor);
}
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 097af8c4fc8a..481c376804d1 100644
--- a/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java
+++ b/platform/diff-impl/src/com/intellij/diff/util/DiffUtil.java
@@ -88,6 +88,7 @@ import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.ArrayUtil;
import com.intellij.util.DocumentUtil;
+import com.intellij.util.ImageLoader;
import com.intellij.util.LineSeparator;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
@@ -113,6 +114,19 @@ public class DiffUtil {
@NotNull public static final String DIFF_CONFIG = "diff.xml";
public static final int TITLE_GAP = JBUI.scale(2);
+ public static final List DIFF_FRAME_ICONS = loadDiffFrameImages();
+
+
+ @NotNull
+ private static List loadDiffFrameImages() {
+ return ContainerUtil.list(
+ ImageLoader.loadFromResource("/diff_frame16.png"),
+ ImageLoader.loadFromResource("/diff_frame32.png"),
+ ImageLoader.loadFromResource("/diff_frame64.png"),
+ ImageLoader.loadFromResource("/diff_frame128.png")
+ );
+ }
+
//
// Editor
//
diff --git a/platform/icons/src/diff_frame128.png b/platform/icons/src/diff_frame128.png
new file mode 100644
index 000000000000..7fe30c294739
Binary files /dev/null and b/platform/icons/src/diff_frame128.png differ
diff --git a/platform/icons/src/diff_frame16.png b/platform/icons/src/diff_frame16.png
new file mode 100644
index 000000000000..b86600dd917b
Binary files /dev/null and b/platform/icons/src/diff_frame16.png differ
diff --git a/platform/icons/src/diff_frame32.png b/platform/icons/src/diff_frame32.png
new file mode 100644
index 000000000000..65bb77966fd3
Binary files /dev/null and b/platform/icons/src/diff_frame32.png differ
diff --git a/platform/icons/src/diff_frame64.png b/platform/icons/src/diff_frame64.png
new file mode 100644
index 000000000000..faab388ebb6a
Binary files /dev/null and b/platform/icons/src/diff_frame64.png differ
diff --git a/platform/icons/src/icon-robots.txt b/platform/icons/src/icon-robots.txt
new file mode 100644
index 000000000000..e9a17d2af1c5
--- /dev/null
+++ b/platform/icons/src/icon-robots.txt
@@ -0,0 +1 @@
+skip: diff_frame*
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java
index 0b2226504b30..2576802954d8 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java
@@ -26,12 +26,12 @@ import com.intellij.ui.tabs.UiDecorator;
import com.intellij.ui.tabs.impl.JBEditorTabs;
import com.intellij.ui.tabs.impl.JBTabsImpl;
import com.intellij.ui.tabs.impl.TabLabel;
-import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.util.Map;
@@ -107,7 +107,7 @@ public class JBRunnerTabs extends JBEditorTabs {
@Override
public void apply(UiDecorator.UiDecoration decoration) {
- setBorder(JBUI.Borders.empty(5, 5, 7, 5));
+ setBorder(new EmptyBorder(5, 5, 7, 5));//Don't use JBUI here, it clips tab text in case of HiDPI
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
index 411ebbed370e..42da2e201538 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
@@ -456,16 +456,13 @@ public class InjectedLanguageUtil {
DebugUtil.finishPsiModification();
}
- PsiElement context = InjectedLanguageManager.getInstance(injected.getProject()).getInjectionHost(injected);
- PsiFile hostFile;
- if (context != null) {
- hostFile = context.getContainingFile();
- }
- else {
- VirtualFile delegate = virtualFile.getDelegate();
- hostFile = delegate.isValid() ? psiManagerEx.findFile(delegate) : null;
- }
- if (hostFile != null) {
+ VirtualFile delegate = virtualFile.getDelegate();
+ if (!delegate.isValid()) return;
+
+ FileViewProvider viewProvider = psiManagerEx.getFileManager().findCachedViewProvider(delegate);
+ if (!(viewProvider instanceof SingleRootFileViewProvider)) return;
+
+ for (PsiFile hostFile : ((SingleRootFileViewProvider)viewProvider).getCachedPsiFiles()) {
// modification of cachedInjectedDocuments must be under PsiLock
synchronized (InjectedLanguageManagerImpl.ourInjectionPsiLock) {
List cachedInjectedDocuments = getCachedInjectedDocuments(hostFile);
diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java
index 6611ccfc4b4c..ddc45b1f09b6 100644
--- a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java
+++ b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java
@@ -20,6 +20,7 @@ import com.intellij.CommonBundle;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.requests.ContentDiffRequest;
import com.intellij.diff.requests.SimpleDiffRequest;
+import com.intellij.diff.util.DiffUtil;
import com.intellij.history.core.LocalHistoryFacade;
import com.intellij.history.integration.IdeaGateway;
import com.intellij.history.integration.LocalHistoryBundle;
@@ -54,7 +55,6 @@ import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBLayeredPane;
import com.intellij.util.Consumer;
-import com.intellij.util.ImageLoader;
import com.intellij.util.ui.AbstractLayoutManager;
import com.intellij.util.ui.AnimatedIcon;
import com.intellij.util.ui.AsyncProcessIcon;
@@ -98,7 +98,7 @@ public abstract class HistoryDialog extends FrameW
setProject(project);
setDimensionKey(getPropertiesKey());
- setImage(ImageLoader.loadFromResource("/diff/Diff.png"));
+ setImages(DiffUtil.DIFF_FRAME_ICONS);
closeOnEsc();
if (doInit) init();
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/WindowWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/WindowWrapper.java
index 9baa58dd63d1..7455b9aa6982 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/WindowWrapper.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/WindowWrapper.java
@@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
+import java.util.List;
public interface WindowWrapper extends Disposable {
enum Mode {FRAME, MODAL, NON_MODAL}
@@ -27,7 +28,7 @@ public interface WindowWrapper extends Disposable {
void setTitle(@Nullable String title);
- void setImage(@Nullable Image image);
+ void setImages(@Nullable List images);
void close();
}
diff --git a/platform/platform-api/src/com/intellij/ui/components/breadcrumbs/Breadcrumbs.java b/platform/platform-api/src/com/intellij/ui/components/breadcrumbs/Breadcrumbs.java
index 393569045ac5..50c026a2b324 100644
--- a/platform/platform-api/src/com/intellij/ui/components/breadcrumbs/Breadcrumbs.java
+++ b/platform/platform-api/src/com/intellij/ui/components/breadcrumbs/Breadcrumbs.java
@@ -47,6 +47,8 @@ import java.util.function.Function;
import javax.swing.JComponent;
import javax.swing.border.AbstractBorder;
+import static javax.swing.SwingUtilities.isLeftMouseButton;
+
/**
* @author Sergey.Malenkov
*/
@@ -337,6 +339,10 @@ public class Breadcrumbs extends JComponent implements RegionPainter {
return insets;
}
+ private static int getGap(Component component) {
+ return 10 * getScale(component);
+ }
+
private static int getScale(Component component) {
return component == null ? 1 : getScale(component.getFont());
}
@@ -364,7 +370,9 @@ public class Breadcrumbs extends JComponent implements RegionPainter {
@Override
public Dimension preferredLayoutSize(Container container) {
- Dimension size = getPreferredSize(getComponents(container, Breadcrumbs::toVisible));
+ ArrayList components = getComponents(container, Breadcrumbs::toVisible);
+ Dimension size = getPreferredSize(components);
+ size.width += components.size() * getGap(container);
if (size.height == 0) size.height = getPreferredHeight(container);
JBInsets.addTo(size, container.getInsets());
return size;
@@ -385,7 +393,7 @@ public class Breadcrumbs extends JComponent implements RegionPainter {
else /*if (bounds.width < size.width) {
}
else*/ {
- int gap = Math.max(0, Math.min(10 * getScale(container), (bounds.width - size.width) / (count - 1)));
+ int gap = getGap(container);
for (Component component : components) {
Dimension preferred = component.getPreferredSize();
component.setBounds(bounds.x, bounds.y, preferred.width, bounds.height);
@@ -416,6 +424,7 @@ public class Breadcrumbs extends JComponent implements RegionPainter {
if (!isHovered(crumb)) consumer = hover;
break;
case MouseEvent.MOUSE_CLICKED:
+ if (!isLeftMouseButton(event)) break;
crumb = function.apply(event);
if (crumb != null) consumer = select;
break;
diff --git a/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java b/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java
index 1ad75ae19716..ed47e0d868e4 100644
--- a/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java
+++ b/platform/platform-impl/src/com/intellij/designer/LightToolWindowManager.java
@@ -262,7 +262,7 @@ public abstract class LightToolWindowManager implements ProjectComponent {
}
@Nullable
- final ToolWindowAnchor getEditorMode() {
+ public final ToolWindowAnchor getEditorMode() {
String value = myPropertiesComponent.getValue(myEditorModeKey);
if (value == null) {
return getAnchor();
diff --git a/platform/platform-impl/src/com/intellij/ide/IdePopupManager.java b/platform/platform-impl/src/com/intellij/ide/IdePopupManager.java
index c310bb074b63..53951e39b779 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdePopupManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdePopupManager.java
@@ -79,6 +79,9 @@ public final class IdePopupManager implements IdeEventQueue.EventDispatcher {
&& !ultimateParentForFocusedComponent.equals(ultimateParentForEventWindow)) {
shouldCloseAllPopup = true;
}
+ else if (focused instanceof Dialog && ((Dialog)focused).isModal()) {
+ shouldCloseAllPopup = true;
+ }
}
if (!shouldCloseAllPopup && isPopupWindow(sourceWindow) && sourceWindow.getParent() == ((WindowEvent)e).getOppositeWindow()) {
shouldCloseAllPopup = true;
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java
index 4a913447988c..ebe14a4068a6 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java
@@ -368,6 +368,7 @@ public class MacIntelliJComboBoxUI extends BasicComboBoxUI {
Rectangle bounds = rectangleForCurrentValue();
if ( !comboBox.isEditable() ) {
+ listBox.setForeground(comboBox.isEnabled() ? UIManager.getColor("Label.foreground") : UIManager.getColor("Label.disabledForeground"));
paintCurrentValue(g, bounds, comboBox.isPopupVisible());
}
}
diff --git a/platform/platform-impl/src/com/intellij/internal/focus/FocusDebuggerAction.java b/platform/platform-impl/src/com/intellij/internal/focus/FocusDebuggerAction.java
index 46935ae0ea95..22490c63f831 100644
--- a/platform/platform-impl/src/com/intellij/internal/focus/FocusDebuggerAction.java
+++ b/platform/platform-impl/src/com/intellij/internal/focus/FocusDebuggerAction.java
@@ -37,7 +37,7 @@ public class FocusDebuggerAction extends AnAction implements DumbAware {
private FocusDrawer myFocusDrawer;
public FocusDebuggerAction() {
- if (Boolean.getBoolean("focus.debug")) {
+ if (Boolean.getBoolean("idea.ui.debug.mode")) {
ApplicationManager.getApplication().invokeLater(() -> actionPerformed(null));
}
}
diff --git a/platform/platform-impl/src/com/intellij/internal/inspector/UiInspectorAction.java b/platform/platform-impl/src/com/intellij/internal/inspector/UiInspectorAction.java
index b8fd3d2140f3..b2642d40a260 100644
--- a/platform/platform-impl/src/com/intellij/internal/inspector/UiInspectorAction.java
+++ b/platform/platform-impl/src/com/intellij/internal/inspector/UiInspectorAction.java
@@ -24,6 +24,7 @@ import com.intellij.notification.Notifications;
import com.intellij.notification.NotificationsManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.roots.ui.configuration.actions.IconWithTextAction;
import com.intellij.openapi.ui.DialogWrapper;
@@ -80,6 +81,12 @@ public class UiInspectorAction extends ToggleAction implements DumbAware {
private UiInspector myInspector;
+ public UiInspectorAction() {
+ if (Boolean.getBoolean("idea.ui.debug.mode")) {
+ ApplicationManager.getApplication().invokeLater(() -> setSelected(null, true));
+ }
+ }
+
@Override
public boolean isSelected(AnActionEvent e) {
return myInspector != null;
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
index d8c4954d226a..c40b712289e0 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java
@@ -267,7 +267,7 @@ public final class EditorHistoryManager implements PersistentStateComponent myImages = null;
private boolean myCloseOnEsc = false;
private Window myFrame;
private final Map myDataMap = ContainerUtil.newHashMap();
@@ -81,7 +81,6 @@ public class FrameWrapper implements Disposable, DataProvider {
protected StatusBar myStatusBar;
private boolean myShown;
private boolean myIsDialog;
- private boolean myImageWasChanged;
public FrameWrapper(Project project) {
this(project, null);
@@ -175,9 +174,9 @@ public class FrameWrapper implements Disposable, DataProvider {
} else {
((JDialog)frame).setTitle(myTitle);
}
- if (myImageWasChanged && myImage != null) {
+ if (myImages != null) {
// unwrap the image before setting as frame's icon
- frame.setIconImage(ImageUtil.toBufferedImage(myImage));
+ frame.setIconImages(ContainerUtil.map(myImages, ImageUtil::toBufferedImage));
}
else {
AppUIUtil.updateWindowIcon(myFrame);
@@ -230,7 +229,7 @@ public class FrameWrapper implements Disposable, DataProvider {
myFocusedCallback = null;
myFocusTrackback = null;
myComponent = null;
- myImage = null;
+ myImages = null;
myDisposed = true;
if (statusBar != null) {
@@ -333,8 +332,11 @@ public class FrameWrapper implements Disposable, DataProvider {
}
public void setImage(Image image) {
- myImageWasChanged = true;
- myImage = image;
+ setImages(image != null ? Collections.singletonList(image) : Collections.emptyList());
+ }
+
+ public void setImages(List images) {
+ myImages = images;
}
protected void loadFrameState() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java b/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java
index 96e25cef9497..39ff610194be 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/WindowWrapperBuilder.java
@@ -14,6 +14,7 @@ import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
+import java.util.List;
public class WindowWrapperBuilder {
@NotNull private final Mode myMode;
@@ -170,7 +171,7 @@ public class WindowWrapperBuilder {
}
@Override
- public void setImage(@Nullable Image image) {
+ public void setImages(@Nullable List images) {
}
@Override
@@ -305,8 +306,8 @@ public class WindowWrapperBuilder {
}
@Override
- public void setImage(@Nullable Image image) {
- myFrame.setImage(image);
+ public void setImages(@Nullable List images) {
+ myFrame.setImages(images);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java
index fd60e6407198..f80d4b47c7fc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2017 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.openapi.updateSettings.impl;
+import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -33,10 +34,14 @@ public class CheckForUpdateAction extends AnAction implements DumbAware {
else {
e.getPresentation().setVisible(!SystemInfo.isMacSystemMenu || !ActionPlaces.MAIN_MENU.equals(place));
}
+
+ if (!UpdateSettings.getInstance().isPlatformUpdateEnabled()) {
+ e.getPresentation().setDescription(ActionsBundle.message("action.CheckForUpdate.description.plugins"));
+ }
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
UpdateChecker.updateAndShowResult(e.getProject(), null);
}
-}
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesDialog.java
index 90c7b315267f..fc1d0c729152 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesDialog.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -53,7 +53,13 @@ class NoUpdatesDialog extends AbstractUpdateDialog {
private JEditorPane myMessageArea;
public NoUpdatesPanel() {
- myNothingToUpdateLabel.setText(IdeBundle.message("updates.no.updates.message", ApplicationInfo.getInstance().getVersionName()));
+ if (UpdateSettings.getInstance().isPlatformUpdateEnabled()) {
+ String app = ApplicationInfo.getInstance().getVersionName();
+ myNothingToUpdateLabel.setText(IdeBundle.message("updates.no.updates.message", app));
+ }
+ else {
+ myNothingToUpdateLabel.setText(IdeBundle.message("updates.no.updates.plugins.message"));
+ }
configureMessageArea(myMessageArea);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.kt b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.kt
index 6c7c8cfac8eb..093132648c48 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.kt
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -42,7 +42,6 @@ import com.intellij.openapi.util.BuildNumber
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
-import com.intellij.util.SystemProperties
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.containers.MultiMap
import com.intellij.util.io.HttpRequests
@@ -69,7 +68,6 @@ object UpdateChecker {
val NOTIFICATIONS = NotificationGroup(IdeBundle.message("update.notifications.title"), NotificationDisplayType.STICKY_BALLOON, true)
private val DISABLED_UPDATE = "disabled_update.txt"
- private val NO_PLATFORM_UPDATE = "ide.no.platform.update"
private var ourDisabledToUpdatePlugins: MutableSet? = null
private val ourAdditionalRequestOptions = hashMapOf()
@@ -120,11 +118,7 @@ object UpdateChecker {
indicator?.text = IdeBundle.message("updates.checking.platform")
val result = checkPlatformUpdate(updateSettings)
-
- if (manualCheck && result.state == UpdateStrategy.State.LOADED) {
- UpdateSettings.getInstance().saveLastCheckedInfo()
- }
- else if (result.state == UpdateStrategy.State.CONNECTION_ERROR) {
+ if (result.state == UpdateStrategy.State.CONNECTION_ERROR) {
val e = result.error
if (e != null) LOG.debug(e)
showErrorMessage(manualCheck, IdeBundle.message("updates.error.connection.failed", e?.message ?: "internal error"))
@@ -151,6 +145,8 @@ object UpdateChecker {
// show result
+ UpdateSettings.getInstance().saveLastCheckedInfo()
+
ApplicationManager.getApplication().invokeLater({
showUpdateResult(project, result, updateSettings, updatedPlugins, incompatiblePlugins, externalUpdates, !fromSettings, manualCheck)
callback?.setDone()
@@ -158,7 +154,7 @@ object UpdateChecker {
}
private fun checkPlatformUpdate(settings: UpdateSettings): CheckForUpdateResult {
- if (SystemProperties.getBooleanProperty(NO_PLATFORM_UPDATE, false)) {
+ if (!settings.isPlatformUpdateEnabled) {
return CheckForUpdateResult(UpdateStrategy.State.NOTHING_LOADED, null)
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java
index ad757e76af18..cfd5d3786303 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java
@@ -112,7 +112,7 @@ public class UpdateCheckerComponent implements Disposable, ApplicationComponent
@Override
public void appFrameCreated(String[] commandLineArgs, @NotNull Ref willOpenProject) {
BuildNumber currentBuild = ApplicationInfo.getInstance().getBuild();
- BuildNumber lastBuildChecked = BuildNumber.fromString(mySettings.getLasBuildChecked());
+ BuildNumber lastBuildChecked = BuildNumber.fromString(mySettings.getLastBuildChecked());
long timeSinceLastCheck = max(System.currentTimeMillis() - mySettings.getLastTimeChecked(), 0);
if (lastBuildChecked == null || currentBuild.compareTo(lastBuildChecked) > 0 || timeSinceLastCheck >= CHECK_INTERVAL) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java
index 2770eb01e39c..ea6ccd3899d3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettings.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import com.intellij.openapi.components.*;
import com.intellij.openapi.updateSettings.UpdateStrategyCustomization;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.SmartList;
+import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.net.NetUtils;
import com.intellij.util.xmlb.annotations.CollectionBean;
@@ -27,8 +28,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
-import java.util.List;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -61,8 +62,13 @@ public class UpdateSettings implements PersistentStateComponent getActiveChannels() {
UpdateStrategyCustomization tweaker = UpdateStrategyCustomization.getInstance();
return Stream.of(ChannelStatus.values())
- .filter((ch) -> ch == ChannelStatus.EAP || ch == ChannelStatus.RELEASE || tweaker.isChannelActive(ch))
+ .filter(ch -> ch == ChannelStatus.EAP || ch == ChannelStatus.RELEASE || tweaker.isChannelActive(ch))
.collect(Collectors.toList());
}
@@ -173,13 +179,13 @@ public class UpdateSettings implements PersistentStateComponent
- /** @deprecated use {@link #getSelectedChannelStatus()} (to be removed in IDEA 17) */
+ /** @deprecated use {@link #getSelectedChannelStatus()} (to be removed in IDEA 2018) */
@SuppressWarnings("unused")
public String getUpdateChannelType() {
return myState.UPDATE_CHANNEL_TYPE;
}
- /** @deprecated use {@link #setSelectedChannelStatus(ChannelStatus)} (to be removed in IDEA 17) */
+ /** @deprecated use {@link #setSelectedChannelStatus(ChannelStatus)} (to be removed in IDEA 2018) */
@SuppressWarnings("unused")
public void setUpdateChannelType(@NotNull String value) {
myState.UPDATE_CHANNEL_TYPE = value;
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java
index 379079825f10..38874f25e088 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -210,7 +210,13 @@ public class UpdateSettingsConfigurable extends BaseConfigurable implements Sear
private void updateLastCheckedLabel() {
long time = mySettings.getLastTimeChecked();
- myLastCheckedDate.setText(time == 0 ? IdeBundle.message("updates.last.check.never") : DateFormatUtil.formatPrettyDateTime(time));
+ if (time <= 0) {
+ myLastCheckedDate.setText(IdeBundle.message("updates.last.check.never"));
+ }
+ else {
+ myLastCheckedDate.setText(DateFormatUtil.formatPrettyDateTime(time));
+ myLastCheckedDate.setToolTipText(DateFormatUtil.formatDate(time) + ' ' + DateFormatUtil.formatTimeWithSeconds(time));
+ }
}
public ChannelStatus getSelectedChannelType() {
diff --git a/platform/platform-impl/src/com/intellij/ui/AppIcon.java b/platform/platform-impl/src/com/intellij/ui/AppIcon.java
index 8f2c55088eb9..d80edacb8662 100644
--- a/platform/platform-impl/src/com/intellij/ui/AppIcon.java
+++ b/platform/platform-impl/src/com/intellij/ui/AppIcon.java
@@ -27,6 +27,7 @@ import com.intellij.openapi.wm.AppIconScheme;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.util.IconUtil;
+import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.ImageUtil;
import com.intellij.util.ui.UIUtil;
import org.apache.sanselan.ImageWriteException;
@@ -46,6 +47,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.Map;
public abstract class AppIcon {
private static final Logger LOG = Logger.getInstance(AppIcon.class);
@@ -165,6 +167,7 @@ public abstract class AppIcon {
@SuppressWarnings("UseJBColor")
private static class MacAppIcon extends BaseIcon {
private BufferedImage myAppImage;
+ private Map
+ * 4. Parse the output via {@link #parse(CharSequence)} or {@link #parseOneRecord(CharSequence)} (if you want the output to be parsed line by line).
*
*
The class is package visible, since it's used only in GitHistoryUtils - the class which retrieve various pieced of history information
* in different formats from 'git log'
*
*
Note that you may pass one set of options to the GitLogParser constructor and then execute git log with other set of options.
- * In that case {@link #parse(String)} will parse only those options which you've specified in the constructor.
+ * In that case {@link #parse(CharSequence)} will parse only those options which you've specified in the constructor.
* Others will be ignored since the parser knows nothing about them: it just gets the 'git log' output to parse.
* Moreover you really must use {@link #getPretty()} to pass "--pretty=format" pattern to 'git log' - otherwise the parser won't be able
* to parse output of 'git log' (because special separator characters are used for that).
@@ -65,6 +65,8 @@ public class GitLogParser {
public static final String RECORD_START_GIT = "%x01%x01";
private static final String ITEMS_SEPARATOR_GIT = "%x02";
private static final String RECORD_END_GIT = "%x03%x03";
+ private static final int INPUT_ERROR_MESSAGE_HEAD_LIMIT = 1000000; // limit the string by ~2mb
+ private static final int INPUT_ERROR_MESSAGE_TAIL_LIMIT = 100;
private final String myFormat; // pretty custom format generated in the constructor
private final GitLogOption[] myOptions;
@@ -158,7 +160,7 @@ public class GitLogParser {
* The list is sorted as usual for git log - the first is the newest, the last is the oldest.
*/
@NotNull
- List parse(@NotNull String output) {
+ List parse(@NotNull CharSequence output) {
// Here is what git log returns for --pretty=tformat:^%H#%s$
// ^2c815939f45fbcfda9583f84b14fe9d393ada790#sample commit$
//
@@ -166,20 +168,21 @@ public class GitLogParser {
// ^b71477e9738168aa67a8d41c414f284255f81e8a#moved out$
//
// R100 dir/anew.txt anew.txt
- final List records = StringUtil.split(output, RECORD_START); // split by START, because END is the end of information, but not the end of the record: file status and path follow.
+ final List records = StringUtil.split(output, RECORD_START); // split by START, because END is the end of information, but not the end of the record: file status and path follow.
String notMatchedPart = null;
final List res = new ArrayList<>(records.size());
- for (String record : records) {
- if (!record.trim().isEmpty()) { // record[0] is empty for sure, because we're splitting on RECORD_START. Just to play safe adding the check for all records.
+ for (CharSequence record : records) {
+ String recordString = record.toString();
+ if (!recordString.isEmpty()) { // record[0] is empty for sure, because we're splitting on RECORD_START. Just to play safe adding the check for all records.
if (notMatchedPart != null) {
- record = notMatchedPart + record;
+ recordString = notMatchedPart + recordString;
}
- if (ONE_RECORD.matcher(record).matches()) {
+ if (ONE_RECORD.matcher(recordString).matches()) {
notMatchedPart = null;
- res.add(parseOneRecord(record));
+ res.add(parseOneRecord(recordString));
}
else {
- notMatchedPart = record;
+ notMatchedPart = recordString;
}
}
}
@@ -194,8 +197,8 @@ public class GitLogParser {
* @throws GitFormatException if the line is given in unexpected format.
*/
@Nullable
- GitLogRecord parseOneRecord(@NotNull String line) {
- if (line.isEmpty()) {
+ GitLogRecord parseOneRecord(@NotNull CharSequence line) {
+ if (line.length() == 0) {
return null;
}
Matcher matcher = ONE_RECORD.matcher(line);
@@ -273,8 +276,18 @@ public class GitLogParser {
}
}
- private static void throwGFE(String message, String line) {
- throw new GitFormatException(message + " [" + StringUtil.escapeStringCharacters(line) + "]");
- }
+ private static void throwGFE(String message, @NotNull CharSequence line) {
+ String lineString;
+ String formatString = "%s...(%d more characters)...%s";
+ if (line.length() > INPUT_ERROR_MESSAGE_HEAD_LIMIT + INPUT_ERROR_MESSAGE_TAIL_LIMIT + formatString.length()) {
+ lineString = String.format(formatString, line.subSequence(0, INPUT_ERROR_MESSAGE_HEAD_LIMIT),
+ (line.length() - INPUT_ERROR_MESSAGE_HEAD_LIMIT - INPUT_ERROR_MESSAGE_TAIL_LIMIT),
+ line.subSequence(line.length() - INPUT_ERROR_MESSAGE_TAIL_LIMIT, line.length()));
+ }
+ else {
+ lineString = line.toString();
+ }
+ throw new GitFormatException(message + " [" + StringUtil.escapeStringCharacters(lineString) + "]");
+ }
}
diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java
index dd31e7609d48..efaa81eba912 100644
--- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java
+++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessChecker.java
@@ -166,7 +166,7 @@ public class GrUnresolvedAccessChecker {
!PsiUtil.hasEnclosingInstanceInScope(outerClass, newExpression, true) &&
!hasEnclosingInstanceInArgList(newExpression.getArgumentList(), outerClass)) {
String qname = clazz.getQualifiedName();
- LOG.assertTrue(qname != null, clazz.getText());
+ LOG.assertTrue(qname != null);
return createAnnotationForRef(refElement, inStaticContext, GroovyBundle.message("cannot.reference.non.static", qname));
}
}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/ReimportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/ReimportingTest.java
index f9c1bf732ca8..c086447beb7d 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/ReimportingTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/ReimportingTest.java
@@ -16,7 +16,6 @@
package org.jetbrains.idea.maven.importing;
import com.intellij.compiler.CompilerConfiguration;
-import com.intellij.idea.Bombed;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
@@ -29,7 +28,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.idea.maven.MavenImportingTestCase;
-import java.util.Calendar;
import java.util.concurrent.atomic.AtomicInteger;
import static com.intellij.openapi.module.EffectiveLanguageLevelUtil.getEffectiveLanguageLevel;
@@ -258,10 +256,9 @@ public class ReimportingTest extends MavenImportingTestCase {
}
- @Bombed(user = "Vladislav.Soroka", year=2020, month = Calendar.APRIL, day = 1, description = "temporary disabled")
public void testSettingTargetLevel() throws Exception {
createModulePom("m1", "test" +
- "project" +
+ "m1" +
"1");
importProject();
assertEquals("1.5", CompilerConfiguration.getInstance(myProject).getBytecodeTargetLevel(getModule("m1")));
@@ -301,7 +298,7 @@ public class ReimportingTest extends MavenImportingTestCase {
// after configuration/target element delete in maven-compiler-plugin CompilerConfiguration#getBytecodeTargetLevel should be also updated
createModulePom("m1", "test" +
- "project" +
+ "m1" +
"1");
importProject();
assertEquals("1.5", CompilerConfiguration.getInstance(myProject).getBytecodeTargetLevel(getModule("m1")));
diff --git a/python/educational-core/resources/META-INF/plugin.xml b/python/educational-core/resources/META-INF/plugin.xml
index 630f26649fc4..249be31cb07f 100644
--- a/python/educational-core/resources/META-INF/plugin.xml
+++ b/python/educational-core/resources/META-INF/plugin.xml
@@ -41,14 +41,11 @@
-
-
-
-
+
@@ -78,8 +75,6 @@
description="Watch test input "/>
-
diff --git a/python/educational-python/resources/fileTemplates/internal/task.html.ft b/python/educational-core/resources/fileTemplates/internal/task.html.ft
similarity index 100%
rename from python/educational-python/resources/fileTemplates/internal/task.html.ft
rename to python/educational-core/resources/fileTemplates/internal/task.html.ft
diff --git a/python/educational-python/resources/fileTemplates/internal/task.md.ft b/python/educational-core/resources/fileTemplates/internal/task.md.ft
similarity index 100%
rename from python/educational-python/resources/fileTemplates/internal/task.md.ft
rename to python/educational-core/resources/fileTemplates/internal/task.md.ft
diff --git a/python/educational-core/resources/icons/com/jetbrains/edu/learning/Stepik.png b/python/educational-core/resources/icons/com/jetbrains/edu/learning/Stepik.png
new file mode 100644
index 000000000000..299f0d979719
Binary files /dev/null and b/python/educational-core/resources/icons/com/jetbrains/edu/learning/Stepik.png differ
diff --git a/python/educational-core/resources/icons/com/jetbrains/edu/learning/Stepik@2x.png b/python/educational-core/resources/icons/com/jetbrains/edu/learning/Stepik@2x.png
new file mode 100644
index 000000000000..60229f83a5ec
Binary files /dev/null and b/python/educational-core/resources/icons/com/jetbrains/edu/learning/Stepik@2x.png differ
diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java
index 61d0323f968c..d1548a4244fe 100644
--- a/python/educational-core/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java
+++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java
@@ -105,8 +105,10 @@ public class CCProjectComponent extends AbstractProjectComponent {
public void projectOpened() {
migrateIfNeeded();
- VirtualFileManager.getInstance().addVirtualFileListener(myTaskFileLifeListener);
- EduUsagesCollector.projectTypeOpened(CCUtils.COURSE_MODE);
+ if (CCUtils.isCourseCreator(myProject)) {
+ VirtualFileManager.getInstance().addVirtualFileListener(myTaskFileLifeListener);
+ EduUsagesCollector.projectTypeOpened(CCUtils.COURSE_MODE);
+ }
}
public void projectClosed() {
diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/CCSubtaskEditorNotificationProvider.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/CCSubtaskEditorNotificationProvider.java
index 8c6c2a49b0fa..6189b8c9186f 100644
--- a/python/educational-core/src/com/jetbrains/edu/coursecreator/CCSubtaskEditorNotificationProvider.java
+++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/CCSubtaskEditorNotificationProvider.java
@@ -28,6 +28,7 @@ import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholderSubtaskInfo;
import com.jetbrains.edu.learning.courseFormat.Lesson;
import com.jetbrains.edu.learning.courseFormat.TaskFile;
+import com.jetbrains.edu.learning.courseFormat.tasks.PyCharmTask;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import com.jetbrains.edu.learning.courseFormat.tasks.TaskWithSubtasks;
import org.jetbrains.annotations.NotNull;
@@ -227,7 +228,7 @@ public class CCSubtaskEditorNotificationProvider extends EditorNotifications.Pro
final Lesson lesson = myTask.getLesson();
final List list = lesson.getTaskList();
final int i = list.indexOf(myTask);
- final Task task = new Task();
+ final Task task = new PyCharmTask();
task.copyTaskParameters(myTask);
for (TaskFile taskFile : task.getTaskFiles().values()) {
taskFile.setTask(task);
diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/CCUtils.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/CCUtils.java
index 0b8815f4aa58..a8be51afe37f 100644
--- a/python/educational-core/src/com/jetbrains/edu/coursecreator/CCUtils.java
+++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/CCUtils.java
@@ -29,6 +29,7 @@ import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.Lesson;
import com.jetbrains.edu.learning.courseFormat.StudyItem;
import com.jetbrains.edu.learning.courseFormat.TaskFile;
+import com.jetbrains.edu.learning.courseFormat.tasks.PyCharmTask;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import org.apache.commons.codec.binary.Base64;
import org.jetbrains.annotations.NotNull;
@@ -264,7 +265,7 @@ public class CCUtils {
final Lesson lesson = new Lesson();
lesson.setName(EduNames.PYCHARM_ADDITIONAL);
- final Task task = new Task();
+ final Task task = new PyCharmTask();
task.setLesson(lesson);
task.setName(EduNames.PYCHARM_ADDITIONAL);
task.setIndex(1);
diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/CCVirtualFileListener.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/CCVirtualFileListener.java
index cfc2e0dd636b..7a2f28b61b4a 100644
--- a/python/educational-core/src/com/jetbrains/edu/coursecreator/CCVirtualFileListener.java
+++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/CCVirtualFileListener.java
@@ -16,8 +16,6 @@ import com.jetbrains.edu.learning.courseFormat.TaskFile;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import org.jetbrains.annotations.NotNull;
-import java.io.File;
-
public class CCVirtualFileListener implements VirtualFileListener {
@Override
@@ -37,7 +35,7 @@ public class CCVirtualFileListener implements VirtualFileListener {
return;
}
Course course = StudyTaskManager.getInstance(project).getCourse();
- if (course == null || !CCUtils.isCourseCreator(project)) {
+ if (course == null) {
return;
}
TaskFile taskFile = StudyUtils.getTaskFile(project, createdFile);
diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java
index 0436abb5132c..09e24daf3360 100644
--- a/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java
+++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java
@@ -15,8 +15,6 @@ import icons.EducationalCoreIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.List;
-
public class CCCreateLesson extends CCCreateStudyItemActionBase {
public static final String TITLE = "Create New " + EduNames.LESSON_TITLED;
@@ -82,8 +80,8 @@ public class CCCreateLesson extends CCCreateStudyItemActionBase {
}
@Override
- protected List extends StudyItem> getSiblings(@NotNull Course course, @Nullable StudyItem parentItem) {
- return course.getLessons(true);
+ protected void sortSiblings(@NotNull Course course, @Nullable StudyItem parentItem) {
+ course.sortLessons();
}
@Override
diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateStudyItemActionBase.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateStudyItemActionBase.java
index 4af27a9a372f..732f6dd904d3 100644
--- a/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateStudyItemActionBase.java
+++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateStudyItemActionBase.java
@@ -18,15 +18,12 @@ import com.jetbrains.edu.coursecreator.CCUtils;
import com.jetbrains.edu.coursecreator.ui.CCCreateStudyItemDialog;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
-import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.StudyItem;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.Collections;
-import java.util.List;
public abstract class CCCreateStudyItemActionBase extends DumbAwareAction {
@@ -50,7 +47,6 @@ public abstract class CCCreateStudyItemActionBase extends DumbAwareAction {
createItem(view, project, directory, course);
}
-
@Override
public void update(@NotNull AnActionEvent event) {
final Presentation presentation = event.getPresentation();
@@ -81,13 +77,11 @@ public abstract class CCCreateStudyItemActionBase extends DumbAwareAction {
presentation.setEnabledAndVisible(true);
}
-
@Nullable
protected abstract PsiDirectory getParentDir(@NotNull final Project project,
@NotNull final Course course,
@NotNull final PsiDirectory directory);
-
@Nullable
public PsiDirectory createItem(@Nullable final IdeView view, @NotNull final Project project,
@NotNull final PsiDirectory sourceDirectory, @NotNull final Course course) {
@@ -103,13 +97,12 @@ public abstract class CCCreateStudyItemActionBase extends DumbAwareAction {
CCUtils.updateHigherElements(parentDir.getVirtualFile().getChildren(), getStudyOrderable(item),
item.getIndex() - 1, getItemName(), 1);
addItem(course, item);
- Collections.sort(getSiblings(course, parentItem), EduUtils.INDEX_COMPARATOR);
+ sortSiblings(course, parentItem);
return createItemDir(project, item, view, parentDir, course);
}
protected abstract void addItem(@NotNull final Course course, @NotNull final StudyItem item);
-
protected abstract Function getStudyOrderable(@NotNull final StudyItem item);
protected abstract PsiDirectory createItemDir(@NotNull final Project project, @NotNull final StudyItem item,
@@ -168,7 +161,7 @@ public abstract class CCCreateStudyItemActionBase extends DumbAwareAction {
@NotNull final Project project,
@NotNull final Course course);
- protected abstract List extends StudyItem> getSiblings(@NotNull final Course course, @Nullable final StudyItem parentItem);
+ protected abstract void sortSiblings(@NotNull final Course course, @Nullable final StudyItem parentItem);
protected abstract String getItemName();
diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java
index 78e74feda957..3f64f5dc4588 100644
--- a/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java
+++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java
@@ -11,13 +11,13 @@ import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.Lesson;
import com.jetbrains.edu.learning.courseFormat.StudyItem;
+import com.jetbrains.edu.learning.courseFormat.tasks.PyCharmTask;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import icons.EducationalCoreIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
-import java.util.List;
public class CCCreateTask extends CCCreateStudyItemActionBase {
public static final String TITLE = "Create New " + EduNames.TASK_TITLED;
@@ -26,9 +26,6 @@ public class CCCreateTask extends CCCreateStudyItemActionBase {
super(EduNames.TASK_TITLED, TITLE, EducationalCoreIcons.Task);
}
-
-
-
@Nullable
@Override
protected PsiDirectory getParentDir(@NotNull Project project, @NotNull Course course, @NotNull PsiDirectory directory) {
@@ -59,8 +56,8 @@ public class CCCreateTask extends CCCreateStudyItemActionBase {
@Override
@Nullable
protected PsiDirectory createItemDir(@NotNull final Project project, @NotNull final StudyItem item,
- @Nullable final IdeView view, @NotNull final PsiDirectory parentDirectory,
- @NotNull final Course course) {
+ @Nullable final IdeView view, @NotNull final PsiDirectory parentDirectory,
+ @NotNull final Course course) {
EduPluginConfigurator configurator = EduPluginConfigurator.INSTANCE.forLanguage(course.getLanguageById());
if (configurator != null) {
return configurator.createTaskContent(project, (Task)item, view, parentDirectory, course);
@@ -100,11 +97,10 @@ public class CCCreateTask extends CCCreateStudyItemActionBase {
}
@Override
- protected List extends StudyItem> getSiblings(@NotNull Course course, @Nullable StudyItem parentItem) {
+ protected void sortSiblings(@NotNull Course course, @Nullable StudyItem parentItem) {
if (parentItem instanceof Lesson) {
- return ((Lesson)parentItem).getTaskList();
+ Collections.sort(((Lesson)parentItem).getTaskList(), EduUtils.INDEX_COMPARATOR);
}
- return Collections.emptyList();
}
@Override
@@ -114,7 +110,7 @@ public class CCCreateTask extends CCCreateStudyItemActionBase {
@Override
protected StudyItem createAndInitItem(@NotNull Course course, @Nullable StudyItem parentItem, String name, int index) {
- final Task task = new Task(name);
+ final Task task = new PyCharmTask(name);
task.setIndex(index);
if (parentItem == null) {
return null;
diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/handlers/CCLessonMoveHandlerDelegate.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/handlers/CCLessonMoveHandlerDelegate.java
index 3b163cd947ca..ebe4603afc9c 100644
--- a/python/educational-core/src/com/jetbrains/edu/coursecreator/handlers/CCLessonMoveHandlerDelegate.java
+++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/handlers/CCLessonMoveHandlerDelegate.java
@@ -22,14 +22,12 @@ import com.jetbrains.edu.coursecreator.CCUtils;
import com.jetbrains.edu.coursecreator.ui.CCMoveStudyItemDialog;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.core.EduNames;
-import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.Lesson;
import com.jetbrains.edu.learning.courseFormat.StudyItem;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
-import java.util.Collections;
public class CCLessonMoveHandlerDelegate extends MoveHandlerDelegate {
@@ -109,7 +107,7 @@ public class CCLessonMoveHandlerDelegate extends MoveHandlerDelegate {
newItemIndex - 1, EduNames.LESSON, 1);
sourceLesson.setIndex(newItemIndex);
- Collections.sort(course.getLessons(true), EduUtils.INDEX_COMPARATOR);
+ course.sortLessons();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
diff --git a/python/educational-core/src/com/jetbrains/edu/coursecreator/stepik/CCStepicConnector.java b/python/educational-core/src/com/jetbrains/edu/coursecreator/stepik/CCStepicConnector.java
index c5ac73922cb9..3ce6f33d90cb 100644
--- a/python/educational-core/src/com/jetbrains/edu/coursecreator/stepik/CCStepicConnector.java
+++ b/python/educational-core/src/com/jetbrains/edu/coursecreator/stepik/CCStepicConnector.java
@@ -108,6 +108,7 @@ public class CCStepicConnector {
postedCourse.setLessons(course.getLessons(true));
postedCourse.setAuthors(course.getAuthors());
postedCourse.setCourseMode(CCUtils.COURSE_MODE);
+ postedCourse.setLanguage(course.getLanguageID());
final int sectionId = postModule(postedCourse.getId(), 1, String.valueOf(postedCourse.getName()));
int position = 1;
for (Lesson lesson : course.getLessons()) {
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/EduPluginConfigurator.java b/python/educational-core/src/com/jetbrains/edu/learning/EduPluginConfigurator.java
index aaa21bbf5ead..c41739bef591 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/EduPluginConfigurator.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/EduPluginConfigurator.java
@@ -105,7 +105,6 @@ public interface EduPluginConfigurator {
}
group.add(action);
}
- group.add(new StudyRunAction());
group.add(new StudyEditInputAction());
return group;
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/StudySerializationUtils.java b/python/educational-core/src/com/jetbrains/edu/learning/StudySerializationUtils.java
index 043625347769..fb5f151f69dd 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/StudySerializationUtils.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/StudySerializationUtils.java
@@ -97,6 +97,7 @@ public class StudySerializationUtils {
private static String THEORY_TAG = "theoryTask";
private static String ADAPTIVE_TASK_PARAMETERS = "adaptiveTaskParameters";
private static String ADAPTIVE = "adaptive";
+ public static final String PYCHARM_TASK = "PyCharmTask";
private static String TASK_WITH_SUBTASKS = "TaskWithSubtasks";
private static String THEORY_TASK = "TheoryTask";
private static String CHOICE_TASK = "ChoiceTask";
@@ -285,6 +286,9 @@ public class StudySerializationUtils {
else if (Boolean.valueOf(adaptive.getAttributeValue(VALUE))) {
task.setName(CODE_TASK);
}
+ else {
+ task.setName(PYCHARM_TASK);
+ }
task.removeContent(adaptiveParams);
task.removeContent(theoryTask);
}
@@ -638,7 +642,7 @@ public class StudySerializationUtils {
case "choice": return gson.fromJson(json, ChoiceTask.class);
case "theory": return gson.fromJson(json, TheoryTask.class);
case "code": return gson.fromJson(json, CodeTask.class);
- case "pycharm": return gson.fromJson(json, Task.class);
+ case "pycharm": return gson.fromJson(json, PyCharmTask.class);
case "subtasks": return gson.fromJson(json, TaskWithSubtasks.class);
default: {
LOG.warn("Unsupported task type " + taskType);
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/StudyUtils.java b/python/educational-core/src/com/jetbrains/edu/learning/StudyUtils.java
index 8909c6936fd7..46d3ca1b1fc2 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/StudyUtils.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/StudyUtils.java
@@ -1,15 +1,11 @@
package com.jetbrains.edu.learning;
-import com.intellij.execution.RunContentExecutor;
-import com.intellij.execution.configurations.GeneralCommandLine;
-import com.intellij.execution.process.ProcessHandler;
import com.intellij.ide.IdeView;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.fileTemplates.FileTemplateUtil;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.util.EditorHelper;
-import com.intellij.lang.Language;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
@@ -31,7 +27,6 @@ import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupFactory;
@@ -61,8 +56,6 @@ import com.intellij.util.TimeoutUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.MarkdownUtil;
import com.intellij.util.ui.UIUtil;
-import com.jetbrains.edu.learning.checker.StudyExecutor;
-import com.jetbrains.edu.learning.checker.StudyTestRunner;
import com.jetbrains.edu.learning.core.EduAnswerPlaceholderDeleteHandler;
import com.jetbrains.edu.learning.core.EduAnswerPlaceholderPainter;
import com.jetbrains.edu.learning.core.EduNames;
@@ -237,42 +230,6 @@ public class StudyUtils {
}
}
- @Nullable
- public static Sdk findSdk(@NotNull final Task task, @NotNull final Project project) {
- final Language language = task.getLesson().getCourse().getLanguageById();
- return StudyExecutor.INSTANCE.forLanguage(language).findSdk(project);
- }
-
- @NotNull
- public static StudyTestRunner getTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
- final Language language = task.getLesson().getCourse().getLanguageById();
- return StudyExecutor.INSTANCE.forLanguage(language).getTestRunner(task, taskDir);
- }
-
- public static RunContentExecutor getExecutor(@NotNull final Project project, @NotNull final Task currentTask,
- @NotNull final ProcessHandler handler) {
- final Language language = currentTask.getLesson().getCourse().getLanguageById();
- return StudyExecutor.INSTANCE.forLanguage(language).getExecutor(project, handler);
- }
-
- public static void setCommandLineParameters(@NotNull final GeneralCommandLine cmd,
- @NotNull final Project project,
- @NotNull final String filePath,
- @NotNull final String sdkPath,
- @NotNull final Task currentTask) {
- final Language language = currentTask.getLesson().getCourse().getLanguageById();
- StudyExecutor.INSTANCE.forLanguage(language).setCommandLineParameters(cmd, project, filePath, sdkPath, currentTask);
- }
-
- public static void showNoSdkNotification(@NotNull final Task currentTask, @NotNull final Project project) {
- final Lesson lesson = currentTask.getLesson();
- if (lesson == null) return;
- final Course course = lesson.getCourse();
- if (course == null) return;
- final Language language = course.getLanguageById();
- StudyExecutor.INSTANCE.forLanguage(language).showNoSdkNotification(project);
- }
-
/**
* shows pop up in the center of "check task" button in study editor
@@ -735,7 +692,7 @@ public class StudyUtils {
}
public static void registerStudyToolWindow(@Nullable final Course course, Project project) {
- if (course != null && "PyCharm".equals(course.getCourseType())) {
+ if (course != null && EduNames.PYCHARM.equals(course.getCourseType())) {
final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
registerToolWindows(toolWindowManager, project);
final ToolWindow studyToolWindow = toolWindowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW);
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java b/python/educational-core/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java
index 984d1a5dd699..abf32c6c97e5 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java
@@ -13,7 +13,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
-import com.jetbrains.edu.learning.StudyCheckListener;
+import com.jetbrains.edu.learning.checker.StudyCheckListener;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.checker.StudyCheckUtils;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/actions/StudyRunAction.java b/python/educational-core/src/com/jetbrains/edu/learning/actions/StudyRunAction.java
deleted file mode 100644
index a565dadd4528..000000000000
--- a/python/educational-core/src/com/jetbrains/edu/learning/actions/StudyRunAction.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package com.jetbrains.edu.learning.actions;
-
-import com.intellij.execution.ExecutionException;
-import com.intellij.execution.RunContentExecutor;
-import com.intellij.execution.configurations.GeneralCommandLine;
-import com.intellij.execution.process.OSProcessHandler;
-import com.intellij.execution.process.ProcessHandler;
-import com.intellij.execution.process.ProcessListener;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.project.DumbAwareAction;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.Sdk;
-import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.jetbrains.edu.learning.core.EduUtils;
-import com.jetbrains.edu.learning.courseFormat.tasks.Task;
-import com.jetbrains.edu.learning.courseFormat.TaskFile;
-import com.jetbrains.edu.learning.StudyTaskManager;
-import com.jetbrains.edu.learning.StudyUtils;
-import com.jetbrains.edu.learning.courseFormat.UserTest;
-import com.jetbrains.edu.learning.editor.StudyEditor;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.LinkedList;
-import java.util.List;
-
-public class StudyRunAction extends DumbAwareAction {
- private static final Logger LOG = Logger.getInstance(StudyRunAction.class.getName());
- public static final String ACTION_ID = "StudyRunAction";
- private ProcessHandler myHandler;
- private List myProcessListeners = new LinkedList<>();
-
- public StudyRunAction() {
- super("Run File With Tests", "Run your code with tests", AllIcons.General.Run);
- }
-
- public void run(@NotNull final Project project) {
- if (myHandler != null && !myHandler.isProcessTerminated()) return;
- Editor selectedEditor = StudyUtils.getSelectedEditor(project);
- FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
- assert selectedEditor != null;
- VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
-
- if (openedFile != null && openedFile.getCanonicalPath() != null) {
- String filePath = openedFile.getCanonicalPath();
- executeFile(project, openedFile, filePath);
- }
- }
-
- private void executeFile(@NotNull final Project project,
- @NotNull final VirtualFile openedFile, @NotNull final String filePath) {
- GeneralCommandLine cmd = new GeneralCommandLine();
- cmd.withWorkDirectory(openedFile.getParent().getCanonicalPath());
-
- TaskFile selectedTaskFile = StudyUtils.getTaskFile(project, openedFile);
- assert selectedTaskFile != null;
- final Task currentTask = selectedTaskFile.getTask();
- final Sdk sdk = StudyUtils.findSdk(currentTask, project);
- if (sdk == null) {
- StudyUtils.showNoSdkNotification(currentTask, project);
- return;
- }
- String sdkHomePath = sdk.getHomePath();
- if (sdkHomePath != null) {
- cmd.setExePath(sdkHomePath);
- StudyUtils.setCommandLineParameters(cmd, project, filePath, sdkHomePath, currentTask);
-
- try {
- myHandler = new OSProcessHandler(cmd);
- }
- catch (ExecutionException e) {
- LOG.error(e);
- return;
- }
-
- for (ProcessListener processListener : myProcessListeners) {
- myHandler.addProcessListener(processListener);
- }
-
- final RunContentExecutor executor = StudyUtils.getExecutor(project, currentTask, myHandler);
- if (executor != null) {
- Disposer.register(project, executor);
- executor.run();
- }
- EduUtils.synchronize();
- }
- }
-
- public void addProcessListener(@NotNull final ProcessListener processListener) {
- myProcessListeners.add(processListener);
- }
-
- public void removeProcessListener(@NotNull final ProcessListener processListener) {
- myProcessListeners.remove(processListener);
- }
-
- public void actionPerformed(@NotNull AnActionEvent e) {
- final Project project = e.getProject();
- if (project != null) {
- run(project);
- }
- }
-
- @Override
- public void update(AnActionEvent e) {
- EduUtils.enableAction(e, false);
-
- final Project project = e.getProject();
- if (project != null) {
- StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
- if (studyEditor != null) {
- final List userTests = StudyTaskManager.getInstance(project).getUserTests(studyEditor.getTaskFile().getTask());
- if (!userTests.isEmpty()) {
- EduUtils.enableAction(e, true);
- }
- }
- }
- }
-}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/StudyCheckListener.java b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckListener.java
similarity index 91%
rename from python/educational-core/src/com/jetbrains/edu/learning/StudyCheckListener.java
rename to python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckListener.java
index d4896f864d27..e4f2fa636028 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/StudyCheckListener.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckListener.java
@@ -1,4 +1,4 @@
-package com.jetbrains.edu.learning;
+package com.jetbrains.edu.learning.checker;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java
index 0c070df1cb99..09e411d82931 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java
@@ -3,29 +3,24 @@ package com.jetbrains.edu.learning.checker;
import com.intellij.execution.process.CapturingProcessHandler;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.ide.projectView.ProjectView;
-import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
-import com.jetbrains.edu.learning.*;
-import com.jetbrains.edu.learning.actions.StudyRunAction;
+import com.jetbrains.edu.learning.StudySettings;
+import com.jetbrains.edu.learning.StudyState;
+import com.jetbrains.edu.learning.StudyTaskManager;
+import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.core.EduUtils;
-import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.StudyStatus;
-import com.jetbrains.edu.learning.courseFormat.TaskFile;
import com.jetbrains.edu.learning.courseFormat.tasks.ChoiceTask;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
-import com.jetbrains.edu.learning.courseFormat.tasks.TaskWithSubtasks;
import com.jetbrains.edu.learning.courseFormat.tasks.TheoryTask;
import com.jetbrains.edu.learning.stepic.EduAdaptiveStepicConnector;
import com.jetbrains.edu.learning.stepic.EduStepicConnector;
@@ -33,8 +28,6 @@ import com.jetbrains.edu.learning.stepic.StepicUser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Map;
-
public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroundable {
private static final Logger LOG = Logger.getInstance(StudyCheckTask.class);
@@ -47,9 +40,7 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun
private final Ref myCheckInProcess;
private final Process myTestProcess;
private final String myCommandLine;
- private boolean myRunTestFile = true;
private static final String FAILED_CHECK_LAUNCH = "Failed to launch checking";
- private static final String DO_NOT_RUN_ON_CHECK = "DO_NOT_RUN_ON_CHECK";
public StudyCheckTask(Project project, StudyState studyState, Ref checkInProcess, Process testProcess, String commandLine) {
super(project, "Checking Task");
@@ -98,9 +89,6 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun
private void checkForEduCourse(@NotNull ProgressIndicator indicator) {
final StudyTestsOutputParser.TestsOutput testsOutput = getTestOutput(indicator);
- if (myRunTestFile) {
- ApplicationManager.getApplication().invokeLater(() -> runTask(myProject));
- }
if (testsOutput != null) {
if (testsOutput.isSuccess()) {
onTaskSolved(testsOutput.getMessage());
@@ -119,14 +107,6 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun
}
}
- private static void runTask(@NotNull Project project) {
- final StudyRunAction runAction = (StudyRunAction)ActionManager.getInstance().getAction(StudyRunAction.ACTION_ID);
- if (runAction == null) {
- return;
- }
- runAction.run(project);
- }
-
@Nullable
private StudyTestsOutputParser.TestsOutput getTestOutput(@NotNull ProgressIndicator indicator) {
final CapturingProcessHandler handler = new CapturingProcessHandler(myTestProcess, null, myCommandLine);
@@ -135,7 +115,6 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun
ApplicationManager.getApplication().invokeLater(
() -> StudyCheckUtils.showTestResultPopUp("Check cancelled", MessageType.WARNING.getPopupBackground(), myProject));
}
- myRunTestFile = !output.getStdout().contains(DO_NOT_RUN_ON_CHECK);
final Course course = StudyTaskManager.getInstance(myProject).getCourse();
if (course != null) {
final StudyTestsOutputParser.TestsOutput testsOutput = StudyTestsOutputParser.getTestsOutput(output, course.isAdaptive());
@@ -173,7 +152,8 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun
if (reactionPosted) {
if (myStatusBeforeCheck != StudyStatus.Solved) {
myTask.setStatus(StudyStatus.Solved);
- EduAdaptiveStepicConnector.addNextRecommendedTask(myProject, indicator, EduAdaptiveStepicConnector.NEXT_RECOMMENDATION_REACTION);
+ EduAdaptiveStepicConnector.addNextRecommendedTask(myProject, myTask.getLesson(), indicator,
+ EduAdaptiveStepicConnector.NEXT_RECOMMENDATION_REACTION);
}
}
else {
@@ -203,7 +183,8 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun
if (pair.getFirst()) {
onTaskSolved("Congratulations! Remote tests passed.");
if (myStatusBeforeCheck != StudyStatus.Solved) {
- EduAdaptiveStepicConnector.addNextRecommendedTask(myProject, indicator, EduAdaptiveStepicConnector.NEXT_RECOMMENDATION_REACTION);
+ EduAdaptiveStepicConnector.addNextRecommendedTask(myProject, myTask.getLesson(), indicator,
+ EduAdaptiveStepicConnector.NEXT_RECOMMENDATION_REACTION);
}
}
else {
@@ -224,91 +205,13 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun
}
protected void onTaskFailed(@NotNull String message) {
- final Course course = StudyTaskManager.getInstance(myProject).getCourse();
myTask.setStatus(StudyStatus.Failed);
- if (course != null) {
- if (course.isAdaptive()) {
- ApplicationManager.getApplication().invokeLater(
- () -> {
- StudyCheckUtils.showTestResultPopUp("Failed", MessageType.ERROR.getPopupBackground(), myProject);
- StudyCheckUtils.showTestResultsToolWindow(myProject, message, false);
- });
- }
- else {
- ApplicationManager.getApplication()
- .invokeLater(() -> StudyCheckUtils.showTestResultPopUp(message, MessageType.ERROR.getPopupBackground(), myProject));
- }
- }
+ myTask.getChecker(myProject).onTaskFailed(message);
}
protected void onTaskSolved(@NotNull String message) {
- final Course course = StudyTaskManager.getInstance(myProject).getCourse();
myTask.setStatus(StudyStatus.Solved);
- if (course != null) {
- if (course.isAdaptive()) {
- ApplicationManager.getApplication().invokeLater(
- () -> {
- if (myTask instanceof ChoiceTask) {
- StudyCheckUtils.showTestResultPopUp("Congratulations!", MessageType.INFO.getPopupBackground(), myProject);
- }
- else {
- StudyCheckUtils.showTestResultPopUp("Congratulations!", MessageType.INFO.getPopupBackground(), myProject);
- StudyCheckUtils.showTestResultsToolWindow(myProject, message, true);
- }
- });
- }
- else {
- if (myTask instanceof TaskWithSubtasks) {
- boolean hasMoreSubtasks = ((TaskWithSubtasks)myTask).activeSubtaskNotLast();
- final int activeSubtaskIndex = ((TaskWithSubtasks)myTask).getActiveSubtaskIndex();
- int visibleSubtaskIndex = activeSubtaskIndex + 1;
-
- ApplicationManager.getApplication().invokeLater(() -> {
- int subtaskSize = ((TaskWithSubtasks)myTask).getLastSubtaskIndex() + 1;
- String resultMessage = !hasMoreSubtasks ? message : "Subtask " + visibleSubtaskIndex + "/" + subtaskSize + " solved";
- StudyCheckUtils.showTestResultPopUp(resultMessage, MessageType.INFO.getPopupBackground(), myProject);
- if (hasMoreSubtasks) {
- int nextSubtaskIndex = activeSubtaskIndex + 1;
- StudySubtaskUtils.switchStep(myProject, (TaskWithSubtasks)myTask, nextSubtaskIndex);
- rememberAnswers(nextSubtaskIndex);
- }
- });
- }
- else {
- ApplicationManager.getApplication().invokeLater(
- () -> StudyCheckUtils.showTestResultPopUp(message, MessageType.INFO.getPopupBackground(), myProject));
- }
- }
- }
- }
-
- private void rememberAnswers(int nextSubtaskIndex) {
- VirtualFile taskDir = myTask.getTaskDir(myProject);
- if (taskDir == null) {
- return;
- }
- VirtualFile srcDir = taskDir.findChild(EduNames.SRC);
- if (srcDir != null) {
- taskDir = srcDir;
- }
- for (Map.Entry entry : myTask.getTaskFiles().entrySet()) {
- TaskFile taskFile = entry.getValue();
- VirtualFile virtualFile = taskDir.findFileByRelativePath(entry.getKey());
- if (virtualFile == null) {
- continue;
- }
- Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
- if (document == null) {
- continue;
- }
- for (AnswerPlaceholder placeholder : taskFile.getActivePlaceholders()) {
- if (placeholder.getSubtaskInfos().containsKey(nextSubtaskIndex - 1)) {
- int offset = placeholder.getOffset();
- String answer = document.getText(TextRange.create(offset, offset + placeholder.getRealLength()));
- placeholder.getSubtaskInfos().get(nextSubtaskIndex - 1).setAnswer(answer);
- }
- }
- }
+ myTask.getChecker(myProject).onTaskSolved(message);
}
private void runAfterTaskCheckedActions() {
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java
index 7ba9aef911f5..714433bcb03b 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java
@@ -28,8 +28,8 @@ import com.jetbrains.edu.learning.core.EduDocumentListener;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
-import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import com.jetbrains.edu.learning.courseFormat.TaskFile;
+import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import com.jetbrains.edu.learning.editor.StudyEditor;
import com.jetbrains.edu.learning.navigation.StudyNavigator;
import com.jetbrains.edu.learning.ui.StudyTestResultsToolWindowFactory;
@@ -108,7 +108,7 @@ public class StudyCheckUtils {
}
- public static void showTestResultPopUp(final String text, Color color, @NotNull final Project project) {
+ public static void showTestResultPopUp(@NotNull final String text, Color color, @NotNull final Project project) {
BalloonBuilder balloonBuilder =
JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, null, color, null);
final Balloon balloon = balloonBuilder.createBalloon();
@@ -201,30 +201,26 @@ public class StudyCheckUtils {
}
}
- public static void showTestResultsToolWindow(@NotNull final Project project, @NotNull final String message, boolean solved) {
- final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
- ToolWindow window = toolWindowManager.getToolWindow(StudyTestResultsToolWindowFactoryKt.ID);
- if (window == null) {
- toolWindowManager.registerToolWindow(StudyTestResultsToolWindowFactoryKt.ID, true, ToolWindowAnchor.BOTTOM);
- window = toolWindowManager.getToolWindow(StudyTestResultsToolWindowFactoryKt.ID);
- new StudyTestResultsToolWindowFactory().createToolWindowContent(project, window);
- }
-
- final Content[] contents = window.getContentManager().getContents();
- for (Content content : contents) {
- final JComponent component = content.getComponent();
- if (component instanceof ConsoleViewImpl) {
- ((ConsoleViewImpl)component).clear();
- if (!solved) {
- ((ConsoleViewImpl)component).print(message, ConsoleViewContentType.ERROR_OUTPUT);
- }
- else {
- ((ConsoleViewImpl)component).print(message, ConsoleViewContentType.NORMAL_OUTPUT);
- }
- window.setAvailable(true, () -> {});
- window.show(() -> {});
- return;
+ public static void showTestResultsToolWindow(@NotNull final Project project, @NotNull final String message) {
+ ApplicationManager.getApplication().invokeLater(() -> {
+ final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
+ ToolWindow window = toolWindowManager.getToolWindow(StudyTestResultsToolWindowFactoryKt.ID);
+ if (window == null) {
+ toolWindowManager.registerToolWindow(StudyTestResultsToolWindowFactoryKt.ID, true, ToolWindowAnchor.BOTTOM);
+ window = toolWindowManager.getToolWindow(StudyTestResultsToolWindowFactoryKt.ID);
+ new StudyTestResultsToolWindowFactory().createToolWindowContent(project, window);
}
- }
+
+ final Content[] contents = window.getContentManager().getContents();
+ for (Content content : contents) {
+ final JComponent component = content.getComponent();
+ if (component instanceof ConsoleViewImpl) {
+ ((ConsoleViewImpl)component).clear();
+ ((ConsoleViewImpl)component).print(message, ConsoleViewContentType.ERROR_OUTPUT);
+ window.setAvailable(true,null);
+ window.show(null);
+ }
+ }
+ });
}
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyExecutor.java b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyExecutor.java
deleted file mode 100644
index 8e27c2bedd79..000000000000
--- a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyExecutor.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2000-2014 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.jetbrains.edu.learning.checker;
-
-import com.intellij.execution.RunContentExecutor;
-import com.intellij.execution.configurations.GeneralCommandLine;
-import com.intellij.execution.process.ProcessHandler;
-import com.intellij.lang.LanguageExtension;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.Sdk;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.jetbrains.edu.learning.courseFormat.tasks.Task;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public interface StudyExecutor {
- LanguageExtension INSTANCE = new LanguageExtension<>("Edu.StudyExecutor");
-
- @Nullable
- Sdk findSdk(@NotNull final Project project);
-
- StudyTestRunner getTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir);
-
- RunContentExecutor getExecutor(@NotNull final Project project, @NotNull final ProcessHandler handler);
-
- void setCommandLineParameters(@NotNull final GeneralCommandLine cmd,
- @NotNull final Project project,
- @NotNull final String filePath,
- @NotNull final String sdkPath,
- @NotNull final Task currentTask);
-
- void showNoSdkNotification(@NotNull final Project project);
-}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyTaskChecker.java b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyTaskChecker.java
new file mode 100644
index 000000000000..879621a1a725
--- /dev/null
+++ b/python/educational-core/src/com/jetbrains/edu/learning/checker/StudyTaskChecker.java
@@ -0,0 +1,27 @@
+package com.jetbrains.edu.learning.checker;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.jetbrains.edu.learning.courseFormat.tasks.Task;
+import org.jetbrains.annotations.NotNull;
+
+public class StudyTaskChecker {
+ @NotNull protected final T myTask;
+ @NotNull protected final Project myProject;
+
+ public StudyTaskChecker(@NotNull T task, @NotNull Project project) {
+ myTask = task;
+ myProject = project;
+ }
+
+ public void onTaskSolved(@NotNull String message) {
+ ApplicationManager.getApplication().invokeLater(
+ () -> StudyCheckUtils.showTestResultPopUp(message, MessageType.INFO.getPopupBackground(), myProject));
+ }
+
+ public void onTaskFailed(@NotNull String message) {
+ ApplicationManager.getApplication()
+ .invokeLater(() -> StudyCheckUtils.showTestResultPopUp(message, MessageType.ERROR.getPopupBackground(), myProject));
+ }
+}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/checker/TaskWithSubtasksChecker.java b/python/educational-core/src/com/jetbrains/edu/learning/checker/TaskWithSubtasksChecker.java
new file mode 100644
index 000000000000..f18b15fe2eff
--- /dev/null
+++ b/python/educational-core/src/com/jetbrains/edu/learning/checker/TaskWithSubtasksChecker.java
@@ -0,0 +1,70 @@
+package com.jetbrains.edu.learning.checker;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.edu.learning.StudySubtaskUtils;
+import com.jetbrains.edu.learning.core.EduNames;
+import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
+import com.jetbrains.edu.learning.courseFormat.TaskFile;
+import com.jetbrains.edu.learning.courseFormat.tasks.TaskWithSubtasks;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+
+public class TaskWithSubtasksChecker extends StudyTaskChecker {
+ public TaskWithSubtasksChecker(@NotNull TaskWithSubtasks task,
+ @NotNull Project project) {
+ super(task, project);
+ }
+
+ @Override
+ public void onTaskSolved(@NotNull String message) {
+ boolean hasMoreSubtasks = myTask.activeSubtaskNotLast();
+ final int activeSubtaskIndex = myTask.getActiveSubtaskIndex();
+ int visibleSubtaskIndex = activeSubtaskIndex + 1;
+ ApplicationManager.getApplication().invokeLater(() -> {
+ int subtaskSize = myTask.getLastSubtaskIndex() + 1;
+ String resultMessage = !hasMoreSubtasks ? message : "Subtask " + visibleSubtaskIndex + "/" + subtaskSize + " solved";
+ StudyCheckUtils.showTestResultPopUp(resultMessage, MessageType.INFO.getPopupBackground(), myProject);
+ if (hasMoreSubtasks) {
+ int nextSubtaskIndex = activeSubtaskIndex + 1;
+ StudySubtaskUtils.switchStep(myProject, myTask, nextSubtaskIndex);
+ rememberAnswers(nextSubtaskIndex, myTask);
+ }
+ });
+ }
+
+ private void rememberAnswers(int nextSubtaskIndex, @NotNull TaskWithSubtasks task) {
+ VirtualFile taskDir = task.getTaskDir(myProject);
+ if (taskDir == null) {
+ return;
+ }
+ VirtualFile srcDir = taskDir.findChild(EduNames.SRC);
+ if (srcDir != null) {
+ taskDir = srcDir;
+ }
+ for (Map.Entry entry : task.getTaskFiles().entrySet()) {
+ TaskFile taskFile = entry.getValue();
+ VirtualFile virtualFile = taskDir.findFileByRelativePath(entry.getKey());
+ if (virtualFile == null) {
+ continue;
+ }
+ Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
+ if (document == null) {
+ continue;
+ }
+ for (AnswerPlaceholder placeholder : taskFile.getActivePlaceholders()) {
+ if (placeholder.getSubtaskInfos().containsKey(nextSubtaskIndex - 1)) {
+ int offset = placeholder.getOffset();
+ String answer = document.getText(TextRange.create(offset, offset + placeholder.getRealLength()));
+ placeholder.getSubtaskInfos().get(nextSubtaskIndex - 1).setAnswer(answer);
+ }
+ }
+ }
+ }
+}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/core/EduNames.java b/python/educational-core/src/com/jetbrains/edu/learning/core/EduNames.java
index 29a0cc2c7470..c2c35a63b217 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/core/EduNames.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/core/EduNames.java
@@ -35,7 +35,6 @@ public class EduNames {
public static final String WINDOWS_POSTFIX = "_windows";
public static final String ANSWERS_POSTFIX = "_answers";
public static final String USER_TESTS = "userTests";
- public static final String TESTS_FILE = "tests.py";
public static final String TEST_HELPER = "test_helper.py";
public static final String COURSE_META_FILE = "course.json";
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/Course.java b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/Course.java
index 9e4efbe46f33..d203b338f186 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/Course.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/Course.java
@@ -44,13 +44,19 @@ public class Course {
}
}
+ /**
+ * exclude service lesson containing additional files for the course. Returns lessons copy.
+ */
public List getLessons() {
return getLessons(false);
}
+ /**
+ * returns service lesson as well. Meant to be used in project generation/serialization
+ */
public List getLessons(boolean withAdditional) {
- return withAdditional ? lessons
- : lessons.stream().filter(lesson -> !EduNames.PYCHARM_ADDITIONAL.equals(lesson.getName())).collect(Collectors.toList());
+ return withAdditional ? lessons : lessons.stream().filter(lesson -> !EduNames.PYCHARM_ADDITIONAL.equals(lesson.getName()))
+ .collect(Collectors.toList());
}
public void setLessons(List lessons) {
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/Lesson.java b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/Lesson.java
index 18692467e3ee..4109a93be0d9 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/Lesson.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/Lesson.java
@@ -28,7 +28,7 @@ public class Lesson implements StudyItem {
@Expose
@SerializedName("task_list")
@AbstractCollection(elementTypes = {
- Task.class,
+ PyCharmTask.class,
ChoiceTask.class,
TheoryTask.class,
CodeTask.class,
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/RemoteCourse.java b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/RemoteCourse.java
index 01e764610e62..dd0f7bb26c53 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/RemoteCourse.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/RemoteCourse.java
@@ -2,9 +2,15 @@ package com.jetbrains.edu.learning.courseFormat;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
+import com.intellij.openapi.progress.EmptyProgressIndicator;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task.Backgroundable;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import com.jetbrains.edu.learning.stepic.EduStepicConnector;
+import com.jetbrains.edu.learning.stepic.EduStepicNames;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Date;
@@ -12,12 +18,14 @@ import java.util.List;
public class RemoteCourse extends Course {
//course type in format "pycharm"
- @SerializedName("course_format") private String myType = "pycharm" + EduStepicConnector.CURRENT_VERSION + " Python";
+ @SerializedName("course_format") private String myType =
+ String.format("%s%d %s", EduStepicNames.PYCHARM_PREFIX, EduStepicConnector.CURRENT_VERSION, getLanguageID());
@SerializedName("is_idea_compatible") private boolean isCompatible = true;
List sections;
List instructors = new ArrayList<>();
@Expose private int id;
@Expose @SerializedName("update_date") private Date myUpdateDate;
+ private Boolean isUpToDate = true;
@Expose private boolean isAdaptive = false;
@SerializedName("is_public") boolean isPublic;
@@ -25,6 +33,11 @@ public class RemoteCourse extends Course {
return myType;
}
+ public void setLanguage(@NotNull final String language) {
+ super.setLanguage(language);
+ updateType(language);
+ }
+
public List getSections() {
return sections;
}
@@ -45,14 +58,24 @@ public class RemoteCourse extends Course {
public boolean isUpToDate() {
if (id == 0) return true;
if (!EduNames.STUDY.equals(courseMode)) return true;
- final Date date = EduStepicConnector.getCourseUpdateDate(id);
- if (date == null) return true;
- if (myUpdateDate == null) return true;
- if (date.after(myUpdateDate)) return false;
- for (Lesson lesson : lessons) {
- if (!lesson.isUpToDate()) return false;
- }
- return true;
+
+ ProgressManager.getInstance().runProcessWithProgressAsynchronously(new Backgroundable(null, "Updating Course") {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ final Date date = EduStepicConnector.getCourseUpdateDate(id);
+ if (date == null) return;
+ if (date.after(myUpdateDate)) {
+ isUpToDate = false;
+ }
+ for (Lesson lesson : lessons) {
+ if (!lesson.isUpToDate()) {
+ isUpToDate = false;
+ }
+ }
+ }
+ }, new EmptyProgressIndicator());
+
+ return isUpToDate;
}
public void setUpdated() {
@@ -91,8 +114,10 @@ public class RemoteCourse extends Course {
public void copyCourseParameters(RemoteCourse course) {
setName(course.getName());
-
setUpdateDate(course.getUpdateDate());
+ }
+ private void updateType(String language) {
+ myType = String.format("%s%d %s", EduStepicNames.PYCHARM_PREFIX, EduStepicConnector.CURRENT_VERSION, language);
}
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/ChoiceTask.java b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/ChoiceTask.java
index f7ce2ae9a162..476af7826116 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/ChoiceTask.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/ChoiceTask.java
@@ -2,6 +2,11 @@ package com.jetbrains.edu.learning.courseFormat.tasks;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
+import com.intellij.openapi.project.Project;
+import com.jetbrains.edu.learning.StudyUtils;
+import com.jetbrains.edu.learning.checker.StudyTaskChecker;
+import com.jetbrains.edu.learning.editor.StudyChoiceVariantsPanel;
+import com.jetbrains.edu.learning.ui.StudyToolWindow;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -48,4 +53,22 @@ public class ChoiceTask extends Task {
public String getTaskType() {
return "choice";
}
+
+ @Override
+ public StudyTaskChecker getChecker(@NotNull Project project) {
+ return new StudyTaskChecker(this, project) {
+ @Override
+ public void onTaskFailed(@NotNull String message) {
+ super.onTaskFailed(message);
+ repaintChoicePanel(project, myTask);
+ }
+
+ private void repaintChoicePanel(@NotNull Project project, @NotNull ChoiceTask task) {
+ final StudyToolWindow toolWindow = StudyUtils.getStudyToolWindow(project);
+ if (toolWindow != null) {
+ toolWindow.setBottomComponent(new StudyChoiceVariantsPanel(task));
+ }
+ }
+ };
+ }
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/CodeTask.java b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/CodeTask.java
index fb2d701cb6ac..b82c478c43d9 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/CodeTask.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/CodeTask.java
@@ -1,5 +1,8 @@
package com.jetbrains.edu.learning.courseFormat.tasks;
+import com.intellij.openapi.project.Project;
+import com.jetbrains.edu.learning.checker.StudyCheckUtils;
+import com.jetbrains.edu.learning.checker.StudyTaskChecker;
import org.jetbrains.annotations.NotNull;
public class CodeTask extends Task {
@@ -14,4 +17,15 @@ public class CodeTask extends Task {
public String getTaskType() {
return "code";
}
+
+ @Override
+ public StudyTaskChecker getChecker(@NotNull Project project) {
+ return new StudyTaskChecker(this, project) {
+ @Override
+ public void onTaskFailed(@NotNull String message) {
+ super.onTaskFailed("Wrong solution");
+ StudyCheckUtils.showTestResultsToolWindow(myProject, message);
+ }
+ };
+ }
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/PyCharmTask.java b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/PyCharmTask.java
new file mode 100644
index 000000000000..7ec30c7bf90f
--- /dev/null
+++ b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/PyCharmTask.java
@@ -0,0 +1,21 @@
+package com.jetbrains.edu.learning.courseFormat.tasks;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Original PyCharm Edu tasks with local tests and answer placeholders
+ */
+public class PyCharmTask extends Task {
+
+ public PyCharmTask() {
+ }
+
+ public PyCharmTask(@NotNull String name) {
+ super(name);
+ }
+
+ @Override
+ public String getTaskType() {
+ return "pycharm";
+ }
+}
\ No newline at end of file
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/Task.java b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/Task.java
index e3561075e1bf..4bfc083c656e 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/Task.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/Task.java
@@ -2,12 +2,15 @@ package com.jetbrains.edu.learning.courseFormat.tasks;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
+import com.intellij.lang.Language;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.xmlb.XmlSerializer;
import com.intellij.util.xmlb.annotations.Transient;
+import com.jetbrains.edu.learning.checker.StudyTaskChecker;
+import com.jetbrains.edu.learning.EduPluginConfigurator;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.*;
import com.jetbrains.edu.learning.stepic.EduStepicConnector;
@@ -27,7 +30,7 @@ import java.util.Map;
* - go to Lesson and update elementTypes in taskList AbstractCollection. Needed for proper xml serialization
* - Update TaskSerializer and TaskDeserializer in StudySerializationUtil to handle json serialization
*/
-public class Task implements StudyItem {
+public abstract class Task implements StudyItem {
@Expose private String name;
// index is visible to user number of task from 1 to task number
@@ -167,9 +170,12 @@ public class Task implements StudyItem {
@NotNull
public String getTestsText(@NotNull final Project project) {
+ final Course course = getLesson().getCourse();
+ final Language language = course.getLanguageById();
+ final EduPluginConfigurator configurator = EduPluginConfigurator.INSTANCE.forLanguage(language);
final VirtualFile taskDir = getTaskDir(project);
if (taskDir != null) {
- final VirtualFile file = taskDir.findChild(EduNames.TESTS_FILE);
+ final VirtualFile file = taskDir.findChild(configurator.getTestFileName());
if (file == null) return "";
final Document document = FileDocumentManager.getInstance().getDocument(file);
if (document != null) {
@@ -263,7 +269,9 @@ public class Task implements StudyItem {
}
// used in json serialization/deserialization
- public String getTaskType() {
- return "pycharm";
+ public abstract String getTaskType();
+
+ public StudyTaskChecker getChecker(@NotNull Project project) {
+ return new StudyTaskChecker<>(this, project);
}
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/TaskWithSubtasks.java b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/TaskWithSubtasks.java
index ac10657b829c..6146fb3e9df7 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/TaskWithSubtasks.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/courseFormat/tasks/TaskWithSubtasks.java
@@ -2,6 +2,9 @@ package com.jetbrains.edu.learning.courseFormat.tasks;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
+import com.intellij.openapi.project.Project;
+import com.jetbrains.edu.learning.checker.StudyTaskChecker;
+import com.jetbrains.edu.learning.checker.TaskWithSubtasksChecker;
import com.jetbrains.edu.learning.courseFormat.AnswerPlaceholder;
import com.jetbrains.edu.learning.courseFormat.StudyStatus;
import com.jetbrains.edu.learning.courseFormat.TaskFile;
@@ -58,4 +61,9 @@ public class TaskWithSubtasks extends Task {
public String getTaskType() {
return "subtasks";
}
+
+ @Override
+ public StudyTaskChecker getChecker(@NotNull Project project) {
+ return new TaskWithSubtasksChecker(this, project);
+ }
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java b/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java
index dad0e77a7d64..1fed74118ab7 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java
@@ -73,7 +73,7 @@ public class StudyGenerator {
createChildFile(taskDir, name, taskFile.text);
}
- public static void createDescriptions(VirtualFile taskDir, Task task) throws IOException {
+ private static void createDescriptions(VirtualFile taskDir, Task task) throws IOException {
final Map texts = task.getTaskTexts();
for (Map.Entry entry : texts.entrySet()) {
final String name = entry.getKey();
@@ -82,7 +82,7 @@ public class StudyGenerator {
}
}
- public static void createTestFiles(VirtualFile taskDir, Task task) throws IOException {
+ private static void createTestFiles(VirtualFile taskDir, Task task) throws IOException {
final Map tests = task.getTestsText();
for (Map.Entry entry : tests.entrySet()) {
final String name = entry.getKey();
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java b/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java
index b294e5d29dad..6b25be65eef2 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java
@@ -144,7 +144,7 @@ public class StudyProjectGenerator {
}
@NotNull
- public List getCoursesUnderProgress(boolean force, @NotNull final String progressTitle, @NotNull final Project project) {
+ public List getCoursesUnderProgress(boolean force, @NotNull final String progressTitle, @Nullable final Project project) {
try {
return ProgressManager.getInstance()
.runProcessWithProgressSynchronously(() -> {
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/intellij/EduIntelliJTemplateFactory.java b/python/educational-core/src/com/jetbrains/edu/learning/intellij/EduIntelliJTemplateFactory.java
index 48e9ce41923b..19535068e1c1 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/intellij/EduIntelliJTemplateFactory.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/intellij/EduIntelliJTemplateFactory.java
@@ -3,16 +3,35 @@ package com.jetbrains.edu.learning.intellij;
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
import com.intellij.platform.ProjectTemplate;
import com.intellij.platform.ProjectTemplatesFactory;
+import com.jetbrains.edu.learning.courseFormat.Course;
+import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator;
+import com.jetbrains.edu.learning.intellij.stepik.EduRemoteCourseTemplate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
@SuppressWarnings("unused") //used in other educational plugins that are stored in separate repository
public class EduIntelliJTemplateFactory extends ProjectTemplatesFactory {
private static final String GROUP_NAME = "Education";
+ private static List ourRemoteCourses;
+
+ static {
+ ProgressManager.getInstance().run(new Task.Backgroundable(null, "Updating Course") {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ ourRemoteCourses = new StudyProjectGenerator().getCourses(true);
+ }
+ });
+ }
@NotNull
@Override
@@ -23,7 +42,14 @@ public class EduIntelliJTemplateFactory extends ProjectTemplatesFactory {
@NotNull
@Override
public ProjectTemplate[] createTemplates(@Nullable String group, WizardContext context) {
- return ApplicationManager.getApplication().getExtensions(EduIntelliJProjectTemplate.EP_NAME);
+ final ArrayList templates = new ArrayList<>();
+ if (ourRemoteCourses != null) {
+ for (Course course : ourRemoteCourses) {
+ templates.add(new EduRemoteCourseTemplate(course));
+ }
+ }
+ Collections.addAll(templates, ApplicationManager.getApplication().getExtensions(EduIntelliJProjectTemplate.EP_NAME));
+ return templates.toArray(new ProjectTemplate[templates.size()]);
}
@Override
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/intellij/stepik/EduRemoteCourseModuleBuilder.java b/python/educational-core/src/com/jetbrains/edu/learning/intellij/stepik/EduRemoteCourseModuleBuilder.java
new file mode 100644
index 000000000000..9aa0282e7985
--- /dev/null
+++ b/python/educational-core/src/com/jetbrains/edu/learning/intellij/stepik/EduRemoteCourseModuleBuilder.java
@@ -0,0 +1,90 @@
+package com.jetbrains.edu.learning.intellij.stepik;
+
+import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
+import com.intellij.ide.util.projectWizard.ProjectWizardStepFactory;
+import com.intellij.ide.util.projectWizard.SettingsStep;
+import com.intellij.lang.Language;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.ModifiableModuleModel;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleWithNameAlreadyExists;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Conditions;
+import com.intellij.openapi.util.InvalidDataException;
+import com.jetbrains.edu.learning.EduPluginConfigurator;
+import com.jetbrains.edu.learning.StudyTaskManager;
+import com.jetbrains.edu.learning.courseFormat.Course;
+import com.jetbrains.edu.learning.intellij.generation.EduProjectGenerator;
+import org.jdom.JDOMException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+
+class EduRemoteCourseModuleBuilder extends JavaModuleBuilder {
+ private static final Logger LOG = Logger.getInstance(EduRemoteCourseModuleBuilder.class);
+ private final Course myCourse;
+ private EduProjectGenerator myGenerator = new EduProjectGenerator();
+
+ public EduRemoteCourseModuleBuilder(Course course) {
+ myCourse = course;
+ }
+
+ @Nullable
+ @Override
+ public Module commitModule(@NotNull Project project, @Nullable ModifiableModuleModel model) {
+ Module module = super.commitModule(project, model);
+ if (module == null) {
+ return null;
+ }
+ String languageName = myCourse.getLanguageID();
+ Language language = Language.findLanguageByID(languageName);
+ if (language == null) {
+ return module;
+ }
+ EduPluginConfigurator configurator = EduPluginConfigurator.INSTANCE.forLanguage(language);
+ if (configurator == null) {
+ return module;
+ }
+ configurator.configureModule(module);
+ return module;
+ }
+
+ @Nullable
+ @Override
+ public String getBuilderId() {
+ return "remote.course.builder." + myCourse.getName();
+ }
+
+ @Nullable
+ @Override
+ public ModuleWizardStep modifySettingsStep(@NotNull SettingsStep settingsStep) {
+ return ProjectWizardStepFactory.getInstance().createJavaSettingsStep(settingsStep, this, Conditions.alwaysTrue());
+ }
+
+ @NotNull
+ @Override
+ public Module createModule(@NotNull ModifiableModuleModel moduleModel)
+ throws InvalidDataException, IOException, ModuleWithNameAlreadyExists, JDOMException, ConfigurationException {
+ Module baseModule = super.createModule(moduleModel);
+ String languageName = myCourse.getLanguageID();
+ Language language = Language.findLanguageByID(languageName);
+ if (language != null) {
+ EduPluginConfigurator configurator = EduPluginConfigurator.INSTANCE.forLanguage(language);
+ if (configurator != null) {
+ Project project = baseModule.getProject();
+ myGenerator.setSelectedCourse(myCourse);
+ myGenerator.generateProject(project, project.getBaseDir());
+ Course course = StudyTaskManager.getInstance(project).getCourse();
+ if (course == null) {
+ LOG.info("failed to generate course");
+ return baseModule;
+ }
+ configurator.createCourseModuleContent(moduleModel, project, course, getModuleFileDirectory());
+ }
+ }
+ return baseModule;
+ }
+}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/intellij/stepik/EduRemoteCourseTemplate.java b/python/educational-core/src/com/jetbrains/edu/learning/intellij/stepik/EduRemoteCourseTemplate.java
new file mode 100644
index 000000000000..b3f1bd994e10
--- /dev/null
+++ b/python/educational-core/src/com/jetbrains/edu/learning/intellij/stepik/EduRemoteCourseTemplate.java
@@ -0,0 +1,48 @@
+package com.jetbrains.edu.learning.intellij.stepik;
+
+import com.intellij.ide.util.projectWizard.AbstractModuleBuilder;
+import com.intellij.openapi.ui.ValidationInfo;
+import com.jetbrains.edu.learning.courseFormat.Course;
+import com.jetbrains.edu.learning.intellij.EduIntelliJProjectTemplate;
+import icons.EducationalCoreIcons;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class EduRemoteCourseTemplate implements EduIntelliJProjectTemplate {
+ private final Course myCourse;
+
+ public EduRemoteCourseTemplate(Course course) {
+ myCourse = course;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return myCourse.getName();
+ }
+
+ @Nullable
+ @Override
+ public String getDescription() {
+ return myCourse.getDescription();
+ }
+
+ @Override
+ public Icon getIcon() {
+ return EducationalCoreIcons.Stepik;
+ }
+
+ @NotNull
+ @Override
+ public AbstractModuleBuilder createModuleBuilder() {
+ return new EduRemoteCourseModuleBuilder(myCourse);
+ }
+
+ @Nullable
+ @Override
+ public ValidationInfo validateSettings() {
+ return null;
+ }
+}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java b/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java
index 3c0f635fce8f..d1da82314213 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java
@@ -7,20 +7,19 @@ import com.intellij.ide.projectView.ProjectView;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.jetbrains.edu.learning.StudySettings;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
-import com.jetbrains.edu.learning.checker.StudyExecutor;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.*;
import com.jetbrains.edu.learning.courseFormat.tasks.ChoiceTask;
@@ -28,7 +27,6 @@ import com.jetbrains.edu.learning.courseFormat.tasks.CodeTask;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import com.jetbrains.edu.learning.courseFormat.tasks.TheoryTask;
import com.jetbrains.edu.learning.courseGeneration.StudyGenerator;
-import com.jetbrains.edu.learning.editor.StudyEditor;
import com.jetbrains.edu.learning.navigation.StudyNavigator;
import com.jetbrains.edu.learning.ui.StudyToolWindow;
import org.apache.http.HttpEntity;
@@ -49,7 +47,10 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import static com.jetbrains.edu.learning.stepic.EduStepicConnector.getStep;
@@ -146,7 +147,7 @@ public class EduAdaptiveStepicConnector {
else if (stepType.equals(CHOICE_TYPE_TEXT)) {
return getChoiceTaskFromStep(name, step.block, stepId, userId);
}
- else if (stepType.startsWith(EduStepicConnector.PYCHARM_PREFIX)) {
+ else if (stepType.startsWith(EduStepicNames.PYCHARM_PREFIX)) {
return EduStepicConnector.createTask(stepId);
}
else if (stepType.equals(TEXT_STEP_TYPE)) {
@@ -280,10 +281,15 @@ public class EduAdaptiveStepicConnector {
}
}
- public static void addNextRecommendedTask(@NotNull Project project, @NotNull ProgressIndicator indicator, int reactionToPost) {
- final StudyEditor editor = StudyUtils.getSelectedStudyEditor(project);
+ public static void addNextRecommendedTask(@NotNull Project project,
+ @NotNull Lesson lesson,
+ @NotNull ProgressIndicator indicator,
+ int reactionToPost) {
final Course course = StudyTaskManager.getInstance(project).getCourse();
- if (course == null || editor == null || editor.getTaskFile() == null || !(course instanceof RemoteCourse)) {
+ if (!(course instanceof RemoteCourse)) {
+ LOG.warn("Course is in incorrect state");
+ ApplicationManager.getApplication().invokeLater(() -> StudyUtils.showErrorPopupOnToolbar(project,
+ "Can't get next recommendation: course is broken"));
return;
}
@@ -296,7 +302,6 @@ public class EduAdaptiveStepicConnector {
return;
}
- final Lesson lesson = editor.getTaskFile().getTask().getLesson();
final boolean reactionPosted = postRecommendationReaction(String.valueOf(lesson.getId()), String.valueOf(user.getId()), reactionToPost);
if (!reactionPosted) {
LOG.warn("Recommendation reaction wasn't posted");
@@ -315,10 +320,10 @@ public class EduAdaptiveStepicConnector {
task.initTask(lesson, false);
boolean replaceCurrentTask = reactionToPost == TOO_HARD_RECOMMENDATION_REACTION || reactionToPost == TOO_BORING_RECOMMENDATION_REACTION;
if (replaceCurrentTask) {
- replaceCurrentTask(project, editor, task);
+ replaceCurrentTask(project, task, lesson);
}
else {
- addAsNextTask(project, editor, task);
+ addAsNextTask(project, task, lesson);
}
ApplicationManager.getApplication().invokeLater(() -> {
@@ -328,11 +333,10 @@ public class EduAdaptiveStepicConnector {
});
}
- private static void addAsNextTask(@NotNull Project project, @NotNull StudyEditor editor, @NotNull Task task) {
+ private static void addAsNextTask(@NotNull Project project, @NotNull Task task, @NotNull Lesson lesson) {
Course course = StudyTaskManager.getInstance(project).getCourse();
assert course != null;
- final Lesson lesson = editor.getTaskFile().getTask().getLesson();
lesson.addTask(task);
task.setIndex(lesson.getTaskList().size());
lesson.initLesson(course, true);
@@ -357,19 +361,15 @@ public class EduAdaptiveStepicConnector {
}
}
- private static void replaceCurrentTask(@NotNull Project project, @NotNull StudyEditor editor, @NotNull Task task) {
+ private static void replaceCurrentTask(@NotNull Project project, @NotNull Task task, @NotNull Lesson lesson) {
Course course = StudyTaskManager.getInstance(project).getCourse();
assert course != null;
- final Lesson lesson = editor.getTaskFile().getTask().getLesson();
int taskIndex = lesson.getTaskList().size();
- task.setLesson(lesson);
task.setIndex(taskIndex);
lesson.getTaskList().set(taskIndex - 1, task);
- copyTaskFileParameters(editor, task);
-
final String lessonName = EduNames.LESSON + lesson.getIndex();
updateProjectFiles(project, task, lessonName);
setToolWindowText(project, task);
@@ -378,12 +378,10 @@ public class EduAdaptiveStepicConnector {
private static void updateProjectFiles(@NotNull Project project, @NotNull Task task, @NotNull String lessonName) {
final VirtualFile lessonDir = project.getBaseDir().findChild(lessonName);
if (lessonDir != null) {
- final VirtualFile taskResourceRoot = lessonDir.findChild(EduNames.TASK + task.getIndex());
ApplicationManager.getApplication().invokeLater(() -> ApplicationManager.getApplication().runWriteAction(() -> {
try {
- removeOldProjectFiles(project, taskResourceRoot);
- StudyGenerator.createTestFiles(taskResourceRoot, task);
- StudyGenerator.createDescriptions(taskResourceRoot, task);
+ removeOldProjectFiles(lessonDir, task.getIndex());
+ StudyGenerator.createTask(task, lessonDir);
}
catch (IOException e) {
LOG.warn(e.getMessage());
@@ -392,46 +390,14 @@ public class EduAdaptiveStepicConnector {
}
}
- private static void removeOldProjectFiles(@NotNull Project project, @Nullable VirtualFile taskRecourseRoot) throws IOException {
- if (taskRecourseRoot == null) {
+ private static void removeOldProjectFiles(@NotNull VirtualFile lessonDir, int taskIndex) throws IOException {
+ final VirtualFile taskDir = lessonDir.findChild(EduNames.TASK + taskIndex);
+ if (taskDir == null) {
LOG.warn("Failed to update files for a new recommendation: task directory is null");
return;
}
- VirtualFile[] children = VfsUtil.getChildren(taskRecourseRoot);
- for (VirtualFile file : children) {
- String name = file.getName();
- if (StudyUtils.isTestsFile(project, name) || StudyUtils.isTaskDescriptionFile(name)) {
- file.delete(taskRecourseRoot);
- }
- }
- }
-
- private static void copyTaskFileParameters(@NotNull StudyEditor editor, @NotNull Task task) {
- final Map taskFiles = task.getTaskFiles();
- if (taskFiles.size() == 1) {
- TaskFile newTaskFile = (TaskFile)taskFiles.values().toArray()[0];
- setTaskFileParameters(editor, task, newTaskFile);
- updateEditorText(editor, newTaskFile);
- }
- else {
- LOG.warn("Got task without unexpected number of task files: " + taskFiles.size());
- }
- }
- private static void updateEditorText(@NotNull StudyEditor editor, @NotNull TaskFile newTaskFile) {
- ApplicationManager.getApplication().invokeLater(() -> ApplicationManager.getApplication().runWriteAction(() -> {
- final Document document = editor.getEditor().getDocument();
- document.setText(newTaskFile.text);
- }));
- }
-
- private static void setTaskFileParameters(@NotNull StudyEditor editor, @NotNull Task task, @NotNull TaskFile newTaskFile) {
- TaskFile currentTaskFile = editor.getTaskFile();
- currentTaskFile.text = newTaskFile.text;
- currentTaskFile.name = newTaskFile.name;
- currentTaskFile.setTask(task);
- task.getTaskFiles().clear();
- task.taskFiles.put(CODE_TASK_NAME, currentTaskFile);
+ taskDir.delete(EduAdaptiveStepicConnector.class);
}
private static void setToolWindowText(@NotNull Project project, @NotNull Task task) {
@@ -489,7 +455,7 @@ public class EduAdaptiveStepicConnector {
}
}
else {
- final String templateForTask = getCodeTemplateForTask(project, task, step.options.codeTemplates);
+ final String templateForTask = getCodeTemplateForTask(project, step.options.codeTemplates);
String text = templateForTask == null ? "# write your answer here \n" : templateForTask;
createMockTaskFile(task, text);
}
@@ -497,10 +463,9 @@ public class EduAdaptiveStepicConnector {
}
private static String getCodeTemplateForTask(@NotNull Project project,
- @NotNull Task task,
@Nullable StepicWrappers.CodeTemplatesWrapper codeTemplates) {
if (codeTemplates != null) {
- final String languageString = getLanguageString(task, project);
+ final String languageString = getLanguageString(project);
if (languageString != null) {
return codeTemplates.getTemplateForLanguage(languageString);
}
@@ -656,12 +621,12 @@ public class EduAdaptiveStepicConnector {
}
@Nullable
- private static String getLanguageString(@NotNull Task task, @NotNull Project project) {
+ private static String getLanguageString(@NotNull Project project) {
final Language pythonLanguage = Language.findLanguageByID("Python");
if (pythonLanguage != null) {
- final Sdk language = StudyExecutor.INSTANCE.forLanguage(pythonLanguage).findSdk(project);
- if (language != null) {
- final String versionString = language.getVersionString();
+ Sdk sdk = ModuleRootManager.getInstance(ModuleManager.getInstance(project).getModules()[0]).getSdk();
+ if (sdk != null) {
+ final String versionString = sdk.getVersionString();
if (versionString != null) {
final List versionStringParts = StringUtil.split(versionString, " ");
if (versionStringParts.size() == 2) {
@@ -669,9 +634,6 @@ public class EduAdaptiveStepicConnector {
}
}
}
- else {
- StudyUtils.showNoSdkNotification(task, project);
- }
}
return null;
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java b/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java
index fb0998541a16..5ae616d81654 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduStepicConnector.java
@@ -2,16 +2,20 @@ package com.jetbrains.edu.learning.stepic;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import com.intellij.lang.LanguageExtensionPoint;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.edu.learning.EduPluginConfigurator;
import com.jetbrains.edu.learning.StudySettings;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.*;
+import com.jetbrains.edu.learning.courseFormat.tasks.PyCharmTask;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import com.jetbrains.edu.learning.courseFormat.tasks.TaskWithSubtasks;
import org.apache.http.HttpEntity;
@@ -32,14 +36,15 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
+import static com.jetbrains.edu.learning.stepic.EduStepicNames.PYCHARM_PREFIX;
+
public class EduStepicConnector {
private static final Logger LOG = Logger.getInstance(EduStepicConnector.class.getName());
public static final int CURRENT_VERSION = 2;
//this prefix indicates that course can be opened by educational plugin
- public static final String PYCHARM_PREFIX = "pycharm";
private static final String ADAPTIVE_NOTE =
- "\n\nInitially, the adaptive system may behave somewhat randomly, but the more problems you solve, the smarter it become!";
+ "\n\nInitially, the adaptive system may behave somewhat randomly, but the more problems you solve, the smarter it becomes!";
private EduStepicConnector() {
}
@@ -147,6 +152,8 @@ public class EduStepicConnector {
final List courses = coursesContainer.courses;
for (RemoteCourse info : courses) {
if (!info.isAdaptive() && StringUtil.isEmptyOrSpaces(info.getType())) continue;
+ setCourseLanguage(info);
+
if (canBeOpened(info)) {
final ArrayList authors = new ArrayList<>();
for (Integer instructor : info.getInstructors()) {
@@ -164,13 +171,34 @@ public class EduStepicConnector {
}
}
- static boolean canBeOpened(RemoteCourse courseInfo) {
- if (courseInfo.isAdaptive()) {
- return true;
+ private static void setCourseLanguage(RemoteCourse info) {
+ if (info.isAdaptive()) {
+ info.setLanguage("Python"); // adaptive courses available only in PyCharm now
+ return;
}
+ String courseType = info.getType();
+ final int separator = courseType.indexOf(" ");
+ assert separator != -1;
+ final String language = courseType.substring(separator + 1);
+ info.setLanguage(language);
+ }
+
+ static boolean canBeOpened(RemoteCourse courseInfo) {
+ final ArrayList supportedLanguages = new ArrayList<>();
+ final LanguageExtensionPoint[] extensions = Extensions.getExtensions(EduPluginConfigurator.EP_NAME, null);
+ for (LanguageExtensionPoint extension : extensions) {
+ String languageId = extension.getKey();
+ supportedLanguages.add(languageId);
+ }
+
+ if (courseInfo.isAdaptive()) {
+ return supportedLanguages.contains(courseInfo.getLanguageID());
+ }
+
String courseType = courseInfo.getType();
final List typeLanguage = StringUtil.split(courseType, " ");
String prefix = typeLanguage.get(0);
+ if (!supportedLanguages.contains(courseInfo.getLanguageID())) return false;
if (typeLanguage.size() < 2 || !prefix.startsWith(PYCHARM_PREFIX)) {
return false;
}
@@ -188,14 +216,8 @@ public class EduStepicConnector {
}
}
- public static RemoteCourse getCourse(@NotNull final Project project, @NotNull final RemoteCourse course) {
- final RemoteCourse remoteCourse = (RemoteCourse)course.copy();
+ public static RemoteCourse getCourse(@NotNull final Project project, @NotNull final RemoteCourse remoteCourse) {
if (!remoteCourse.isAdaptive()) {
- String courseType = remoteCourse.getType();
- final int separator = courseType.indexOf(" ");
- assert separator != -1;
- final String language = courseType.substring(separator + 1);
- remoteCourse.setLanguage(language);
try {
for (Integer section : remoteCourse.getSections()) {
remoteCourse.addLessons(getLessons(section));
@@ -267,7 +289,7 @@ public class EduStepicConnector {
return null;
}
final int lastSubtaskIndex = block.options.lastSubtaskIndex;
- Task task = new Task();
+ Task task = new PyCharmTask();
if (lastSubtaskIndex != 0) {
task = createTaskWithSubtasks(lastSubtaskIndex);
}
@@ -301,6 +323,9 @@ public class EduStepicConnector {
final List placeholders = file.getAnswerPlaceholders();
for (AnswerPlaceholder placeholder : placeholders) {
final AnswerPlaceholderSubtaskInfo info = placeholder.getActiveSubtaskInfo();
+ if (info == null) {
+ continue;
+ }
final int offset = placeholder.getOffset();
final int length = placeholder.getLength();
if (fileText.length() > offset + length) {
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduStepicNames.java b/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduStepicNames.java
index b25e80fcea34..5ee99dc6cde8 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduStepicNames.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduStepicNames.java
@@ -21,4 +21,6 @@ public class EduStepicNames {
public static final String SECTIONS = "/sections/";
public static final String ENROLLMENTS = "/enrollments";
public static final String STEPIC_REGISTRATION_LINK = "https://stepic.org/registration?next=%2Fexplore%2Fcourses";
+
+ public static final String PYCHARM_PREFIX = "pycharm";
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java b/python/educational-core/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java
index 6f68839fd936..8aabf57e7144 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java
@@ -148,7 +148,8 @@ public class StepicAdaptiveReactionsPanel extends JPanel {
public void run(@NotNull ProgressIndicator indicator) {
StepicAdaptiveReactionsPanel.this.setEnabledRecursive(false);
ApplicationManager.getApplication().invokeLater(()->setBackground(UIUtil.getLabelBackground()));
- EduAdaptiveStepicConnector.addNextRecommendedTask(StepicAdaptiveReactionsPanel.this.myProject, indicator, myReaction);
+ EduAdaptiveStepicConnector.addNextRecommendedTask(StepicAdaptiveReactionsPanel.this.myProject, task.getLesson(), indicator,
+ myReaction);
StepicAdaptiveReactionsPanel.this.setEnabledRecursive(true);
}
});
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/stepic/StepicWrappers.java b/python/educational-core/src/com/jetbrains/edu/learning/stepic/StepicWrappers.java
index 1690b383f063..5124acab9833 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/stepic/StepicWrappers.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/stepic/StepicWrappers.java
@@ -2,13 +2,14 @@ package com.jetbrains.edu.learning.stepic;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
+import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.edu.learning.EduPluginConfigurator;
import com.jetbrains.edu.learning.StudyUtils;
-import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.core.EduUtils;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.Lesson;
@@ -136,13 +137,16 @@ public class StepicWrappers {
}
private static List getTestFiles(@NotNull Task task, @NotNull Project project) {
+ final Course course = task.getLesson().getCourse();
+ final Language language = course.getLanguageById();
+ final EduPluginConfigurator configurator = EduPluginConfigurator.INSTANCE.forLanguage(language);
List testFiles = new ArrayList<>();
VirtualFile taskDir = task.getTaskDir(project);
if (taskDir == null) {
return testFiles;
}
if (!(task instanceof TaskWithSubtasks)) {
- VirtualFile testFile = taskDir.findChild(EduNames.TESTS_FILE);
+ VirtualFile testFile = taskDir.findChild(configurator.getTestFileName());
testFiles.add(testFile);
return testFiles;
}
@@ -190,6 +194,7 @@ public class StepicWrappers {
public CourseWrapper(Course course) {
this.course = new RemoteCourse();
this.course.setName(course.getName());
+ this.course.setLanguage(course.getLanguageID());
this.course.setDescription(course.getDescription());
this.course.setAuthors(course.getAuthors());
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/twitter/StudyTwitterAction.java b/python/educational-core/src/com/jetbrains/edu/learning/twitter/StudyTwitterAction.java
index a1c57b92583d..360c0eba54bd 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/twitter/StudyTwitterAction.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/twitter/StudyTwitterAction.java
@@ -2,7 +2,7 @@ package com.jetbrains.edu.learning.twitter;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
-import com.jetbrains.edu.learning.StudyCheckListener;
+import com.jetbrains.edu.learning.checker.StudyCheckListener;
import com.jetbrains.edu.learning.StudyTwitterPluginConfigurator;
import com.jetbrains.edu.learning.courseFormat.StudyStatus;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
diff --git a/python/educational-core/src/icons/EducationalCoreIcons.java b/python/educational-core/src/icons/EducationalCoreIcons.java
index c089db48d76c..73c105a44024 100644
--- a/python/educational-core/src/icons/EducationalCoreIcons.java
+++ b/python/educational-core/src/icons/EducationalCoreIcons.java
@@ -22,6 +22,7 @@ public class EducationalCoreIcons {
public static final Icon ResetTaskFile = load("/icons/com/jetbrains/edu/learning/ResetTaskFile.png"); // 16x16
public static final Icon Sandbox = load("/icons/com/jetbrains/edu/learning/Sandbox.png"); // 16x16
public static final Icon ShowHint = load("/icons/com/jetbrains/edu/learning/showHint.png"); // 16x16
+ public static final Icon Stepik = load("/icons/com/jetbrains/edu/learning/Stepik.png"); // 16x16
public static final Icon Task = load("/icons/com/jetbrains/edu/learning/Task.png"); // 16x16
public static final Icon TaskCompl = load("/icons/com/jetbrains/edu/learning/TaskCompl.png"); // 16x16
public static final Icon TaskDescription = load("/icons/com/jetbrains/edu/learning/TaskDescription.png"); // 13x13
diff --git a/python/educational-core/testSrc/com/jetbrains/edu/coursecreator/CCTestCase.java b/python/educational-core/testSrc/com/jetbrains/edu/coursecreator/CCTestCase.java
index 5be02916f2fe..051964560cc6 100644
--- a/python/educational-core/testSrc/com/jetbrains/edu/coursecreator/CCTestCase.java
+++ b/python/educational-core/testSrc/com/jetbrains/edu/coursecreator/CCTestCase.java
@@ -19,6 +19,7 @@ import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.courseFormat.*;
+import com.jetbrains.edu.learning.courseFormat.tasks.PyCharmTask;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -85,7 +86,7 @@ public abstract class CCTestCase extends CodeInsightFixtureTestCase {
Lesson lesson = new Lesson();
lesson.setName("lesson1");
- Task task = new Task();
+ Task task = new PyCharmTask();
task.setName("task1");
task.setIndex(1);
lesson.addTask(task);
diff --git a/python/educational-python/Edu-Python/Edu-Python.iml b/python/educational-python/Edu-Python/Edu-Python.iml
index 3460c943ef69..69c8e7ca7d1b 100644
--- a/python/educational-python/Edu-Python/Edu-Python.iml
+++ b/python/educational-python/Edu-Python/Edu-Python.iml
@@ -13,7 +13,6 @@
-
diff --git a/python/educational-python/Edu-Python/resources/META-INF/plugin.xml b/python/educational-python/Edu-Python/resources/META-INF/plugin.xml
index b7a8fb0120f6..e39f149ef86e 100644
--- a/python/educational-python/Edu-Python/resources/META-INF/plugin.xml
+++ b/python/educational-python/Edu-Python/resources/META-INF/plugin.xml
@@ -35,7 +35,6 @@
-
diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java
index cfd453a0e8cc..3bbdd68f95a7 100644
--- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java
+++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java
@@ -77,10 +77,10 @@ public class PyEduPluginConfigurator implements EduPluginConfigurator {
@Override
public boolean isTestFile(VirtualFile file) {
String name = file.getName();
- if (EduNames.TESTS_FILE.equals(name)) {
+ if (TESTS_PY.equals(name)) {
return true;
}
- return name.contains(FileUtil.getNameWithoutExtension(EduNames.TESTS_FILE)) && name.contains(EduNames.SUBTASK_MARKER);
+ return name.contains(FileUtil.getNameWithoutExtension(TESTS_PY)) && name.contains(EduNames.SUBTASK_MARKER);
}
@Override
@@ -94,7 +94,7 @@ public class PyEduPluginConfigurator implements EduPluginConfigurator {
ApplicationManager.getApplication().runWriteAction(() -> {
try {
PsiDirectory taskPsiDir = PsiManager.getInstance(project).findDirectory(taskDir);
- FileTemplate testsTemplate = FileTemplateManager.getInstance(project).getInternalTemplate(EduNames.TESTS_FILE);
+ FileTemplate testsTemplate = FileTemplateManager.getInstance(project).getInternalTemplate(TESTS_PY);
if (taskPsiDir == null || testsTemplate == null) {
return;
}
@@ -108,10 +108,10 @@ public class PyEduPluginConfigurator implements EduPluginConfigurator {
@NotNull
public static String getSubtaskTestsFileName(int index) {
- return index == 0 ? EduNames.TESTS_FILE : FileUtil.getNameWithoutExtension(EduNames.TESTS_FILE) +
+ return index == 0 ? TESTS_PY : FileUtil.getNameWithoutExtension(TESTS_PY) +
EduNames.SUBTASK_MARKER +
index + "." +
- FileUtilRt.getExtension(EduNames.TESTS_FILE);
+ FileUtilRt.getExtension(TESTS_PY);
}
@NotNull
diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyCheckAction.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyCheckAction.java
index 264596c26b46..1948c1ce49a8 100644
--- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyCheckAction.java
+++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyCheckAction.java
@@ -6,7 +6,6 @@ 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.ui.MessageType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.jetbrains.edu.learning.actions.StudyCheckAction;
@@ -15,14 +14,10 @@ import com.jetbrains.edu.learning.checker.StudyCheckUtils;
import com.jetbrains.edu.learning.checker.StudyTestRunner;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.Course;
-import com.jetbrains.edu.learning.courseFormat.StudyStatus;
import com.jetbrains.edu.learning.courseFormat.TaskFile;
-import com.jetbrains.edu.learning.courseFormat.tasks.ChoiceTask;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
-import com.jetbrains.edu.learning.editor.StudyChoiceVariantsPanel;
import com.jetbrains.edu.learning.editor.StudyEditor;
import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
-import com.jetbrains.edu.learning.ui.StudyToolWindow;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -52,7 +47,7 @@ public class PyStudyCheckAction extends StudyCheckAction {
ApplicationManager.getApplication().invokeLater(
() -> IdeFocusManager.getInstance(project).requestFocus(studyState.getEditor().getComponent(), true));
- final StudyTestRunner testRunner = StudyUtils.getTestRunner(task, taskDir);
+ final StudyTestRunner testRunner = new PyStudyTestRunner(task, taskDir);
Process testProcess = null;
String commandLine = "";
try {
@@ -83,9 +78,9 @@ public class PyStudyCheckAction extends StudyCheckAction {
return new StudyCheckTask(project, studyState, myCheckInProgress, testProcess, commandLine) {
@Override
protected void onTaskFailed(@NotNull String message) {
+ super.onTaskFailed(message);
ApplicationManager.getApplication().invokeLater(() -> {
if (myTaskDir == null) return;
- myTask.setStatus(StudyStatus.Failed);
for (Map.Entry entry : myTask.getTaskFiles().entrySet()) {
final String name = entry.getKey();
final TaskFile taskFile = entry.getValue();
@@ -99,38 +94,12 @@ public class PyStudyCheckAction extends StudyCheckAction {
() -> StudyCheckUtils.runSmartTestProcess(myTaskDir, testRunner, name, taskFile, project)));
}
}
- final StudyToolWindow toolWindow = StudyUtils.getStudyToolWindow(project);
- if (toolWindow != null) {
- final Course course = StudyTaskManager.getInstance(project).getCourse();
- if (course != null) {
- if (course.isAdaptive()) {
- if (myTask instanceof ChoiceTask) {
- StudyCheckUtils.showTestResultPopUp("Wrong answer", MessageType.ERROR.getPopupBackground(), project);
- repaintChoicePanel(project, (ChoiceTask)myTask);
- }
- else {
- StudyCheckUtils.showTestResultPopUp("Wrong answer", MessageType.ERROR.getPopupBackground(), project);
- StudyCheckUtils.showTestResultsToolWindow(project, message, false);
- }
- }
- else {
- StudyCheckUtils.showTestResultPopUp(message, MessageType.ERROR.getPopupBackground(), project);
- }
- }
- StudyCheckUtils.navigateToFailedPlaceholder(myStudyState, myTask, myTaskDir, project);
- }
+ StudyCheckUtils.navigateToFailedPlaceholder(myStudyState, myTask, myTaskDir, project);
});
}
};
}
- private static void repaintChoicePanel(@NotNull Project project, @NotNull ChoiceTask task) {
- final StudyToolWindow toolWindow = StudyUtils.getStudyToolWindow(project);
- if (toolWindow != null) {
- toolWindow.setBottomComponent(new StudyChoiceVariantsPanel(task));
- }
- }
-
@Nullable
private static VirtualFile getTaskVirtualFile(@NotNull final StudyState studyState,
@NotNull final Task task,
diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyExecutor.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyExecutor.java
deleted file mode 100644
index 0bd87804ab94..000000000000
--- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyExecutor.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2000-2014 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.jetbrains.edu.learning;
-
-import com.intellij.execution.RunContentExecutor;
-import com.intellij.execution.configurations.GeneralCommandLine;
-import com.intellij.execution.process.ProcessHandler;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.module.ModuleManager;
-import com.intellij.openapi.options.ShowSettingsUtil;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.Sdk;
-import com.intellij.openapi.ui.MessageType;
-import com.intellij.openapi.ui.popup.Balloon;
-import com.intellij.openapi.ui.popup.BalloonBuilder;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.jetbrains.edu.learning.courseFormat.tasks.Task;
-import com.jetbrains.edu.learning.checker.StudyExecutor;
-import com.jetbrains.edu.learning.checker.StudyTestRunner;
-import com.jetbrains.edu.learning.courseFormat.UserTest;
-import com.jetbrains.python.run.PythonTracebackFilter;
-import com.jetbrains.python.sdk.PythonSdkType;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.event.HyperlinkEvent;
-import java.io.File;
-import java.util.List;
-
-public class PyStudyExecutor implements StudyExecutor {
-
- @Override
- public Sdk findSdk(@NotNull final Project project) {
- return PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]);
- }
-
- @Override
- public StudyTestRunner getTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
- return new PyStudyTestRunner(task, taskDir);
- }
-
- @Override
- public RunContentExecutor getExecutor(@NotNull final Project project, @NotNull final ProcessHandler handler) {
- return new RunContentExecutor(project, handler).withFilter(new PythonTracebackFilter(project));
- }
-
- @Override
- public void setCommandLineParameters(@NotNull final GeneralCommandLine cmd,
- @NotNull final Project project,
- @NotNull final String filePath,
- @NotNull final String sdkPath,
- @NotNull final Task currentTask) {
- final List userTests = StudyTaskManager.getInstance(project).getUserTests(currentTask);
- if (!userTests.isEmpty()) {
- EduPluginConfigurator configurator = EduPluginConfigurator.INSTANCE.forLanguage(currentTask.getLesson().getCourse().getLanguageById());
- if (configurator != null) {
- cmd.addParameter(new File(project.getBaseDir().getPath(), "user_tester.py").getPath());
- cmd.addParameter(sdkPath);
- cmd.addParameter(filePath);
- }
- }
- else {
- cmd.addParameter(filePath);
- }
- }
-
- public void showNoSdkNotification(@NotNull final Project project) {
- final String text = "No Python interpreter configured for the project Configure interpreter";
- final BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().
- createHtmlTextBalloonBuilder(text, null,
- MessageType.WARNING.getPopupBackground(),
- event -> {
- if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
- ApplicationManager.getApplication()
- .invokeLater(
- () -> ShowSettingsUtil.getInstance().showSettingsDialog(project, "Project Interpreter"));
- }
- });
- balloonBuilder.setHideOnLinkClick(true);
- final Balloon balloon = balloonBuilder.createBalloon();
- StudyUtils.showCheckPopUp(project, balloon);
- }
-}
diff --git a/python/educational-python/main_pycharm_edu.iml b/python/educational-python/main_pycharm_edu.iml
index 8a0ded56714a..4f0645b39f2e 100644
--- a/python/educational-python/main_pycharm_edu.iml
+++ b/python/educational-python/main_pycharm_edu.iml
@@ -15,7 +15,6 @@
-
diff --git a/python/educational-python/resources/fileTemplates/internal/test_helper.py.ft b/python/educational-python/resources/fileTemplates/internal/test_helper.py.ft
index 42bdaa245c70..16ba2d37f90c 100644
--- a/python/educational-python/resources/fileTemplates/internal/test_helper.py.ft
+++ b/python/educational-python/resources/fileTemplates/internal/test_helper.py.ft
@@ -218,13 +218,6 @@ def check_samples(samples=()):
passed()
-def do_not_run_on_check():
- """
- Do not execute task file on check
- """
- print("#educational_plugin DO_NOT_RUN_ON_CHECK")
-
-
def run_common_tests(error_text="Please, reload file and try again"):
test_is_not_empty()
test_answer_placeholders_text_deleted()
diff --git a/python/helpers/pydev/_pydev_bundle/pydev_ipython_console_011.py b/python/helpers/pydev/_pydev_bundle/pydev_ipython_console_011.py
index 7745c7b60549..b7705c6f680d 100644
--- a/python/helpers/pydev/_pydev_bundle/pydev_ipython_console_011.py
+++ b/python/helpers/pydev/_pydev_bundle/pydev_ipython_console_011.py
@@ -313,16 +313,17 @@ class _PyDevFrontEnd:
version = release.__version__
def __init__(self, show_banner=True):
-
# Create and initialize our IPython instance.
- self.ipython = PyDevTerminalInteractiveShell.instance()
+ if hasattr(PyDevTerminalInteractiveShell, '_instance') and PyDevTerminalInteractiveShell._instance is not None:
+ self.ipython = PyDevTerminalInteractiveShell._instance
+ else:
+ self.ipython = PyDevTerminalInteractiveShell.instance()
if show_banner:
# Display the IPython banner, this has version info and
# help info
self.ipython.show_banner()
-
self._curr_exec_line = 0
self._curr_exec_lines = []
diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py
index ee02bf6acb99..62d907bf1876 100644
--- a/python/helpers/pydev/pydevd.py
+++ b/python/helpers/pydev/pydevd.py
@@ -35,7 +35,7 @@ from _pydevd_bundle.pydevd_comm import CMD_SET_BREAK, CMD_SET_NEXT_STATEMENT, CM
from _pydevd_bundle.pydevd_custom_frames import CustomFramesContainer, custom_frames_container_init
from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame
from _pydevd_bundle.pydevd_kill_all_pydevd_threads import kill_all_pydev_threads
-from _pydevd_bundle.pydevd_trace_dispatch import trace_dispatch as _trace_dispatch
+from _pydevd_bundle.pydevd_trace_dispatch import trace_dispatch as _trace_dispatch, global_cache_skips, global_cache_frame_skips
from _pydevd_frame_eval.pydevd_frame_eval_main import frame_eval_func, stop_frame_eval, set_use_code_extra
from _pydevd_bundle.pydevd_utils import save_main_module
from pydevd_concurrency_analyser.pydevd_concurrency_logger import ThreadingLogger, AsyncioLogger, send_message, cur_time
@@ -76,6 +76,7 @@ connected = False
bufferStdOutToServer = False
bufferStdErrToServer = False
remote = False
+inside_fork = False
file_system_encoding = getfilesystemencoding()
@@ -586,7 +587,6 @@ class PyDB:
def consolidate_breakpoints(self, file, id_to_breakpoint, breakpoints):
- from _pydevd_bundle.pydevd_trace_dispatch import global_cache_skips, global_cache_frame_skips
break_dict = {}
for breakpoint_id, pybreakpoint in dict_iter_items(id_to_breakpoint):
break_dict[pybreakpoint.line] = pybreakpoint
@@ -1172,7 +1172,7 @@ def _locked_settrace(
global bufferStdOutToServer
global bufferStdErrToServer
- if not connected :
+ if not connected:
pydevd_vm_type.setup_type()
if SetupHolder.setup is None:
@@ -1220,6 +1220,11 @@ def _locked_settrace(
while not debugger.ready_to_run:
time.sleep(0.1) # busy wait until we receive run command
+ global inside_fork
+ if frame_eval_func is not None and not inside_fork:
+ # Disable frame evaluation for Remote Debug Server
+ debugger.frame_eval_func = None
+
# note that we do that through pydevd_tracing.SetTrace so that the tracing
# is not warned to the user!
pydevd_tracing.SetTrace(debugger.trace_dispatch, debugger.frame_eval_func)
@@ -1359,6 +1364,8 @@ def settrace_forked():
if port is not None:
global connected
connected = False
+ global inside_fork
+ inside_fork = True
custom_frames_container_init()
diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java
index 05dc987be1ef..451a1db5b390 100644
--- a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java
@@ -637,7 +637,19 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
// include our own names
final int underscores = PyUtil.getInitialUnderscores(element.getName());
- final CompletionVariantsProcessor processor = new CompletionVariantsProcessor(element);
+ final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(element);
+ final CompletionVariantsProcessor processor = new CompletionVariantsProcessor(element, e -> {
+ if (builtinCache.isBuiltin(e)) {
+ final String name = e instanceof PyElement ? ((PyElement)e).getName() : null;
+ if (e instanceof PyImportElement) {
+ return false;
+ }
+ if (name != null && PyUtil.getInitialUnderscores(name) == 1) {
+ return false;
+ }
+ }
+ return true;
+ }, null);
final ScopeOwner owner = realContext instanceof ScopeOwner ? (ScopeOwner)realContext : ScopeUtil.getScopeOwner(realContext);
if (owner != null) {
PyResolveUtil.scopeCrawlUp(processor, owner, null, null);
@@ -648,7 +660,7 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
KeywordArgumentCompletionUtil.collectFunctionArgNames(element, ret, TypeEvalContext.codeCompletion(element.getProject(), element.getContainingFile()));
// include builtin names
- final PyFile builtinsFile = PyBuiltinCache.getInstance(element).getBuiltinsFile();
+ final PyFile builtinsFile = builtinCache.getBuiltinsFile();
if (builtinsFile != null) {
PyResolveUtil.scopeCrawlUp(processor, builtinsFile, null, null);
}
diff --git a/python/src/com/jetbrains/python/psi/resolve/PythonBuiltinReferenceResolveProvider.java b/python/src/com/jetbrains/python/psi/resolve/PythonBuiltinReferenceResolveProvider.java
index 1dab95b9fd11..b1dcd9b58840 100644
--- a/python/src/com/jetbrains/python/psi/resolve/PythonBuiltinReferenceResolveProvider.java
+++ b/python/src/com/jetbrains/python/psi/resolve/PythonBuiltinReferenceResolveProvider.java
@@ -59,7 +59,7 @@ public class PythonBuiltinReferenceResolveProvider implements PyReferenceResolve
// ...as a builtin symbol
final PyFile builtinsFile = builtinCache.getBuiltinsFile();
- if (builtinsFile != null && !PyUtil.isClassPrivateName(referencedName)) {
+ if (builtinsFile != null && !PyUtil.isClassPrivateName(referencedName) && PyUtil.getInitialUnderscores(referencedName) != 1) {
for (RatedResolveResult resolveResult : builtinsFile.multiResolveName(referencedName)) {
result.add(new ImportedResolveResult(resolveResult.getElement(), resolveResult.getRate(), null));
}
diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/noProtectedBuiltinNames.py b/python/testData/inspections/PyUnresolvedReferencesInspection/noProtectedBuiltinNames.py
new file mode 100644
index 000000000000..bab889cd914e
--- /dev/null
+++ b/python/testData/inspections/PyUnresolvedReferencesInspection/noProtectedBuiltinNames.py
@@ -0,0 +1,3 @@
+print(_T, _KT)
+print(__import__)
+print(len)
diff --git a/python/testSrc/com/jetbrains/env/python/testing/CreateConfigurationTestTask.java b/python/testSrc/com/jetbrains/env/python/testing/CreateConfigurationTestTask.java
index 0a1a0d9a47cd..6f88bc48f25e 100644
--- a/python/testSrc/com/jetbrains/env/python/testing/CreateConfigurationTestTask.java
+++ b/python/testSrc/com/jetbrains/env/python/testing/CreateConfigurationTestTask.java
@@ -46,12 +46,12 @@ import java.util.Optional;
*
* @author Ilya.Kazakevich
*/
-abstract class CreateConfigurationTestTask extends PyExecutionFixtureTestTask {
+public abstract class CreateConfigurationTestTask extends PyExecutionFixtureTestTask {
@Nullable
private final String myTestRunnerName;
@NotNull
- private final Class extends RunConfiguration> myExpectedConfigurationType;
+ private final Class myExpectedConfigurationType;
/**
* @param testRunnerName test runner name (to set as default to make sure producer launched)
@@ -77,39 +77,49 @@ abstract class CreateConfigurationTestTask extends P
for (final PsiElement elementToRightClickOn : getPsiElementsToRightClickOn()) {
- final List configurationsFromContext =
- new ConfigurationContext(elementToRightClickOn).getConfigurationsFromContext();
- Assert.assertNotNull("Producers were not able to create any configuration in " + elementToRightClickOn, configurationsFromContext);
-
-
- final Optional maybeConfig = configurationsFromContext.stream()
- .filter(o -> myExpectedConfigurationType.isAssignableFrom(o.getConfiguration().getClass()))
- .findFirst();
- Assert.assertTrue("No configuration of expected type created", maybeConfig.isPresent());
- RunnerAndConfigurationSettings runnerAndConfigurationSettings = maybeConfig.get().getConfigurationSettings();
-
-
- Assert.assertNotNull("Producers were not able to create any configuration in " + elementToRightClickOn, runnerAndConfigurationSettings);
- final RunConfiguration configuration = runnerAndConfigurationSettings.getConfiguration();
- Assert.assertNotNull("No real configuration created", configuration);
- Assert.assertThat("No name for configuration", configuration.getName(), Matchers.not(Matchers.isEmptyOrNullString()));
- Assert.assertThat("Bad configuration type in " + elementToRightClickOn, configuration,
- Matchers.is(Matchers.instanceOf(myExpectedConfigurationType)));
-
- RunManager.getInstance(getProject()).addConfiguration(runnerAndConfigurationSettings, false);
-
@SuppressWarnings("unchecked") // Checked one line above
- final T typedConfiguration = (T)configuration;
+ final T typedConfiguration = createConfigurationByElement(elementToRightClickOn, myExpectedConfigurationType);
checkConfiguration(typedConfiguration, elementToRightClickOn);
}
}), ModalityState.NON_MODAL);
}
+ /**
+ * Emulates right click and create configurwation
+ */
+ @NotNull
+ public static T createConfigurationByElement(@NotNull final PsiElement elementToRightClickOn,
+ @NotNull Class expectedConfigurationType) {
+ final List configurationsFromContext =
+ new ConfigurationContext(elementToRightClickOn).getConfigurationsFromContext();
+ Assert.assertNotNull("Producers were not able to create any configuration in " + elementToRightClickOn, configurationsFromContext);
+
+
+ final Optional maybeConfig = configurationsFromContext.stream()
+ .filter(o -> expectedConfigurationType.isAssignableFrom(o.getConfiguration().getClass()))
+ .findFirst();
+ Assert.assertTrue("No configuration of expected type created", maybeConfig.isPresent());
+ RunnerAndConfigurationSettings runnerAndConfigurationSettings = maybeConfig.get().getConfigurationSettings();
+
+
+ Assert.assertNotNull("Producers were not able to create any configuration in " + elementToRightClickOn, runnerAndConfigurationSettings);
+ final RunConfiguration configuration = runnerAndConfigurationSettings.getConfiguration();
+ Assert.assertNotNull("No real configuration created", configuration);
+ Assert.assertThat("No name for configuration", configuration.getName(), Matchers.not(Matchers.isEmptyOrNullString()));
+ Assert.assertThat("Bad configuration type in " + elementToRightClickOn, configuration,
+ Matchers.is(Matchers.instanceOf(expectedConfigurationType)));
+
+ RunManager.getInstance(elementToRightClickOn.getProject()).addConfiguration(runnerAndConfigurationSettings, false);
+
+ @SuppressWarnings("unchecked") // Checked one line above
+ final T typedConfiguration = (T)configuration;
+ return typedConfiguration;
+ }
+
@NotNull
protected abstract List getPsiElementsToRightClickOn();
-
protected void checkConfiguration(@NotNull final T configuration, @NotNull final PsiElement elementToRightClickOn) {
// Configuration already checked when created, but you can do specific checks here
}
diff --git a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
index 6e66e1a7d0d8..70a901b1cd16 100644
--- a/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonCompletionTest.java
@@ -1114,6 +1114,22 @@ public class PythonCompletionTest extends PyTestCase {
assertSameElements(variants, "mod1", "mod2", "foo", "_bar");
}
+ // PY-22828
+ public void testNoImportedBuiltinNames() {
+ final List suggested = doTestByText("T\n");
+ assertNotNull(suggested);
+ assertContainsElements(suggested, "TypeError");
+ assertDoesntContain(suggested, "TypeVar");
+ }
+
+ // PY-22828
+ public void testNoProtectedBuiltinNames() {
+ final List suggested = doTestByText("_\n");
+ assertNotNull(suggested);
+ assertContainsElements(suggested, "__import__");
+ assertDoesntContain(suggested, "_T", "_KT");
+ }
+
@Override
protected String getTestDataPath() {
return super.getTestDataPath() + "/completion";
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
index 0b4da8a34b8e..e26d550b25ed 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java
@@ -763,6 +763,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase {
doTest();
}
+ // PY-22828
+ public void testNoProtectedBuiltinNames() {
+ doTest();
+ }
+
@NotNull
@Override
protected Class extends PyInspection> getInspectionClass() {
diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
index aed2d015aa6d..27bdd07e1223 100644
--- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
+++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
@@ -20,6 +20,7 @@ arquillian
asensitive
aspectj
async
+asyncable
atomikos
attr
attlist
diff --git a/uast/uast-tests/test/org/jetbrains/uast/test/java/AbstractJavaUastTest.kt b/uast/uast-tests/test/org/jetbrains/uast/test/java/AbstractJavaUastTest.kt
index 03573072efa5..44b336496c80 100644
--- a/uast/uast-tests/test/org/jetbrains/uast/test/java/AbstractJavaUastTest.kt
+++ b/uast/uast-tests/test/org/jetbrains/uast/test/java/AbstractJavaUastTest.kt
@@ -27,6 +27,8 @@ abstract class AbstractJavaUastTest : AbstractUastFixtureTest() {
}
override fun getVirtualFile(testName: String): VirtualFile {
- return LocalFileSystem.getInstance().findFileByPath(File(TEST_JAVA_MODEL_DIR, testName).canonicalPath)!!
+ val localPath = File(TEST_JAVA_MODEL_DIR, testName).path
+ val vFile = LocalFileSystem.getInstance().findFileByPath(localPath)
+ return vFile ?: throw IllegalStateException("Couldn't find virtual file for $localPath")
}
}
\ No newline at end of file
diff --git a/updater/src/com/intellij/updater/Utils.java b/updater/src/com/intellij/updater/Utils.java
index 3ba24502a41d..9ddc5f528c02 100644
--- a/updater/src/com/intellij/updater/Utils.java
+++ b/updater/src/com/intellij/updater/Utils.java
@@ -73,7 +73,7 @@ public class Utils {
public static void delete(File file) throws IOException {
Path start = file.toPath();
- if (Files.exists(start)) {
+ if (Files.exists(start, LinkOption.NOFOLLOW_LINKS)) {
Files.walkFileTree(start, new SimpleFileVisitor() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
diff --git a/updater/testSrc/com/intellij/updater/UtilsTest.java b/updater/testSrc/com/intellij/updater/UtilsTest.java
index 2fa9ec1bcf2d..f45dfa1974b9 100644
--- a/updater/testSrc/com/intellij/updater/UtilsTest.java
+++ b/updater/testSrc/com/intellij/updater/UtilsTest.java
@@ -129,4 +129,17 @@ public class UtilsTest {
assertFalse(link.exists());
assertThat(dir.listFiles()).containsExactly(file);
}
+
+ @Test
+ public void testDeleteDanglingSymlink() throws Exception {
+ assumeTrue(!IS_WINDOWS);
+
+ File dir = tempDir.newFolder("temp_dir");
+ File link = new File(dir, "link");
+ Utils.createLink("dangling", link);
+ assertThat(dir.listFiles()).containsExactly(link);
+
+ Utils.delete(link);
+ assertThat(dir.listFiles()).isEmpty();
+ }
}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsInitializingActivity.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsInitializingActivity.java
index 4cf33566d78e..7947105d3f63 100644
--- a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsInitializingActivity.java
+++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsInitializingActivity.java
@@ -141,7 +141,7 @@ public class BreadcrumbsInitializingActivity implements StartupActivity, DumbAwa
@NotNull FileEditor fileEditor,
@NotNull BreadcrumbsXmlWrapper wrapper) {
//noinspection deprecation
- if (wrapper.above) {
+ if (wrapper.breadcrumbs.above) {
fileEditorManager.addTopComponent(fileEditor, wrapper);
}
else {
@@ -154,7 +154,7 @@ public class BreadcrumbsInitializingActivity implements StartupActivity, DumbAwa
@NotNull FileEditor fileEditor,
@NotNull BreadcrumbsXmlWrapper wrapper) {
//noinspection deprecation
- if (wrapper.above) {
+ if (wrapper.breadcrumbs.above) {
fileEditorManager.removeTopComponent(fileEditor, wrapper);
}
else {
diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java
index 8e5a45b8391c..2a1729cd84e3 100644
--- a/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java
+++ b/xml/impl/src/com/intellij/xml/breadcrumbs/BreadcrumbsXmlWrapper.java
@@ -49,8 +49,6 @@ import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.ui.Gray;
-import com.intellij.ui.RelativeFont;
-import com.intellij.ui.components.breadcrumbs.Breadcrumbs;
import com.intellij.ui.components.breadcrumbs.Crumb;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.update.MergingUpdateQueue;
@@ -77,77 +75,7 @@ import static com.intellij.ui.ScrollPaneFactory.createScrollPane;
* @author spleaner
*/
public class BreadcrumbsXmlWrapper extends JComponent implements Disposable {
- private static final class PsiCrumb extends Crumb.Impl {
- private final PsiElement element;
- private CrumbPresentation presentation;
-
- private PsiCrumb(PsiElement element, BreadcrumbsInfoProvider provider) {
- super(null, provider.getElementInfo(element), provider.getElementTooltip(element));
- this.element = element;
- }
-
- private static PsiElement getElement(Crumb crumb) {
- return crumb instanceof PsiCrumb ? ((PsiCrumb)crumb).element : null;
- }
-
- private static CrumbPresentation getPresentation(Crumb crumb) {
- return crumb instanceof PsiCrumb ? ((PsiCrumb)crumb).presentation : null;
- }
- }
-
- final boolean above = Registry.is("editor.breadcrumbs.above");
-
- private final Breadcrumbs breadcrumbs = new Breadcrumbs() {
- @Override
- protected void paint(Graphics2D g, int x, int y, int width, int height, int thickness) {
- super.paint(g, x, y, width, above ? height : thickness, thickness);
- }
-
- @Override
- public void setFont(Font font) {
- super.setFont(RelativeFont.SMALL.derive(font));
- }
-
- @Override
- public Color getForeground() {
- if (!isForegroundSet()) {
- Color foreground = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.LINE_NUMBERS_COLOR);
- if (foreground != null) return foreground;
- }
- return super.getForeground();
- }
-
- @Override
- public Color getBackground() {
- if (!isBackgroundSet()) {
- Color background = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.GUTTER_BACKGROUND);
- if (background != null) return background;
- }
- return super.getBackground();
- }
-
- @Override
- protected Color getForeground(Crumb crumb) {
- CrumbPresentation presentation = PsiCrumb.getPresentation(crumb);
- if (presentation == null) return super.getForeground(crumb);
-
- Color background = super.getBackground(crumb);
- if (background != null) return super.getForeground(crumb);
-
- return presentation.getBackgroundColor(isSelected(crumb), isHovered(crumb), isAfterSelected(crumb));
- }
-
- @Override
- protected Color getBackground(Crumb crumb) {
- CrumbPresentation presentation = PsiCrumb.getPresentation(crumb);
- if (presentation == null) return super.getBackground(crumb);
-
- Color background = super.getBackground(crumb);
- if (background == null) return null;
-
- return presentation.getBackgroundColor(isSelected(crumb), isHovered(crumb), isAfterSelected(crumb));
- }
- };
+ final PsiBreadcrumbs breadcrumbs = new PsiBreadcrumbs();
private final static Logger LOG = Logger.getInstance(BreadcrumbsXmlWrapper.class);
@@ -256,7 +184,7 @@ public class BreadcrumbsXmlWrapper extends JComponent implements Disposable {
ComponentAdapter resizeListener = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent event) {
- updateBorder(gutterComponent.getWhitespaceSeparatorOffset());
+ breadcrumbs.updateBorder(gutterComponent.getWhitespaceSeparatorOffset());
}
};
@@ -266,10 +194,10 @@ public class BreadcrumbsXmlWrapper extends JComponent implements Disposable {
removeComponentListener(resizeListener);
gutterComponent.removeComponentListener(resizeListener);
});
- updateBorder(gutterComponent.getWhitespaceSeparatorOffset());
+ breadcrumbs.updateBorder(gutterComponent.getWhitespaceSeparatorOffset());
}
else {
- updateBorder(0);
+ breadcrumbs.updateBorder(0);
}
Disposer.register(this, new UiNotifyConnector(breadcrumbs, myQueue));
Disposer.register(this, myQueue);
@@ -277,10 +205,6 @@ public class BreadcrumbsXmlWrapper extends JComponent implements Disposable {
queueUpdate();
}
- private void updateBorder(int offset) {
- breadcrumbs.setBorder(BorderFactory.createEmptyBorder(above ? 2 : 0, offset, above ? 0 : 2, 0));
- }
-
private void updateCrumbs() {
if (breadcrumbs != null && myEditor != null && !myEditor.isDisposed()) {
breadcrumbs.setFont(getEditorFont(myEditor));
@@ -520,6 +444,7 @@ public class BreadcrumbsXmlWrapper extends JComponent implements Disposable {
myEditor.putUserData(BREADCRUMBS_COMPONENT_KEY, null);
}
myEditor = null;
+ breadcrumbs.setCrumbs(null);
}
@Nullable
diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/PsiBreadcrumbs.java b/xml/impl/src/com/intellij/xml/breadcrumbs/PsiBreadcrumbs.java
new file mode 100644
index 000000000000..ce1f7cc82ed1
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/breadcrumbs/PsiBreadcrumbs.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2017 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.xml.breadcrumbs;
+
+import com.intellij.openapi.editor.colors.EditorColors;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.ui.RelativeFont;
+import com.intellij.ui.components.breadcrumbs.Breadcrumbs;
+import com.intellij.ui.components.breadcrumbs.Crumb;
+
+import javax.swing.border.EmptyBorder;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+
+/**
+ * @author Sergey.Malenkov
+ */
+final class PsiBreadcrumbs extends Breadcrumbs {
+ final boolean above = Registry.is("editor.breadcrumbs.above");
+
+ void updateBorder(int offset) {
+ // do not use scaling here because this border is used to align breadcrumbs with a gutter
+ setBorder(new EmptyBorder(above ? 2 : 0, offset, above ? 0 : 2, 0));
+ }
+
+ @Override
+ protected void paint(Graphics2D g, int x, int y, int width, int height, int thickness) {
+ super.paint(g, x, y, width, above ? height : thickness, thickness);
+ }
+
+ @Override
+ public void setFont(Font font) {
+ super.setFont(RelativeFont.SMALL.derive(font));
+ }
+
+ @Override
+ public Color getForeground() {
+ if (!isForegroundSet()) {
+ Color foreground = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.LINE_NUMBERS_COLOR);
+ if (foreground != null) return foreground;
+ }
+ return super.getForeground();
+ }
+
+ @Override
+ public Color getBackground() {
+ if (!isBackgroundSet()) {
+ Color background = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.GUTTER_BACKGROUND);
+ if (background != null) return background;
+ }
+ return super.getBackground();
+ }
+
+ @Override
+ protected Color getForeground(Crumb crumb) {
+ CrumbPresentation presentation = PsiCrumb.getPresentation(crumb);
+ if (presentation == null) return super.getForeground(crumb);
+
+ Color background = super.getBackground(crumb);
+ if (background != null) return super.getForeground(crumb);
+
+ return presentation.getBackgroundColor(isSelected(crumb), isHovered(crumb), isAfterSelected(crumb));
+ }
+
+ @Override
+ protected Color getBackground(Crumb crumb) {
+ CrumbPresentation presentation = PsiCrumb.getPresentation(crumb);
+ if (presentation == null) return super.getBackground(crumb);
+
+ Color background = super.getBackground(crumb);
+ if (background == null) return null;
+
+ return presentation.getBackgroundColor(isSelected(crumb), isHovered(crumb), isAfterSelected(crumb));
+ }
+}
diff --git a/xml/impl/src/com/intellij/xml/breadcrumbs/PsiCrumb.java b/xml/impl/src/com/intellij/xml/breadcrumbs/PsiCrumb.java
new file mode 100644
index 000000000000..247f72e001b2
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/breadcrumbs/PsiCrumb.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2017 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.xml.breadcrumbs;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.ui.components.breadcrumbs.Crumb;
+
+/**
+ * @author Sergey.Malenkov
+ */
+final class PsiCrumb extends Crumb.Impl {
+ final PsiElement element;
+ CrumbPresentation presentation;
+
+ PsiCrumb(PsiElement element, BreadcrumbsInfoProvider provider) {
+ super(null, provider.getElementInfo(element), provider.getElementTooltip(element));
+ this.element = element;
+ }
+
+ static PsiElement getElement(Crumb crumb) {
+ return crumb instanceof PsiCrumb ? ((PsiCrumb)crumb).element : null;
+ }
+
+ static CrumbPresentation getPresentation(Crumb crumb) {
+ return crumb instanceof PsiCrumb ? ((PsiCrumb)crumb).presentation : null;
+ }
+}