summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Dahlstrom <dahlstrom@google.com>2022-07-25 15:00:00 -0700
committerDana Dahlstrom <dahlstrom@google.com>2022-08-08 08:00:00 -0700
commit23cd6161724179c75add0b4e69a543275c41433a (patch)
tree77c480904f0c092a2388cd4f8f5b2e2f95d85261
parent441e3cf8013b8cb185db20018f694a7c3aa69115 (diff)
parent174bb89c93c5eff6c743ccc61ebb93ccb8037cd7 (diff)
downloadidea-23cd6161724179c75add0b4e69a543275c41433a.tar.gz
Merge IntelliJ IDEA 2022.1.4 221.6008.13
Change-Id: I174bb89c93c5eff6c743ccc61ebb93ccb8037cd7
-rw-r--r--.gitignore3
-rwxr-xr-xbin/mac/libmacscreenmenu64.dylibbin213941 -> 214312 bytes
-rw-r--r--build.txt2
-rw-r--r--community-resources/src/idea/IdeaApplicationInfo.xml2
-rw-r--r--java/java-tests/testSrc/com/intellij/util/indexing/IndexDiagnosticTest.kt3
-rw-r--r--java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java10
-rw-r--r--native/MacScreenMenu/src/Menu.m47
-rw-r--r--platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildOptions.groovy6
-rw-r--r--platform/build-scripts/groovy/org/jetbrains/intellij/build/ProductProperties.groovy5
-rw-r--r--platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy6
-rw-r--r--platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/ClassFileChecker.groovy (renamed from platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/ClassVersionChecker.groovy)79
-rw-r--r--platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CrossPlatformDistributionBuilder.groovy5
-rw-r--r--platform/diff-impl/intellij.platform.diff.impl.iml1
-rw-r--r--platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffSettings.kt14
-rw-r--r--platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java45
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java6
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java71
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java32
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java57
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java17
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java8
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplate.java16
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplateWithMultipleExpressions.java10
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateEditor.java19
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateExpressionCondition.java17
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/CreateFileAction.java6
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java5
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/ForceIndexRescanningAction.java6
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/RescanIndexesAction.kt8
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java31
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistory.kt52
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryFusReporterListener.kt13
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryImpl.kt6
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/diagnostic/dto/JsonConverter.kt2
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/diagnostic/dto/JsonProjectIndexingHistoryTimes.kt3
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/diagnostic/presentation/jsonToHtmlConverter.kt5
-rw-r--r--platform/lang-impl/testSources/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryImplTest.kt18
-rw-r--r--platform/platform-api/src/com/intellij/ui/mac/screenmenu/Menu.java24
-rw-r--r--platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeUsageCounterCollector.java5
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java12
-rw-r--r--platform/platform-tests/testSrc/com/intellij/openapi/project/DumbServiceImplTest.groovy5
-rw-r--r--platform/platform-tests/testSrc/com/intellij/util/io/PersistencePerformanceTest.java5
-rw-r--r--platform/remoteDev-util/src/com/intellij/remoteDev/downloader/JetBrainsClientDownloaderConfigurationProvider.kt10
-rw-r--r--platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java9
-rw-r--r--platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java51
-rw-r--r--platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.kt15
-rw-r--r--platform/vcs-log/impl/src/com/intellij/vcs/log/ui/details/commit/CommitDetailsPanel.kt18
-rw-r--r--plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java3
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/numeric/unpredictable_big_decimal/Underscores.after.java6
-rw-r--r--plugins/InspectionGadgets/test/com/siyeh/igfixes/numeric/unpredictable_big_decimal/Underscores.java6
-rw-r--r--plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/numeric/UnpredictableBigDecimalConstructorCallFixTest.java6
-rw-r--r--plugins/devkit/devkit-core/resources/fileTemplates/j2ee/devkit-build.gradle.kts.ft3
-rw-r--r--plugins/git4idea/src/git4idea/checkin/GitSkipHooksCommitHandlerFactory.kt23
-rw-r--r--plugins/grazie/src/main/kotlin/com/intellij/grazie/grammar/LanguageToolChecker.kt8
-rw-r--r--plugins/grazie/src/main/kotlin/com/intellij/grazie/text/TextContentBuilder.java26
-rw-r--r--plugins/grazie/src/main/kotlin/com/intellij/grazie/text/TextContentImpl.java10
-rw-r--r--plugins/grazie/src/test/kotlin/com/intellij/grazie/text/TextContentTest.java2
-rw-r--r--plugins/grazie/src/test/kotlin/com/intellij/grazie/text/TextExtractionTest.java16
-rw-r--r--plugins/ide-features-trainer/src/training/featuresSuggester/settings/FeatureSuggesterSettings.kt4
-rw-r--r--plugins/package-search/src/com/jetbrains/packagesearch/intellij/plugin/extensibility/PackageVersionRangeInspection.kt24
-rw-r--r--plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltConfigurationProducer.java8
-rw-r--r--plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java1
-rw-r--r--python/ideCoreSrc/idea/PyCharmCoreApplicationInfo.xml2
-rw-r--r--uast/uast-common/src/org/jetbrains/uast/UastUtils.kt8
64 files changed, 588 insertions, 358 deletions
diff --git a/.gitignore b/.gitignore
index 5e640a6eff50..7a81c1e3c8de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,4 +17,5 @@ edu/dependencies/.gradle
edu/dependencies/build
native/**/build/
stale_outputs_checked
-/android \ No newline at end of file
+/android
+/tools/ideTestingFramework/intellij.tools.ide.starter \ No newline at end of file
diff --git a/bin/mac/libmacscreenmenu64.dylib b/bin/mac/libmacscreenmenu64.dylib
index 8aabfd7209f6..dfd9b142573f 100755
--- a/bin/mac/libmacscreenmenu64.dylib
+++ b/bin/mac/libmacscreenmenu64.dylib
Binary files differ
diff --git a/build.txt b/build.txt
index 66d5774b2fdb..80f4908c6d38 100644
--- a/build.txt
+++ b/build.txt
@@ -1 +1 @@
-221.5921.22.2211.SNAPSHOT
+221.6008.13.2211.SNAPSHOT
diff --git a/community-resources/src/idea/IdeaApplicationInfo.xml b/community-resources/src/idea/IdeaApplicationInfo.xml
index 6db949992468..80843aa9e787 100644
--- a/community-resources/src/idea/IdeaApplicationInfo.xml
+++ b/community-resources/src/idea/IdeaApplicationInfo.xml
@@ -1,7 +1,7 @@
<component xmlns="http://jetbrains.org/intellij/schema/application-info"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jetbrains.org/intellij/schema/application-info http://jetbrains.org/intellij/schema/ApplicationInfo.xsd">
- <version major="2022" minor="1.3"/>
+ <version major="2022" minor="1.4"/>
<company name="JetBrains s.r.o." url="https://www.jetbrains.com"/>
<build number="IC-__BUILD__" date="__BUILD_DATE__" majorReleaseDate="20220412" />
<logo url="/idea_community_logo.png" textcolor="ffffff" progressColor="ffae00" progressY="396" progressHeight="4" />
diff --git a/java/java-tests/testSrc/com/intellij/util/indexing/IndexDiagnosticTest.kt b/java/java-tests/testSrc/com/intellij/util/indexing/IndexDiagnosticTest.kt
index cbda9b713438..8bdfcbcbaceb 100644
--- a/java/java-tests/testSrc/com/intellij/util/indexing/IndexDiagnosticTest.kt
+++ b/java/java-tests/testSrc/com/intellij/util/indexing/IndexDiagnosticTest.kt
@@ -10,7 +10,6 @@ import com.intellij.openapi.project.getProjectCachePath
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
import com.intellij.util.SystemProperties
import com.intellij.util.indexing.diagnostic.IndexDiagnosticDumper
-import com.intellij.util.indexing.diagnostic.ScanningType
import com.intellij.util.indexing.diagnostic.dto.*
import com.intellij.util.indexing.diagnostic.dump.paths.PortableFilePath
import org.junit.Assert
@@ -74,7 +73,7 @@ class IndexDiagnosticTest : JavaCodeInsightFixtureTestCase() {
projectName = "projectName",
times = JsonProjectIndexingHistoryTimes(
"reason",
- ScanningType.PARTIAL,
+ false,
JsonDuration(123),
JsonDuration(456),
JsonDuration(789),
diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java
index c03ae151b04d..7fb108f7066a 100644
--- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java
+++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java
@@ -1195,8 +1195,14 @@ public class JavaMatchingVisitor extends JavaElementVisitor {
final Object value1 = expression.getValue();
final Object value2 = other.getValue();
if ((value1 instanceof String || value1 instanceof Character) && (value2 instanceof String || value2 instanceof Character)) {
- myMatchingVisitor.setResult(myMatchingVisitor.matchText(StructuralSearchUtil.normalize(value1.toString()),
- StructuralSearchUtil.normalize(value2.toString())));
+ String patternValue = value1.toString();
+ if (!patternValue.isEmpty() && patternValue.equals(patternValue.trim())) {
+ myMatchingVisitor.setResult(myMatchingVisitor.matchText(StructuralSearchUtil.normalize(patternValue),
+ StructuralSearchUtil.normalize(value2.toString())));
+ }
+ else {
+ myMatchingVisitor.setResult(myMatchingVisitor.matchText(patternValue, value2.toString()));
+ }
}
else if (value1 != null && value2 != null) {
myMatchingVisitor.setResult(value1.equals(value2));
diff --git a/native/MacScreenMenu/src/Menu.m b/native/MacScreenMenu/src/Menu.m
index f3f6ef3e02b6..bcc54947c925 100644
--- a/native/MacScreenMenu/src/Menu.m
+++ b/native/MacScreenMenu/src/Menu.m
@@ -427,4 +427,49 @@ Java_com_intellij_ui_mac_screenmenu_Menu_nativeGetAppMenu(JNIEnv *env, jclass pe
}
return (jlong)appMenu;
JNI_COCOA_EXIT();
-} \ No newline at end of file
+}
+
+/*
+ * Class: com_intellij_ui_mac_screenmenu_Menu
+ * Method: nativeRenameAppMenuItems
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_com_intellij_ui_mac_screenmenu_Menu_nativeRenameAppMenuItems(JNIEnv *env, jclass peerClass, jobjectArray jStringArray) {
+ JNI_COCOA_ENTER();
+ const int stringCount = (*env)->GetArrayLength(env, jStringArray);
+ if (stringCount < 2) return; // simple protection (just for insurance)
+ NSMutableArray * __strong stringArray = [NSMutableArray arrayWithCapacity:stringCount];
+ for (int i = 0; i < stringCount; i += 2) {
+ jstring jTitle = (jstring) ((*env)->GetObjectArrayElement(env, jStringArray, i));
+ [stringArray addObject:JavaStringToNSString(env, jTitle)];
+ if (i + 1 >= stringCount) return; // simple protection (just for insurance)
+ jstring jLocalizedTitle = (jstring) ((*env)->GetObjectArrayElement(env, jStringArray, i + 1));
+ [stringArray addObject:JavaStringToNSString(env, jLocalizedTitle)];
+ }
+
+ dispatch_block_t block = ^{
+ NSMenu * mainMenu = [NSApplication sharedApplication].mainMenu;
+ id appMenu = [mainMenu numberOfItems] > 0 ? [mainMenu itemAtIndex:0] : nil;
+ if (appMenu != nil) {
+ appMenu = [appMenu submenu];
+ }
+ for (int i = 0; i < stringCount; i += 2) {
+ NSString * title = [stringArray objectAtIndex:i];
+ NSString * localizedTitle = [stringArray objectAtIndex:i + 1];
+ NSMenuItem * item = findItemByTitle(appMenu, title);
+ if (item != nil) {
+ [item setTitle:localizedTitle];
+ if ([item.view isKindOfClass:CustomMenuItemView.class]) {
+ [(CustomMenuItemView *)(item.view) recalcSizes];
+ }
+ }
+ }
+ };
+ if ([NSThread isMainThread]) {
+ block();
+ } else {
+ dispatch_async(dispatch_get_main_queue(), block);
+ }
+ JNI_COCOA_EXIT();
+}
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildOptions.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildOptions.groovy
index c38322f3f363..37398d293c7b 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildOptions.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/BuildOptions.groovy
@@ -234,6 +234,12 @@ final class BuildOptions {
static final String VALIDATE_MODULES_STRUCTURE = "intellij.build.module.structure"
boolean validateModuleStructure = System.getProperty(VALIDATE_MODULES_STRUCTURE, "false").toBoolean()
+ /**
+ * Verify whether class files have a forbidden subpaths in them, false by default
+ */
+ static final String VALIDATE_CLASSFILE_SUBPATHS_PROPERTY = "intellij.verify.classfile.subpaths"
+ boolean validateClassFileSubpaths = System.getProperty(VALIDATE_CLASSFILE_SUBPATHS_PROPERTY, "false").toBoolean()
+
@ApiStatus.Internal
public boolean compressNonBundledPluginArchive = true
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/ProductProperties.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/ProductProperties.groovy
index e12066cac2ca..3639159c8e4f 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/ProductProperties.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/ProductProperties.groovy
@@ -157,6 +157,11 @@ abstract class ProductProperties {
Map<String, String> versionCheckerConfig = null
/**
+ * Strings which are forbidden as a part of resulting class file path
+ */
+ List<String> forbiddenClassFileSubPaths = []
+
+ /**
* Paths to properties files the content of which should be appended to idea.properties file
*/
List<String> additionalIDEPropertiesFilePaths = []
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy
index cc27f9d45811..4b37b32c9150 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/BuildTasksImpl.groovy
@@ -963,10 +963,8 @@ idea.fatal.error.notification=disabled
DistributionJARsBuilder distributionJARsBuilder = compileModulesForDistribution(context)
ProjectStructureMapping projectStructureMapping = distributionJARsBuilder.buildJARs(context)
layoutShared(context)
- Map<String, String> checkerConfig = context.productProperties.versionCheckerConfig
- if (checkerConfig != null) {
- ClassVersionChecker.checkVersions(checkerConfig, context, context.paths.distAllDir)
- }
+
+ ClassFileChecker.checkClassFiles(context.paths.distAllDir, context)
if (context.productProperties.buildSourcesArchive) {
DistributionJARsBuilder.buildSourcesArchive(projectStructureMapping, context)
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/ClassVersionChecker.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/ClassFileChecker.groovy
index 15c7a62f9e6b..2a6439466881 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/ClassVersionChecker.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/ClassFileChecker.groovy
@@ -36,7 +36,26 @@ import java.util.zip.ZipException
* <p>Example: <code>["": "1.8", "lib/idea_rt.jar": "1.3"]</code>.</p>
*/
@CompileStatic
-final class ClassVersionChecker {
+final class ClassFileChecker {
+ static void checkClassFiles(Path targetFile, BuildContext context) {
+ Map<String, String> versionCheckerConfig =
+ context.options.buildStepsToSkip.contains(BuildOptions.VERIFY_CLASS_FILE_VERSIONS)
+ ? [:]
+ : context.productProperties.versionCheckerConfig ?: [:]
+
+ List<String> forbiddenSubPaths =
+ context.options.validateClassFileSubpaths
+ ? context.productProperties.forbiddenClassFileSubPaths ?: []
+ : []
+
+ boolean classFileCheckRequired =
+ (!versionCheckerConfig.isEmpty() || !forbiddenSubPaths.isEmpty())
+
+ if (classFileCheckRequired) {
+ checkClassFilesImpl(versionCheckerConfig, forbiddenSubPaths, context, targetFile)
+ }
+ }
+
private static final class Rule {
final String path
final int version
@@ -49,30 +68,32 @@ final class ClassVersionChecker {
}
}
- private final List<Rule> rules
+ private final List<Rule> versionRules
+ private final List<String> forbiddenSubPaths
private AtomicInteger checkedJarCount = new AtomicInteger()
private AtomicInteger checkedClassCount = new AtomicInteger()
- private ClassVersionChecker(List<Rule> rules) {
- this.rules = rules
+ private ClassFileChecker(List<Rule> versionRules, List<String> forbiddenSubPaths) {
+ this.versionRules = versionRules
+ this.forbiddenSubPaths = forbiddenSubPaths
}
static int classVersion(String version) {
return version.isEmpty() ? -1 : JavaVersion.parse(version).feature + 44 // 1.1 = 45
}
- static void checkVersions(Map<String, String> config, BuildContext context, Path root) {
+ private static void checkClassFilesImpl(Map<String, String> versionCheckConfig, List<String> forbiddenSubPaths, BuildContext context, Path root) {
if (context.options.buildStepsToSkip.contains(BuildOptions.VERIFY_CLASS_FILE_VERSIONS)) {
return
}
BuildHelper.getInstance(context).span(TracerManager.spanBuilder("verify class file versions")
- .setAttribute("ruleCount", config.size())
- .setAttribute("root", root.toString()), new Runnable() {
+ .setAttribute("ruleCount", versionCheckConfig.size())
+ .setAttribute("root", root.toString()).setAttribute("forbiddenSubpathCount", forbiddenSubPaths.size()), new Runnable() {
@Override
void run() {
- List<Rule> rules = new ArrayList<Rule>(config.size())
- for (Map.Entry<String, String> entry : config.entrySet()) {
+ List<Rule> rules = new ArrayList<Rule>(versionCheckConfig.size())
+ for (Map.Entry<String, String> entry : versionCheckConfig.entrySet()) {
rules.add(new Rule(entry.key, classVersion(entry.value)))
}
rules.sort(new Comparator<Rule>() {
@@ -81,11 +102,11 @@ final class ClassVersionChecker {
return Integer.compare(-o1.path.length(), -o2.path.length())
}
})
- if (rules.isEmpty() || !rules.last().path.isEmpty()) {
+ if (!rules.isEmpty() && !rules.last().path.isEmpty()) {
throw new IllegalArgumentException("Invalid configuration: missing default version")
}
- ClassVersionChecker checker = new ClassVersionChecker(rules)
+ ClassFileChecker checker = new ClassFileChecker(rules, forbiddenSubPaths)
Collection<String> errors = new ConcurrentLinkedQueue<>()
if (Files.isDirectory(root)) {
checker.visitDirectory(root, "", errors)
@@ -94,7 +115,7 @@ final class ClassVersionChecker {
checker.visitFile(root, "", errors)
}
- if (checker.checkedClassCount.get() == 0) {
+ if (!rules.isEmpty() && checker.checkedClassCount.get() == 0) {
context.messages.error("No classes found under $root - please check the configuration")
}
@@ -107,13 +128,13 @@ final class ClassVersionChecker {
for (String error in errors) {
context.messages.warning(error)
}
- context.messages.error("Failed with $errorCount problems")
+ context.messages.error("ClassFileChecker failed with $errorCount problems")
}
Collection<String> unusedRules = rules.findResults { it.wasUsed ? null : it.path }
if (!unusedRules.isEmpty()) {
context.messages.error("Class version check rules for the following paths don't match any files, probably entries in " +
- "ProductProperties::versionCheckerConfig are out of date:\n${String.join("\n", unusedRules)}")
+ "ProductProperties::versionCheckerConfig are out of date:\n${String.join("\n", unusedRules)}")
}
}
})
@@ -155,8 +176,13 @@ final class ClassVersionChecker {
if (fullPath.endsWith(".zip") || fullPath.endsWith(".jar")) {
visitZip(fullPath, relPath, new ZipFile(FileChannel.open(file, EnumSet.of(StandardOpenOption.READ))), errors)
}
- else if (fullPath.endsWith(".class") && !fullPath.endsWith("module-info.class") && !isMultiVersion(fullPath)) {
- new BufferedInputStream(Files.newInputStream(file)).withCloseable { checkVersion(relPath, it, errors) }
+ else if (fullPath.endsWith(".class")) {
+ checkIfSubPathIsForbidden(relPath, errors)
+
+ boolean contentCheckRequired = !versionRules.isEmpty() && !fullPath.endsWith("module-info.class") && !isMultiVersion(fullPath)
+ if (contentCheckRequired) {
+ new BufferedInputStream(Files.newInputStream(file)).withCloseable { checkVersion(relPath, it, errors) }
+ }
}
}
@@ -185,8 +211,15 @@ final class ClassVersionChecker {
throw new RuntimeException("Cannot read " + childZipPath, e)
}
}
- else if (name.endsWith(".class") && !name.endsWith("module-info.class") && !isMultiVersion(name)) {
- checkVersion(join(zipRelPath, "!/", name), file.getInputStream(entry), errors)
+ else if (name.endsWith(".class")) {
+ String relPath = join(zipRelPath, "!/", name)
+
+ checkIfSubPathIsForbidden(relPath, errors)
+
+ boolean contentCheckRequired = !versionRules.isEmpty() && !name.endsWith("module-info.class") && !isMultiVersion(name)
+ if (contentCheckRequired) {
+ checkVersion(relPath, file.getInputStream(entry), errors)
+ }
}
}
}
@@ -195,6 +228,14 @@ final class ClassVersionChecker {
}
}
+ private checkIfSubPathIsForbidden(String relPath, Collection<String> errors) {
+ for (f in forbiddenSubPaths) {
+ if (relPath.contains(f)) {
+ errors.add(relPath + " .class file has a forbidden subpath: " + f)
+ }
+ }
+ }
+
private static String join(String prefix, String separator, String suffix) {
return prefix.isEmpty() ? suffix : (prefix + separator + suffix)
}
@@ -215,7 +256,7 @@ final class ClassVersionChecker {
return
}
- Rule rule = rules.find { it.path.isEmpty() || path.startsWith(it.path) }
+ Rule rule = versionRules.find { it.path.isEmpty() || path.startsWith(it.path) }
rule.wasUsed = true
int expected = rule.version
if (expected > 0 && major > expected) {
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CrossPlatformDistributionBuilder.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CrossPlatformDistributionBuilder.groovy
index da5171e94ffb..793ce86155c5 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CrossPlatformDistributionBuilder.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/CrossPlatformDistributionBuilder.groovy
@@ -47,10 +47,7 @@ final class CrossPlatformDistributionBuilder {
ProductInfoValidator.checkInArchive(context, targetFile, "")
context.notifyArtifactBuilt(targetFile)
- Map<String, String> checkerConfig = context.productProperties.versionCheckerConfig
- if (checkerConfig != null) {
- ClassVersionChecker.checkVersions(checkerConfig, context, targetFile)
- }
+ ClassFileChecker.checkClassFiles(targetFile, context)
return targetFile
}
}
diff --git a/platform/diff-impl/intellij.platform.diff.impl.iml b/platform/diff-impl/intellij.platform.diff.impl.iml
index afc78f576e8d..5d1b8d7fe421 100644
--- a/platform/diff-impl/intellij.platform.diff.impl.iml
+++ b/platform/diff-impl/intellij.platform.diff.impl.iml
@@ -23,6 +23,5 @@
<orderEntry type="library" name="fastutil-min" level="project" />
<orderEntry type="module" module-name="intellij.platform.ide.util.io.impl" />
<orderEntry type="library" name="kotlinx-coroutines-jdk8" level="project" />
- <orderEntry type="library" name="StreamEx" level="project" />
</component>
</module> \ No newline at end of file
diff --git a/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffSettings.kt b/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffSettings.kt
index 8dcfcc26d45c..6212c47a899a 100644
--- a/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffSettings.kt
+++ b/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffSettings.kt
@@ -18,6 +18,10 @@ class ExternalDiffSettings : BaseState(), PersistentStateComponent<ExternalDiffS
copyFrom(state)
}
+ override fun noStateLoaded() {
+ isSettingsMigrated = true
+ }
+
@get:OptionTag("MIGRATE_OLD_SETTINGS")
var isSettingsMigrated by property(false)
@@ -98,6 +102,16 @@ class ExternalDiffSettings : BaseState(), PersistentStateComponent<ExternalDiffS
get() = FileTypeManager.getInstance()
@JvmStatic
+ fun findDefaultDiffTool(): ExternalTool? {
+ val diffToolName = instance.defaultToolConfiguration.diffToolName
+
+ if (diffToolName == ExternalToolConfiguration.BUILTIN_TOOL) return null
+ val diffTools = instance.externalTools[ExternalToolGroup.DIFF_TOOL] ?: return null
+
+ return findTool(diffTools, diffToolName)
+ }
+
+ @JvmStatic
fun findDiffTool(fileType: FileType): ExternalTool? {
val diffToolName = findToolConfiguration(fileType)?.diffToolName
?: instance.defaultToolConfiguration.diffToolName
diff --git a/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java b/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java
index 1c3643482ece..e5f9eb381a85 100644
--- a/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java
+++ b/platform/diff-impl/src/com/intellij/diff/tools/external/ExternalDiffTool.java
@@ -14,12 +14,14 @@ import com.intellij.openapi.ListSelection;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.DiffBundle;
import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.fileTypes.UnknownFileType;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.util.io.FileUtilRt;
@@ -29,12 +31,13 @@ import com.intellij.util.ThrowableConvertor;
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
import com.intellij.util.concurrency.annotations.RequiresEdt;
import com.intellij.util.containers.ContainerUtil;
-import one.util.streamex.StreamEx;
+import com.intellij.util.containers.JBIterable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.List;
public final class ExternalDiffTool {
@@ -52,12 +55,32 @@ public final class ExternalDiffTool {
if (isDefault()) return true;
FileTypeManager fileTypeManager = FileTypeManager.getInstance();
- return diffProducers.stream()
- .map(DiffRequestProducer::getName)
- .filter(filePath -> !FileUtilRt.getExtension(filePath).equals("tmp"))
- .map(filePath -> fileTypeManager.getFileTypeByFileName(filePath))
- .distinct()
- .anyMatch(fileType -> ExternalDiffSettings.findDiffTool(fileType) != null);
+ return JBIterable.from(diffProducers)
+ .map(DiffRequestProducer::getName)
+ .filter(filePath -> !FileUtilRt.getExtension(filePath).equals("tmp"))
+ .map(filePath -> fileTypeManager.getFileTypeByFileName(filePath))
+ .unique()
+ .map(fileType -> ExternalDiffSettings.findDiffTool(fileType))
+ .filter(Conditions.notNull())
+ .first() != null;
+ }
+
+ @Nullable
+ private static ExternalDiffSettings.ExternalTool getExternalToolFor(@NotNull ContentDiffRequest request) {
+ ExternalDiffSettings.ExternalTool diffTool = JBIterable.from(request.getContents())
+ .map(content -> content.getContentType())
+ .filter(Conditions.notNull())
+ .unique()
+ .sort(Comparator.comparing(fileType -> fileType != UnknownFileType.INSTANCE ? -1 : 1))
+ .map(fileType -> ExternalDiffSettings.findDiffTool(fileType))
+ .filter(Conditions.notNull())
+ .first();
+ if (diffTool != null) return diffTool;
+
+ if (isDefault()) {
+ return ExternalDiffSettings.findDefaultDiffTool();
+ }
+ return null;
}
public static boolean showIfNeeded(@Nullable Project project,
@@ -120,13 +143,7 @@ public final class ExternalDiffTool {
throws IOException, ExecutionException {
if (!canShow(request)) return false;
- List<DiffContent> contents = ((ContentDiffRequest)request).getContents();
- ExternalDiffSettings.ExternalTool externalTool = StreamEx.of(contents)
- .map(content -> content.getContentType())
- .nonNull()
- .map(fileType -> ExternalDiffSettings.findDiffTool(fileType))
- .nonNull()
- .findFirst().orElse(null);
+ ExternalDiffSettings.ExternalTool externalTool = getExternalToolFor(((ContentDiffRequest)request));
if (externalTool == null) return false;
showRequest(project, request, externalTool);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java
index 7a131a837ffa..d9cfa62f2748 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.completion;
import com.intellij.codeInsight.completion.CompletionParameters;
@@ -24,9 +24,7 @@ class PostfixTemplatesCompletionProvider extends CompletionProvider<CompletionPa
Editor editor = parameters.getEditor();
if (!isCompletionEnabled(parameters) || LiveTemplateCompletionContributor.shouldShowAllTemplates() ||
editor.getCaretModel().getCaretCount() != 1) {
- /*
- disabled or covered with {@link com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor}
- */
+ // disabled or covered with com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor
return;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java
index 4630390d962e..6ffef2da0658 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.CodeInsightBundle;
@@ -10,6 +10,7 @@ import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -19,20 +20,27 @@ import java.util.Objects;
/**
* Represents a postfix template.
- * Postfix templates are live template that applicable to a specific code fragment e.g. "sout" template:
+ * Postfix template is a live template that is applicable to a specific code fragment, e.g. "sout" template:
+ * <br>
* <code>
* "hello".sout
* </code>
+ * <br>
* is expanded to:
- * <code>
- * System.out.println("hello")
- * <code/>
* <br>
- * Editable templates:
- * editable postfix template MUST know the provider that created it.
+ * <code>
+ * System.out.println("hello");
+ * </code>
* <p>
- * Editable postfix templates MUST provide proper equals/hashCode implementation.
- * Equal postfix templates produces by the very same provider will overwrite each other.
+ * Editable postfix template MUST:
+ * <ul>
+ * <li>know the provider that created it</li>
+ * <li>provide proper {@code equals()}/{@code hashCode()} implementation</li>
+ * </ul>
+ * Equal postfix templates produced by the very same provider will overwrite each other.
+ *
+ * @see PostfixTemplateProvider
+ * @see <a href="https://plugins.jetbrains.com/docs/intellij/postfix-templates.html">Postfix Templates (IntelliJ Platform Docs)</a>
*/
public abstract class PostfixTemplate {
private final @NotNull @NonNls String myId;
@@ -92,9 +100,8 @@ public abstract class PostfixTemplate {
return defaultDescription;
}
-
/**
- * Template's identifier. Used for saving the settings related to this templates.
+ * @return identifier used for saving the settings related to this template
*/
@NotNull
public @NonNls String getId() {
@@ -102,25 +109,32 @@ public abstract class PostfixTemplate {
}
/**
- * Template's key. Used while expanding template in editor.
- *
- * @return
+ * @return key used for expanding the template in the editor
*/
@NotNull
public final @NlsSafe String getKey() {
return myKey;
}
+ /**
+ * @return template name displayed in UI
+ */
@NotNull
public @NlsSafe String getPresentableName() {
return myPresentableName;
}
+ /**
+ * @return template description displayed in UI
+ */
@NotNull
public @NlsContexts.DetailedDescription String getDescription() {
return myLazyDescription.getValue();
}
+ /**
+ * @return short example of the expanded form shown in the completion popup and templates tree on the configuration page
+ */
@NotNull
public @NlsSafe String getExample() {
return myExample;
@@ -130,30 +144,53 @@ public abstract class PostfixTemplate {
return true;
}
+ /**
+ * @return {@code true} if general postfix templates setting is enabled and this template is enabled in settings
+ */
public boolean isEnabled(PostfixTemplateProvider provider) {
final PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
return settings.isPostfixTemplatesEnabled() && settings.isTemplateEnabled(this, provider);
}
+ /**
+ * Determines whether this template can be used in the given context specified by the parameters.
+ *
+ * @param context PSI element before the template key
+ * @param copyDocument copy of the document that contains changes introduced
+ * in {@link PostfixTemplateProvider#preCheck(PsiFile, Editor, int)} method
+ * @param newOffset offset before the template key
+ * @return {@code true} if template is applicable in the given context, {@code false} otherwise
+ */
public abstract boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset);
+ /**
+ * Inserts the template content in the given editor.
+ *
+ * @param context PSI element before the template key
+ * @param editor current editor
+ */
public abstract void expand(@NotNull PsiElement context, @NotNull Editor editor);
+ /**
+ * @return the {@link PostfixTemplateProvider} that provided this template
+ */
@Nullable
public PostfixTemplateProvider getProvider() {
return myProvider;
}
/**
- * Builtin templates cannot be removed.
- * If they are editable, they can be restored to default.
+ * Built-in templates cannot be removed.
+ * If they are editable, they can be restored to the default state.
*/
public boolean isBuiltin() {
return true;
}
/**
- * Template can be edit. Template can be editable if its provider is not null and its key starts with . can be edited.
+ * Return true if this template can be edited.
+ * <p>
+ * Note that a template can be edited if its provider is not {@code null} and its key starts with {@code .} (dot), e.g., {@code .iter}.
*/
public boolean isEditable() {
return true;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java
index 57e2850b8eb4..59f23bd35012 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java
@@ -1,21 +1,6 @@
-/*
- * 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.
- */
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
-
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiElement;
import com.intellij.util.Function;
@@ -24,20 +9,23 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
- * Interface provides method used in {@link PostfixTemplateWithExpressionSelector}
+ * Provides information about expressions available in the current postfix template context.
+ *
+ * @see PostfixTemplateWithExpressionSelector
+ * @see <a href="https://plugins.jetbrains.com/docs/intellij/advanced-postfix-templates.html">Advanced Postfix Templates (IntelliJ Platform Docs)</a>
*/
public interface PostfixTemplateExpressionSelector {
/**
- * Check that we can select not-null expression(PsiElement) in current context
+ * Checks whether the current context contains applicable expression that can be selected.
*/
boolean hasExpression(@NotNull PsiElement context,
@NotNull Document copyDocument,
int newOffset);
/**
- * Return list of all possible expressions in the current position.
- * Postfix template implementation shows popup chooser (if size > 1)
+ * Returns the list of all expressions applicable in the current context.
+ * If the list size is greater than 1, then expression chooser popup is shown to a user.
*/
@NotNull
List<PsiElement> getExpressions(@NotNull PsiElement context,
@@ -45,8 +33,8 @@ public interface PostfixTemplateExpressionSelector {
int offset);
/**
- * returns renderer for expressions from {@link #getExpressions}.
- * Renderer is used for showing popup chooser
+ * Returns a renderer for expressions returned from the {@link #getExpressions} method,
+ * which is used to render template item in the expression chooser popup.
*/
@NotNull
Function<PsiElement, String> getRenderer();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java
index c516bf3c4c46..446e9e581d30 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateProvider.java
@@ -1,7 +1,6 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
-
import com.intellij.codeInsight.template.postfix.templates.editable.PostfixTemplateEditor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.NlsActions;
@@ -16,12 +15,15 @@ import java.util.Set;
/**
* Extension point interface for providing language specific postfix templates.
+ *
* @see LanguagePostfixTemplate#EP_NAME
* @see PostfixTemplate
+ * @see <a href=https://plugins.jetbrains.com/docs/intellij/postfix-completion.html">Postfix Completion (IntelliJ Platform Docs)</a>
*/
public interface PostfixTemplateProvider {
+
/**
- * Identifier of template provider. Used for storing settings of provider's templates.
+ * @return identifier used for storing settings of this provider's templates
*/
@NotNull
default @NonNls String getId() {
@@ -29,7 +31,7 @@ public interface PostfixTemplateProvider {
}
/**
- * Presentation name of editable template type. If null, provider doesn't allow to custom templates.
+ * @return presentation name of an editable template type. If {@code null}, the provider doesn't allow customizing its templates.
*/
@Nullable
default @NlsActions.ActionText String getPresentableName() {
@@ -37,54 +39,59 @@ public interface PostfixTemplateProvider {
}
/**
- * Returns builtin templates registered in the provider in their original state.
+ * @return built-in templates registered in the provider in their original state.
* Consider using {@link PostfixTemplatesUtils#getAvailableTemplates(PostfixTemplateProvider)} for actually enabled templates.
*/
@NotNull
Set<PostfixTemplate> getTemplates();
/**
- * Check symbol can separate template keys
+ * @return {@code true} if a given symbol can separate template keys
*/
boolean isTerminalSymbol(char currentChar);
/**
- * Prepare file for template expanding. Running on EDT.
- * E.g. java postfix templates adds semicolon after caret in order to simplify context checking.
+ * Prepares a file for template expanding,
+ * e.g. a Java postfix template adds a semicolon after caret in order to simplify context checking.
* <p>
* File content doesn't contain template's key, it is deleted just before this method invocation.
* <p>
- * Note that while postfix template is checking its availability the file parameter is a _COPY_ of the real file,
- * so you can do with it anything that you want, but in the same time it doesn't recommended to modify editor state because it's real.
+ * Running on EDT.
+ * <p>
+ * Note that when postfix template's availability is checked, the {@code file} parameter is a COPY of the actual file,
+ * so you can do with it anything that you want.
+ * At the same time, it is not recommended to modify the editor state because it's real.
*/
void preExpand(@NotNull PsiFile file, @NotNull Editor editor);
/**
- * Invoked after template finished (doesn't matter if it finished successfully or not).
- * E.g. java postfix template use this method for deleting inserted semicolon.
+ * Cleans up a file content after template expanding is finished (doesn't matter if it finished successfully or not),
+ * e.g. a Java postfix template cleans a semicolon inserted in {@link #preExpand(PsiFile, Editor)}.
*/
void afterExpand(@NotNull PsiFile file, @NotNull Editor editor);
/**
- * Prepare file for checking availability of templates.
- * Almost the same as {@link this#preExpand(PsiFile, Editor)} with several differences:
- * 1. Processes copy of file. So implementations can modify it without corrupting the real file.
- * 2. Could be invoked from anywhere (EDT, write-action, read-action, completion-thread etc.). So implementations should make
- * additional effort to make changes in file.
+ * Prepares a file for checking the availability of templates.
+ * Almost the same as {@link #preExpand(PsiFile, Editor)} with several differences:
+ * <ol>
+ * <li>Processes copy of the file. So implementations can modify it without corrupting the real file.
+ * <li>Could be invoked from anywhere (EDT, write-action, read-action, completion-thread, etc.) so implementations should make
+ * additional effort to make changes in the file.
+ * </ol>
* <p>
- * Content of file copy doesn't contain template's key, it is deleted just before this method invocation.
+ * File content doesn't contain template's key, it is deleted just before this method invocation.
* <p>
- * NOTE: editor is real (not copy) and it doesn't represents the copyFile.
- * So it's safer to use currentOffset parameter instead of offset from editor. Do not modify text via editor.
+ * NOTE: editor is real (not a copy) and it doesn't represent the {@code copyFile}.
+ * It's safer to use {@code currentOffset} parameter instead of the editor offset.
+ * Do not modify text with the provided {@code realEditor}.
*/
@NotNull
PsiFile preCheck(@NotNull PsiFile copyFile, @NotNull Editor realEditor, int currentOffset);
/**
- * Return the editor that it able to represent template in UI
- * and create the template from the settings that users set in UI.
+ * Returns the editor that is used to represent a template in UI and create the template from the settings provided by users.
* <p>
- * If templateToEdit is null, it's considered like an editor for a new template.
+ * If {@code templateToEdit} is {@code null}, it's considered as an editor for a new template.
*/
@Nullable
default PostfixTemplateEditor createEditor(@Nullable PostfixTemplate templateToEdit) {
@@ -92,7 +99,7 @@ public interface PostfixTemplateProvider {
}
/**
- * Instantiates the template that was serialized by the provider to XML.
+ * Reads from a given DOM element, and instantiates a template that was stored by this provider.
*/
@Nullable
default PostfixTemplate readExternalTemplate(@NotNull @NonNls String id, @NotNull @NlsSafe String name, @NotNull Element template) {
@@ -100,7 +107,7 @@ public interface PostfixTemplateProvider {
}
/**
- * Serialized to XML the template that was created by the provider.
+ * Stores a given template that was created by this provider to a given parent DOM element.
*/
default void writeExternalTemplate(@NotNull PostfixTemplate template, @NotNull Element parentElement) {
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
index 73427895ea94..41464887f005 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.CodeInsightBundle;
@@ -38,7 +38,7 @@ public final class PostfixTemplatesUtils {
}
/**
- * Returns all templates registered in the provider, including the edited templates and builtin templates in their current state
+ * @return all templates registered in the given provider, including the edited templates and builtin templates in their current state.
*/
@NotNull
public static Set<PostfixTemplate> getAvailableTemplates(@NotNull PostfixTemplateProvider provider) {
@@ -52,6 +52,10 @@ public final class PostfixTemplatesUtils {
return result;
}
+ /**
+ * Surrounds a given expression with the provided surrounder.
+ * @return range to select/position the caret
+ */
@Nullable
public static TextRange surround(@NotNull Surrounder surrounder,
@NotNull Editor editor,
@@ -72,6 +76,9 @@ public final class PostfixTemplatesUtils {
CodeInsightBundle.message("error.hint.can.t.expand.postfix.template"), "");
}
+ /**
+ * Generates a unique in the scope of a given provider template ID.
+ */
@NotNull
public static String generateTemplateId(@NotNull String templateKey, @NotNull PostfixTemplateProvider provider) {
Set<String> usedIds = new HashSet<>();
@@ -84,6 +91,12 @@ public final class PostfixTemplatesUtils {
return UniqueNameGenerator.generateUniqueName(templateKey + "@userDefined", usedIds);
}
+ /**
+ * Stores a given editable template in the given parent DOM element.
+ * The given template must be an instance of {@link EditablePostfixTemplate}.
+ * If the given template is {@link EditablePostfixTemplateWithMultipleExpressions},
+ * then all data like usage of the topmost expression flag and expression conditions are stored.
+ */
public static void writeExternalTemplate(@NotNull PostfixTemplate template, @NotNull Element parentElement) {
if (template instanceof EditablePostfixTemplateWithMultipleExpressions) {
parentElement.setAttribute(TOPMOST_ATTR, String.valueOf(((EditablePostfixTemplateWithMultipleExpressions<?>)template).isUseTopmostExpression()));
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
index b7fe95b96a5c..8b65e7755b56 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.lang.surroundWith.Surrounder;
@@ -9,6 +9,11 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
+/**
+ * Base for surrounding postfix templates that utilize existing {@link Surrounder} implementations.
+ *
+ * @see <a href="https://plugins.jetbrains.com/docs/intellij/advanced-postfix-templates.html">Advanced Postfix Templates (IntelliJ Platform Docs)</a>
+ */
public abstract class SurroundPostfixTemplateBase extends PostfixTemplateWithExpressionSelector {
@NotNull protected final PostfixTemplatePsiInfo myPsiInfo;
@@ -21,7 +26,6 @@ public abstract class SurroundPostfixTemplateBase extends PostfixTemplateWithExp
myPsiInfo = psiInfo;
}
-
@Override
public final void expandForChooseExpression(@NotNull PsiElement expression, @NotNull final Editor editor) {
PsiElement replace = getReplacedExpression(expression);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplate.java
index 891063db21b0..5db14edf4830 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplate.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates.editable;
import com.intellij.codeInsight.CodeInsightBundle;
@@ -28,6 +28,14 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Objects;
+/**
+ * Base class for editable templates.
+ * Template data is backed by live template.
+ * It supports selecting the expression a template is applied to.
+ *
+ * @see EditablePostfixTemplateWithMultipleExpressions
+ * @see <a href="https://plugins.jetbrains.com/docs/intellij/advanced-postfix-templates.html">Advanced Postfix Templates (IntelliJ Platform Docs)</a>
+ */
public abstract class EditablePostfixTemplate extends PostfixTemplate {
@NotNull private final TemplateImpl myLiveTemplate;
@@ -123,11 +131,11 @@ public abstract class EditablePostfixTemplate extends PostfixTemplate {
}
/**
+ * Default implementation delegates to {@link #getElementToRemove(PsiElement)} and takes the text range of the resulting element.
+ * Override it if it's desired to remove only a part of {@code PsiElement}'s range.
+ *
* @param element element to which the template was applied
* @return a range to remove before inserting the template
- *
- * Default implementation delegates to getElementToRemove and takes the range of the resulting element.
- * You may override it if it's desired to remove only a part of PsiElement range
*/
@NotNull
protected TextRange getRangeToRemove(@NotNull PsiElement element) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplateWithMultipleExpressions.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplateWithMultipleExpressions.java
index 58b57c2c262e..7b4e4e24cb86 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplateWithMultipleExpressions.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/EditablePostfixTemplateWithMultipleExpressions.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates.editable;
import com.intellij.codeInsight.template.impl.TemplateImpl;
@@ -10,6 +10,14 @@ import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.Set;
+/**
+ * Base class for editable templates with applicable expressions conditions.
+ * Template data is backed by live template.
+ * It supports selecting the expression a template is applied to.
+ *
+ * @param <ConditionType> expression condition type
+ * @see <a href="https://plugins.jetbrains.com/docs/intellij/advanced-postfix-templates.html">Advanced Postfix Templates (IntelliJ Platform Docs)</a>
+ */
public abstract class EditablePostfixTemplateWithMultipleExpressions<ConditionType extends PostfixTemplateExpressionCondition>
extends EditablePostfixTemplate {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateEditor.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateEditor.java
index d0e59be154e9..fddfeb14aaf4 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateEditor.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateEditor.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates.editable;
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
@@ -9,13 +9,26 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
- * The editor that is able to show the UI settings for a particular template,
- * or to create a template from settings defined in UI form.
+ * Represents the postfix template editor used for creating and editing editable templates.
+ *
+ * @see com.intellij.codeInsight.template.postfix.settings.PostfixEditTemplateDialog
+ * @see <a href="https://plugins.jetbrains.com/docs/intellij/advanced-postfix-templates.html">Advanced Postfix Templates (IntelliJ Platform Docs)</a>
*/
public interface PostfixTemplateEditor extends Disposable {
+
+ /**
+ * Creates a template from settings defined in the UI form.
+ *
+ * @param templateId unique template ID
+ * @param templateName
+ * @return created template
+ */
@NotNull
PostfixTemplate createTemplate(@NotNull String templateId, @NotNull String templateName);
+ /**
+ * @return template settings form component
+ */
@NotNull
JComponent getComponent();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateExpressionCondition.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateExpressionCondition.java
index f8d4a4be1d27..f12a59990f42 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateExpressionCondition.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/editable/PostfixTemplateExpressionCondition.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates.editable;
import com.intellij.openapi.util.Condition;
@@ -8,6 +8,14 @@ import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+/**
+ * Editable postfix template expression condition used to determine contexts that a postfix template can be applied in.
+ *
+ * @param <T> the supported PSI element type
+ *
+ * @see EditablePostfixTemplateWithMultipleExpressions
+ * @see <a href="https://plugins.jetbrains.com/docs/intellij/advanced-postfix-templates.html">Advanced Postfix Templates (IntelliJ Platform Docs)</a>
+ */
public interface PostfixTemplateExpressionCondition<T extends PsiElement> extends Condition<T> {
@NonNls String ID_ATTR = "id";
@@ -19,7 +27,7 @@ public interface PostfixTemplateExpressionCondition<T extends PsiElement> extend
/**
- * @return id for serialization
+ * @return ID for serialization
*/
@NotNull @NonNls String getId();
@@ -31,6 +39,11 @@ public interface PostfixTemplateExpressionCondition<T extends PsiElement> extend
element.setAttribute(ID_ATTR, getId());
}
+ /**
+ * @param t PSI element to check
+ * @return {@code true} if an expression context determined by a given element is applicable for evaluated postfix template,
+ * {@code false} otherwise
+ */
@Override
boolean value(@NotNull T t);
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/CreateFileAction.java b/platform/lang-impl/src/com/intellij/ide/actions/CreateFileAction.java
index 9da3d43fa620..c07eb8ca5739 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/CreateFileAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/CreateFileAction.java
@@ -7,6 +7,7 @@ import com.intellij.ide.IdeBundle;
import com.intellij.ide.ui.newItemPopup.NewItemPopupUtil;
import com.intellij.ide.ui.newItemPopup.NewItemSimplePopupPanel;
import com.intellij.idea.ActionsBundle;
+import com.intellij.internal.statistic.collectors.fus.fileTypes.FileTypeUsageCounterCollector;
import com.intellij.lang.LangBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Experiments;
@@ -26,6 +27,7 @@ import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -111,7 +113,9 @@ public class CreateFileAction extends CreateElementActionBase implements DumbAwa
@Override
protected PsiElement @NotNull [] create(@NotNull String newName, @NotNull PsiDirectory directory) throws Exception {
MkDirs mkdirs = new MkDirs(newName, directory);
- return new PsiElement[]{WriteAction.compute(() -> mkdirs.directory.createFile(getFileName(mkdirs.newName)))};
+ PsiFile file = WriteAction.compute(() -> mkdirs.directory.createFile(getFileName(mkdirs.newName)));
+ FileTypeUsageCounterCollector.triggerCreate(file.getProject(), file.getVirtualFile());
+ return new PsiElement[]{file};
}
@NotNull
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java
index b8878cd81cbc..51e6618a34c9 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexProjectHandler.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.indexing;
import com.intellij.diagnostic.PerformanceWatcher;
@@ -15,7 +15,6 @@ import com.intellij.util.indexing.contentQueue.IndexUpdateRunner;
import com.intellij.util.indexing.diagnostic.IndexDiagnosticDumper;
import com.intellij.util.indexing.diagnostic.ProjectIndexingHistoryImpl;
import com.intellij.util.indexing.diagnostic.ScanningStatistics;
-import com.intellij.util.indexing.diagnostic.ScanningType;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -93,7 +92,7 @@ public final class FileBasedIndexProjectHandler {
@NotNull Project project,
long refreshedFilesCalcDuration) {
ProjectIndexingHistoryImpl projectIndexingHistory =
- new ProjectIndexingHistoryImpl(project, "On refresh of " + files.size() + " files", ScanningType.REFRESH);
+ new ProjectIndexingHistoryImpl(project, "On refresh of " + files.size() + " files", false);
IndexDiagnosticDumper.getInstance().onIndexingStarted(projectIndexingHistory);
((FileBasedIndexImpl)FileBasedIndex.getInstance()).fireUpdateStarted(project);
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ForceIndexRescanningAction.java b/platform/lang-impl/src/com/intellij/util/indexing/ForceIndexRescanningAction.java
index e464c4142cf5..a59c83922d21 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/ForceIndexRescanningAction.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/ForceIndexRescanningAction.java
@@ -1,10 +1,9 @@
-// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.indexing;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
-import com.intellij.util.indexing.diagnostic.ScanningType;
import org.jetbrains.annotations.NotNull;
final class ForceIndexRescanningAction extends DumbAwareAction {
@@ -16,8 +15,7 @@ final class ForceIndexRescanningAction extends DumbAwareAction {
false,
false,
null,
- "Force re-scanning",
- ScanningType.FULL_FORCED);
+ "Force re-scanning");
task.queue(project);
}
}
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/RescanIndexesAction.kt b/platform/lang-impl/src/com/intellij/util/indexing/RescanIndexesAction.kt
index 1f659a703777..d381ab9056d5 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/RescanIndexesAction.kt
+++ b/platform/lang-impl/src/com/intellij/util/indexing/RescanIndexesAction.kt
@@ -1,4 +1,4 @@
-// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.indexing
import com.intellij.ide.actions.cache.*
@@ -7,13 +7,13 @@ import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.util.ProgressIndicatorUtils
import com.intellij.openapi.project.DumbModeTask
+import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileWithId
import com.intellij.psi.stubs.StubTreeBuilder
import com.intellij.psi.stubs.StubUpdatingIndex
import com.intellij.util.BooleanFunction
import com.intellij.util.indexing.diagnostic.ProjectIndexingHistoryImpl
-import com.intellij.util.indexing.diagnostic.ScanningType
import com.intellij.util.indexing.roots.IndexableFilesIterator
import com.intellij.util.indexing.roots.ProjectIndexableFilesIteratorImpl
import org.jetbrains.annotations.ApiStatus
@@ -39,9 +39,7 @@ class RescanIndexesAction : RecoveryAction {
if (recoveryScope is FilesRecoveryScope) {
predefinedIndexableFilesIterators = recoveryScope.files.map { ProjectIndexableFilesIteratorImpl(it) }
}
- object : UnindexedFilesUpdater(project, false, false,
- predefinedIndexableFilesIterators, "Rescanning indexes recovery action",
- if(predefinedIndexableFilesIterators == null) ScanningType.FULL_FORCED else ScanningType.PARTIAL_FORCED) {
+ object : UnindexedFilesUpdater(project, predefinedIndexableFilesIterators, "Rescanning indexes recovery action") {
private val stubIndex =
runCatching { (FileBasedIndex.getInstance() as FileBasedIndexImpl).getIndex(StubUpdatingIndex.INDEX_ID) }
.onFailure { logger<RescanIndexesAction>().error(it) }.getOrNull()
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java b/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java
index 53798fa938ca..87597de332ba 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/UnindexedFilesUpdater.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.util.indexing;
import com.intellij.diagnostic.PerformanceWatcher;
@@ -36,7 +36,6 @@ import com.intellij.util.indexing.contentQueue.IndexUpdateRunner;
import com.intellij.util.indexing.diagnostic.IndexDiagnosticDumper;
import com.intellij.util.indexing.diagnostic.ProjectIndexingHistoryImpl;
import com.intellij.util.indexing.diagnostic.ScanningStatistics;
-import com.intellij.util.indexing.diagnostic.ScanningType;
import com.intellij.util.indexing.diagnostic.dto.JsonScanningStatistics;
import com.intellij.util.indexing.roots.IndexableFileScanner;
import com.intellij.util.indexing.roots.IndexableFilesDeduplicateFilter;
@@ -86,7 +85,6 @@ public class UnindexedFilesUpdater extends DumbModeTask {
private final boolean myStartSuspended;
private final boolean myOnProjectOpen;
private final @NonNls String myIndexingReason;
- private final @NotNull ScanningType myScanningType;
private final PushedFilePropertiesUpdater myPusher;
private final @Nullable List<IndexableFilesIterator> myPredefinedIndexableFilesIterators;
@@ -94,13 +92,11 @@ public class UnindexedFilesUpdater extends DumbModeTask {
boolean startSuspended,
boolean onProjectOpen,
@Nullable List<IndexableFilesIterator> predefinedIndexableFilesIterators,
- @Nullable @NonNls String indexingReason,
- @NotNull ScanningType scanningType) {
+ @Nullable @NonNls String indexingReason) {
myProject = project;
myStartSuspended = startSuspended;
myOnProjectOpen = onProjectOpen;
myIndexingReason = indexingReason;
- myScanningType = scanningType;
myPusher = PushedFilePropertiesUpdater.getInstance(myProject);
myPredefinedIndexableFilesIterators = predefinedIndexableFilesIterators;
@@ -160,8 +156,7 @@ public class UnindexedFilesUpdater extends DumbModeTask {
myStartSuspended,
false,
mergeIterators(myPredefinedIndexableFilesIterators, ((UnindexedFilesUpdater)taskFromQueue).myPredefinedIndexableFilesIterators),
- reason,
- ScanningType.Companion.merge(oldTask.myScanningType, oldTask.myScanningType)
+ reason
);
}
@@ -182,18 +177,17 @@ public class UnindexedFilesUpdater extends DumbModeTask {
// If we haven't succeeded to fully scan the project content yet, then we must keep trying to run
// file based index extensions for all project files until at least one of UnindexedFilesUpdater-s finishes without cancellation.
// This is important, for example, for shared indexes: all files must be associated with their locally available shared index chunks.
- this(project, false, false, null, null, ScanningType.FULL);
+ this(project, false, false, null, null);
}
public UnindexedFilesUpdater(@NotNull Project project, @Nullable @NonNls String indexingReason) {
- this(project, false, false, null, indexingReason, ScanningType.FULL);
+ this(project, false, false, null, indexingReason);
}
public UnindexedFilesUpdater(@NotNull Project project,
@Nullable List<IndexableFilesIterator> predefinedIndexableFilesIterators,
@Nullable @NonNls String indexingReason) {
- this(project, false, false, predefinedIndexableFilesIterators, indexingReason,
- predefinedIndexableFilesIterators == null ? ScanningType.FULL : ScanningType.PARTIAL);
+ this(project, false, false, predefinedIndexableFilesIterators, indexingReason);
}
private void updateUnindexedFiles(@NotNull ProjectIndexingHistoryImpl projectIndexingHistory, @NotNull ProgressIndicator indicator) {
@@ -579,8 +573,7 @@ public class UnindexedFilesUpdater extends DumbModeTask {
}
protected @NotNull ProjectIndexingHistoryImpl performScanningAndIndexing(@NotNull ProgressIndicator indicator) {
- ProjectIndexingHistoryImpl projectIndexingHistory =
- new ProjectIndexingHistoryImpl(myProject, myIndexingReason, myScanningType);
+ ProjectIndexingHistoryImpl projectIndexingHistory = new ProjectIndexingHistoryImpl(myProject, myIndexingReason, isFullIndexUpdate());
myIndex.loadIndexes();
myIndex.filesUpdateStarted(myProject, isFullIndexUpdate());
IndexDiagnosticDumper.getInstance().onIndexingStarted(projectIndexingHistory);
@@ -650,21 +643,17 @@ public class UnindexedFilesUpdater extends DumbModeTask {
return SystemProperties.getBooleanProperty("ij.indexes.skip.initial.refresh", false);
}
- public static void scanAndIndexProjectAfterOpen(@NotNull Project project,
- boolean startSuspended,
- @Nullable @NonNls String indexingReason) {
+ public static void scanAndIndexProjectAfterOpen(@NotNull Project project, boolean startSuspended, @Nullable @NonNls String indexingReason) {
if (TestModeFlags.is(INDEX_PROJECT_WITH_MANY_UPDATERS_TEST_KEY)) {
LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode());
List<IndexableFilesIterator> iterators = collectProviders(project, (FileBasedIndexImpl)FileBasedIndex.getInstance());
for (IndexableFilesIterator iterator : iterators) {
- new UnindexedFilesUpdater(project, startSuspended, true, Collections.singletonList(iterator), indexingReason,
- ScanningType.FULL_ON_PROJECT_OPEN).queue(project);
+ new UnindexedFilesUpdater(project, startSuspended, true, Collections.singletonList(iterator), indexingReason).queue(project);
}
project.putUserData(CONTENT_SCANNED, true);
}
else {
- new UnindexedFilesUpdater(project, startSuspended, true, null, indexingReason, ScanningType.FULL_ON_PROJECT_OPEN).
- queue(project);
+ new UnindexedFilesUpdater(project, startSuspended, true, null, indexingReason).queue(project);
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistory.kt b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistory.kt
index 495348b196db..f7fa953ce974 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistory.kt
+++ b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistory.kt
@@ -33,56 +33,6 @@ interface ProjectIndexingHistory {
val visibleTimeToAllThreadsTimeRatio: Double
}
-/**
- * isFull - if the whole project was rescanned (instead of a part of it)
- */
-enum class ScanningType(val isFull: Boolean) {
- /**
- * Full project rescan forced by user via Repair IDE action
- */
- FULL_FORCED(true),
-
- /**
- * It's mandatory full project rescan on project open
- */
- FULL_ON_PROJECT_OPEN(true),
-
- /**
- * Full project rescan requested by some code
- */
- FULL(true),
-
-
- /**
- * Partial rescan forced by user via Repair IDE action on a limited scope (not full project)
- */
- PARTIAL_FORCED(false),
-
- /**
- * Partial project rescan requested by some code
- */
- PARTIAL(false),
-
- /**
- * Some files were considered changed and therefore rescanned
- */
- REFRESH(false);
-
- companion object {
- fun merge(first: ScanningType, second: ScanningType): ScanningType = returnFirstFound(first, second,
- FULL_FORCED, FULL_ON_PROJECT_OPEN, FULL,
- PARTIAL_FORCED, PARTIAL,
- REFRESH)
-
- private fun returnFirstFound(first: ScanningType, second: ScanningType, vararg types: ScanningType): ScanningType {
- for (type in types) {
- if (first == type || second == type) return type
- }
- throw IllegalStateException("Unexpected ScanningType $first $second")
- }
- }
-}
-
interface StatsPerFileType {
val totalNumberOfFiles: Int
val totalBytes: BytesNumber
@@ -108,7 +58,7 @@ interface StatsPerIndexer {
interface IndexingTimes {
val indexingReason: String?
- val scanningType: ScanningType
+ val wasFullIndexing: Boolean
val updatingStart: ZonedDateTime
val totalUpdatingTime: TimeNano
val updatingEnd: ZonedDateTime
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryFusReporterListener.kt b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryFusReporterListener.kt
index b845875b42a6..b3643550c5ce 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryFusReporterListener.kt
+++ b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryFusReporterListener.kt
@@ -11,9 +11,7 @@ import com.intellij.openapi.fileTypes.FileType
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.project.Project
import com.intellij.util.indexing.diagnostic.dto.toMillis
-import java.util.*
import java.util.concurrent.TimeUnit
-import kotlin.collections.HashMap
import kotlin.math.roundToLong
class ProjectIndexingHistoryFusReporterListener : ProjectIndexingHistoryListener {
@@ -50,7 +48,7 @@ class ProjectIndexingHistoryFusReporterListener : ProjectIndexingHistoryListener
ProjectIndexingHistoryFusReporter.reportIndexingFinished(
projectIndexingHistory.project,
projectIndexingHistory.indexingSessionId,
- projectIndexingHistory.times.scanningType,
+ projectIndexingHistory.times.wasFullIndexing,
projectIndexingHistory.times.totalUpdatingTime.toMillis(),
projectIndexingHistory.times.indexingDuration.toMillis(),
scanningTime,
@@ -80,14 +78,13 @@ class ProjectIndexingHistoryFusReporterListener : ProjectIndexingHistoryListener
}
object ProjectIndexingHistoryFusReporter : CounterUsagesCollector() {
- private val GROUP = EventLogGroup("indexing.statistics", 6)
+ private val GROUP = EventLogGroup("indexing.statistics", 5)
override fun getGroup() = GROUP
private val indexingSessionId = EventFields.Long("indexing_session_id")
private val isFullIndexing = EventFields.Boolean("is_full")
- private val scanningType = EventFields.Enum<ScanningType>("type") { type -> type.name.lowercase(Locale.ENGLISH) }
private val totalTime = EventFields.Long("total_time")
private val indexingTime = EventFields.Long("indexing_time")
private val scanningTime = EventFields.Long("scanning_time")
@@ -115,7 +112,6 @@ object ProjectIndexingHistoryFusReporter : CounterUsagesCollector() {
"finished",
indexingSessionId,
isFullIndexing,
- scanningType,
totalTime,
indexingTime,
scanningTime,
@@ -138,7 +134,7 @@ object ProjectIndexingHistoryFusReporter : CounterUsagesCollector() {
fun reportIndexingFinished(
project: Project,
indexingSessionId: Long,
- scanningType: ScanningType,
+ wasFullIndexing: Boolean,
totalTime: Long,
indexingTime: Long,
scanningTime: Long,
@@ -154,8 +150,7 @@ object ProjectIndexingHistoryFusReporter : CounterUsagesCollector() {
indexingFinished.log(
project,
this.indexingSessionId.with(indexingSessionId),
- this.isFullIndexing.with(scanningType.isFull),
- this.scanningType.with(scanningType),
+ this.isFullIndexing.with(wasFullIndexing),
this.totalTime.with(totalTime),
this.indexingTime.with(indexingTime),
this.scanningTime.with(scanningTime),
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryImpl.kt b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryImpl.kt
index fa47fb1b29ec..198a2c2a3ce4 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryImpl.kt
+++ b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryImpl.kt
@@ -19,7 +19,7 @@ import kotlin.reflect.KMutableProperty1
@ApiStatus.Internal
data class ProjectIndexingHistoryImpl(override val project: Project,
override val indexingReason: String?,
- private val scanningType: ScanningType) : ProjectIndexingHistory {
+ private val wasFullIndexing: Boolean) : ProjectIndexingHistory {
private companion object {
val indexingSessionIdSequencer = AtomicLong()
val log = thisLogger()
@@ -31,7 +31,7 @@ data class ProjectIndexingHistoryImpl(override val project: Project,
override val times: IndexingTimes by ::timesImpl
- private val timesImpl = IndexingTimesImpl(indexingReason = indexingReason, scanningType = scanningType,
+ private val timesImpl = IndexingTimesImpl(indexingReason = indexingReason, wasFullIndexing = wasFullIndexing,
updatingStart = ZonedDateTime.now(ZoneOffset.UTC), totalUpdatingTime = System.nanoTime())
override val scanningStatistics = arrayListOf<JsonScanningStatistics>()
@@ -324,7 +324,7 @@ data class ProjectIndexingHistoryImpl(override val project: Project,
data class IndexingTimesImpl(
override val indexingReason: String?,
- override val scanningType: ScanningType,
+ override val wasFullIndexing: Boolean,
override val updatingStart: ZonedDateTime,
override var totalUpdatingTime: TimeNano,
override var updatingEnd: ZonedDateTime = updatingStart,
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/dto/JsonConverter.kt b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/dto/JsonConverter.kt
index f3d2684389ff..4b8fa5a6874f 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/dto/JsonConverter.kt
+++ b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/dto/JsonConverter.kt
@@ -85,7 +85,7 @@ fun IndexingFileSetStatistics.IndexedFile.toJson() = JsonFileProviderIndexStatis
fun IndexingTimes.toJson() =
JsonProjectIndexingHistoryTimes(
indexingReason = indexingReason,
- scanningType = scanningType,
+ wasFullIndexing = wasFullIndexing,
totalUpdatingTime = JsonDuration(totalUpdatingTime),
indexingTime = JsonDuration(indexingDuration.toNanos()),
contentLoadingVisibleTime = JsonDuration(contentLoadingVisibleDuration.toNanos()),
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/dto/JsonProjectIndexingHistoryTimes.kt b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/dto/JsonProjectIndexingHistoryTimes.kt
index d90b8ff2fc27..b9e498f53150 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/dto/JsonProjectIndexingHistoryTimes.kt
+++ b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/dto/JsonProjectIndexingHistoryTimes.kt
@@ -3,13 +3,12 @@ package com.intellij.util.indexing.diagnostic.dto
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.fasterxml.jackson.annotation.JsonInclude
-import com.intellij.util.indexing.diagnostic.ScanningType
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
data class JsonProjectIndexingHistoryTimes(
val indexingReason: String? = null,
- val scanningType: ScanningType = ScanningType.FULL,
+ val wasFullIndexing: Boolean = false,
val totalUpdatingTime: JsonDuration = JsonDuration(),
val indexingTime: JsonDuration = JsonDuration(),
val contentLoadingVisibleTime: JsonDuration = JsonDuration(),
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/presentation/jsonToHtmlConverter.kt b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/presentation/jsonToHtmlConverter.kt
index ceaec19987d4..9a23f69063e2 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/presentation/jsonToHtmlConverter.kt
+++ b/platform/lang-impl/src/com/intellij/util/indexing/diagnostic/presentation/jsonToHtmlConverter.kt
@@ -14,7 +14,6 @@ import com.intellij.util.indexing.diagnostic.JsonSharedIndexDiagnosticEvent
import com.intellij.util.indexing.diagnostic.dto.*
import org.intellij.lang.annotations.Language
import org.jetbrains.annotations.Nls
-import java.util.*
fun createAggregateHtml(
projectName: String,
@@ -96,7 +95,7 @@ fun createAggregateHtml(
td(diagnostic.appInfo.productCode + "-" + diagnostic.appInfo.build)
//Indexing type section
- td(diagnostic.indexingTimes.scanningType.name.lowercase(Locale.ENGLISH).replace('_', ' '))
+ td(if (diagnostic.indexingTimes.wasFullIndexing) "Full" else "Partial")
}
}
}
@@ -379,7 +378,7 @@ fun JsonIndexDiagnostic.generateHtml(): String {
if (times.indexingReason != null) {
tr { td("Reason"); td(times.indexingReason) }
}
- tr { td("Type"); td(times.scanningType.name.lowercase(Locale.ENGLISH).replace('_', ' ')) }
+ tr { td("Full or partial"); td(if (times.wasFullIndexing) "full" else "partial") }
tr { td("Finished at"); td(times.updatingEnd.presentableLocalDateTime()) }
tr { td("Cancelled?"); td(times.wasInterrupted.toString()) }
tr { td("Suspended time"); td(times.totalSuspendedTime.presentableDuration()) }
diff --git a/platform/lang-impl/testSources/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryImplTest.kt b/platform/lang-impl/testSources/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryImplTest.kt
index 0e9e7a373ee0..12327dea2ad7 100644
--- a/platform/lang-impl/testSources/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryImplTest.kt
+++ b/platform/lang-impl/testSources/com/intellij/util/indexing/diagnostic/ProjectIndexingHistoryImplTest.kt
@@ -1,4 +1,4 @@
-// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.indexing.diagnostic
import com.intellij.openapi.command.impl.DummyProject
@@ -12,7 +12,7 @@ class ProjectIndexingHistoryImplTest {
@Test
fun `test observation missed the start of suspension (IDEA-281514)`() {
- val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", ScanningType.FULL)
+ val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", true)
val time = Instant.now()
history.stopSuspendingStages(time)
history.startStage(ProjectIndexingHistoryImpl.Stage.Indexing, time.plusNanos(1))
@@ -27,7 +27,7 @@ class ProjectIndexingHistoryImplTest {
@Test
fun `test there may be actions after suspension`() {
- val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", ScanningType.FULL)
+ val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", true)
val time = Instant.now()
history.startStage(ProjectIndexingHistoryImpl.Stage.Indexing, time)
history.suspendStages(time.plusNanos(1))
@@ -42,7 +42,7 @@ class ProjectIndexingHistoryImplTest {
@Test
fun `test there may be actions after suspension 2`() {
- val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", ScanningType.FULL)
+ val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", true)
val time = Instant.now()
history.startStage(ProjectIndexingHistoryImpl.Stage.Indexing, time)
history.suspendStages(time.plusNanos(1))
@@ -58,7 +58,7 @@ class ProjectIndexingHistoryImplTest {
@Test
fun `test there may be actions after suspension 3`() {
- val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", ScanningType.FULL)
+ val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", true)
val time = Instant.now()
history.suspendStages(time)
history.startStage(ProjectIndexingHistoryImpl.Stage.Indexing, time.plusNanos(1))
@@ -74,7 +74,7 @@ class ProjectIndexingHistoryImplTest {
@Test
fun `test there may be actions after suspension 4`() {
- val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", ScanningType.FULL)
+ val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", true)
val time = Instant.now()
history.startStage(ProjectIndexingHistoryImpl.Stage.Indexing, time)
history.stopSuspendingStages(time.plusNanos(1))
@@ -89,7 +89,7 @@ class ProjectIndexingHistoryImplTest {
@Test
fun `test there may be actions after suspension 5`() {
- val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", ScanningType.FULL)
+ val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", true)
val time = Instant.now()
history.startStage(ProjectIndexingHistoryImpl.Stage.Indexing, time.plusNanos(1))
history.stopSuspendingStages(time.plusNanos(2))
@@ -106,7 +106,7 @@ class ProjectIndexingHistoryImplTest {
@Test
fun `test basic workflow`() {
- val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", ScanningType.FULL)
+ val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", true)
val instant = Instant.now()
history.startStage(ProjectIndexingHistoryImpl.Stage.PushProperties, instant)
history.stopStage(ProjectIndexingHistoryImpl.Stage.PushProperties, instant.plusNanos(1))
@@ -122,7 +122,7 @@ class ProjectIndexingHistoryImplTest {
@Test
fun `test stage with suspension inside`() {
- val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", ScanningType.FULL)
+ val history = ProjectIndexingHistoryImpl(DummyProject.getInstance(), "test", true)
val instant = Instant.now()
history.startStage(ProjectIndexingHistoryImpl.Stage.PushProperties, instant)
history.suspendStages(instant.plusNanos(1))
diff --git a/platform/platform-api/src/com/intellij/ui/mac/screenmenu/Menu.java b/platform/platform-api/src/com/intellij/ui/mac/screenmenu/Menu.java
index aef61e0ff058..38e69956aa57 100644
--- a/platform/platform-api/src/com/intellij/ui/mac/screenmenu/Menu.java
+++ b/platform/platform-api/src/com/intellij/ui/mac/screenmenu/Menu.java
@@ -1,6 +1,7 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ui.mac.screenmenu;
+import com.intellij.DynamicBundle;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
@@ -17,6 +18,7 @@ import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
@SuppressWarnings("NonPrivateFieldAccessedInSynchronizedContext")
public class Menu extends MenuItem {
@@ -50,6 +52,23 @@ public class Menu extends MenuItem {
return ourAppMenu;
}
+ public static void renameAppMenuItems(@Nullable DynamicBundle replacements) {
+ if (replacements == null) return;
+
+ Set<String> keySet = replacements.getResourceBundle().keySet();
+ if (keySet.isEmpty()) return;
+
+ String replace[] = new String[keySet.size()*2];
+ int c = 0;
+ for (String title: keySet) {
+ replace[c] = title;
+ replace[c + 1] = replacements.getMessage(title);
+ c += 2;
+ }
+
+ nativeRenameAppMenuItems(replace);
+ }
+
public void setOnOpen(Runnable fillMenuProcedure, Component component) {
this.myOnOpen = fillMenuProcedure;
this.myComponent = component;
@@ -264,6 +283,9 @@ public class Menu extends MenuItem {
static
private native long nativeGetAppMenu();
+ static
+ private native void nativeRenameAppMenuItems(String[] replacements);
+
//
// Static API
//
@@ -274,7 +296,7 @@ public class Menu extends MenuItem {
IS_ENABLED = false;
- if (!SystemInfo.isMac) return false;
+ if (!SystemInfo.isMacOSMojave) return false;
if (!Boolean.getBoolean("jbScreenMenuBar.enabled")) return false;
if (Boolean.getBoolean("apple.laf.useScreenMenuBar")) {
Logger.getInstance(Menu.class).info("apple.laf.useScreenMenuBar==true, default screen menu implementation will be used");
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeUsageCounterCollector.java b/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeUsageCounterCollector.java
index 62e9978d56e0..610189ae1226 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeUsageCounterCollector.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/collectors/fus/fileTypes/FileTypeUsageCounterCollector.java
@@ -67,6 +67,7 @@ public final class FileTypeUsageCounterCollector extends CounterUsagesCollector
}
private static final VarargEventId SELECT = registerFileTypeEvent("select");
+ private static final VarargEventId CREATE_BY_NEW_FILE = registerFileTypeEvent("create_by_new_file");
private static final VarargEventId EDIT = registerFileTypeEvent("edit", FILE_EXTENSION_FIELD);
private static final VarargEventId OPEN = registerFileTypeEvent(
"open", FILE_EDITOR, EventFields.TimeToShowMs, EventFields.DurationMs, IS_WRITABLE, IS_IN_READER_MODE, FILE_EXTENSION_FIELD
@@ -86,6 +87,10 @@ public final class FileTypeUsageCounterCollector extends CounterUsagesCollector
}
}
+ public static void triggerCreate(@NotNull Project project, @NotNull VirtualFile file) {
+ log(CREATE_BY_NEW_FILE, project, file, false);
+ }
+
public static void triggerOpen(@NotNull Project project, @NotNull FileEditorManager source,
@NotNull VirtualFile file, @Nullable Long openStartedNs) {
long timeToShow = openStartedNs != null ? TimeoutUtil.getDurationMillis(openStartedNs) : -1;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java
index 859b4f9c954b..2548f034ce24 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java
@@ -378,18 +378,8 @@ public class IdeMenuBar extends JMenuBar implements IdeEventQueue.EventDispatche
private void updateAppMenu() {
if (!Menu.isJbScreenMenuEnabled()) return;
- final Menu appMenu = Menu.getAppMenu();
-
// 1. rename with localized
- final DynamicBundle bundle = new DynamicBundle("messages.MacAppMenuBundle");
- for (String title: bundle.getResourceBundle().keySet()) {
- String localizedTitle = bundle.getMessage(title);
- MenuItem item = appMenu.findItemByTitle(title);
- if (item != null) {
- item.setLabel(localizedTitle);
- item.dispose(); // must always dispose java-wrapper for native NSMenuItem after usage
- }
- }
+ Menu.renameAppMenuItems(new DynamicBundle("messages.MacAppMenuBundle"));
//
// 2. add custom new items in AppMenu
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/project/DumbServiceImplTest.groovy b/platform/platform-tests/testSrc/com/intellij/openapi/project/DumbServiceImplTest.groovy
index 29304c37706f..f7a672bd966f 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/project/DumbServiceImplTest.groovy
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/project/DumbServiceImplTest.groovy
@@ -1,4 +1,4 @@
-// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.project
import com.intellij.openapi.application.ApplicationManager
@@ -21,7 +21,6 @@ import com.intellij.util.indexing.FileBasedIndex
import com.intellij.util.indexing.FileBasedIndexImpl
import com.intellij.util.indexing.contentQueue.IndexUpdateRunner
import com.intellij.util.indexing.diagnostic.ProjectIndexingHistoryImpl
-import com.intellij.util.indexing.diagnostic.ScanningType
import com.intellij.util.ui.UIUtil
import org.jetbrains.annotations.NotNull
import org.junit.Assert
@@ -172,7 +171,7 @@ class DumbServiceImplTest extends BasePlatformTestCase {
def index = FileBasedIndex.getInstance() as FileBasedIndexImpl
new IndexUpdateRunner(index, ConcurrencyUtil.newSameThreadExecutorService(), 1)
.indexFiles(project, Collections.singletonList(new IndexUpdateRunner.FileSet(project, "child", [child])),
- indicator, new ProjectIndexingHistoryImpl(getProject(), "Testing", ScanningType.PARTIAL))
+ indicator, new ProjectIndexingHistoryImpl(getProject(), "Testing", false))
}
}
catch (ProcessCanceledException e) {
diff --git a/platform/platform-tests/testSrc/com/intellij/util/io/PersistencePerformanceTest.java b/platform/platform-tests/testSrc/com/intellij/util/io/PersistencePerformanceTest.java
index 7af410828c16..f78a77c29cdf 100644
--- a/platform/platform-tests/testSrc/com/intellij/util/io/PersistencePerformanceTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/util/io/PersistencePerformanceTest.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util.io;
import com.intellij.openapi.application.ApplicationManager;
@@ -15,7 +15,6 @@ import com.intellij.util.indexing.FileBasedIndexImpl;
import com.intellij.util.indexing.UnindexedFilesUpdater;
import com.intellij.util.indexing.contentQueue.IndexUpdateRunner;
import com.intellij.util.indexing.diagnostic.ProjectIndexingHistoryImpl;
-import com.intellij.util.indexing.diagnostic.ScanningType;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
@@ -109,7 +108,7 @@ public class PersistencePerformanceTest extends BasePlatformTestCase {
Thread.sleep(100);
new IndexUpdateRunner(index, UnindexedFilesUpdater.GLOBAL_INDEXING_EXECUTOR, UnindexedFilesUpdater.getNumberOfIndexingThreads())
.indexFiles(getProject(), Collections.singletonList(new IndexUpdateRunner.FileSet(getProject(), "test files", files)),
- new EmptyProgressIndicator(), new ProjectIndexingHistoryImpl(getProject(), "Testing", ScanningType.PARTIAL));
+ new EmptyProgressIndicator(), new ProjectIndexingHistoryImpl(getProject(), "Testing", false));
}
for (Future<Boolean> future : futures) {
assertTrue(future.get());
diff --git a/platform/remoteDev-util/src/com/intellij/remoteDev/downloader/JetBrainsClientDownloaderConfigurationProvider.kt b/platform/remoteDev-util/src/com/intellij/remoteDev/downloader/JetBrainsClientDownloaderConfigurationProvider.kt
index c58c22ab19b9..70913f632f8e 100644
--- a/platform/remoteDev-util/src/com/intellij/remoteDev/downloader/JetBrainsClientDownloaderConfigurationProvider.kt
+++ b/platform/remoteDev-util/src/com/intellij/remoteDev/downloader/JetBrainsClientDownloaderConfigurationProvider.kt
@@ -42,8 +42,8 @@ interface JetBrainsClientDownloaderConfigurationProvider {
class RealJetBrainsClientDownloaderConfigurationProvider : JetBrainsClientDownloaderConfigurationProvider {
override fun modifyClientCommandLine(clientCommandLine: GeneralCommandLine) { }
- override val clientDownloadLocation: URI = URI("https://cache-redirector.jetbrains.com/download.jetbrains.com/idea/code-with-me/")
- override val jreDownloadLocation: URI = URI("https://cache-redirector.jetbrains.com/download.jetbrains.com/idea/jbr/")
+ override val clientDownloadLocation: URI = URI("https://download.jetbrains.com/idea/code-with-me/")
+ override val jreDownloadLocation: URI = URI("https://download.jetbrains.com/idea/jbr/")
override val clientCachesDir: Path = getJetBrainsSystemCachesDir() / "JetBrainsClientDist"
override val verifySignature: Boolean = true
@@ -70,8 +70,8 @@ class TestJetBrainsClientDownloaderConfigurationProvider : JetBrainsClientDownlo
}
}
- override var clientDownloadLocation: URI = URI("https://cache-redirector.jetbrains.com/download.jetbrains.com/idea/code-with-me/")
- override var jreDownloadLocation: URI = URI("https://cache-redirector.jetbrains.com/download.jetbrains.com/idea/jbr/")
+ override var clientDownloadLocation: URI = URI("https://download.jetbrains.com/idea/code-with-me/")
+ override var jreDownloadLocation: URI = URI("https://download.jetbrains.com/idea/jbr/")
override var clientCachesDir: Path = Files.createTempDirectory("")
override var verifySignature: Boolean = true
@@ -179,4 +179,4 @@ class TestJetBrainsClientDownloaderConfigurationProvider : JetBrainsClientDownlo
serveFile(clientDistribution)
serveFile(clientJdkBuildTxt)
}
-} \ No newline at end of file
+}
diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java
index 4896b1692e93..3df8216b10db 100644
--- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java
+++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java
@@ -300,6 +300,15 @@ public class StructuralSearchTest extends StructuralSearchTestCase {
assertEquals("match literal by value", 1, findMatchesCount(s3, "32"));
assertEquals("match char with substitution", 3, findMatchesCount(s3, "\\''_x\\'"));
assertEquals("string literal should not match char", 0, findMatchesCount(s3, "\"a\""));
+
+ String s4 = "class X {" +
+ " String s = \"\\n\";" +
+ " String t = \" \";" +
+ " String u = \" \";" +
+ " String v = \"\";" +
+ "}";
+ assertEquals("match empty string", 1, findMatchesCount(s4, "\"\""));
+ assertEquals("match space", 2, findMatchesCount(s4, "\" \""));
}
public void testCovariantArraySearch() {
diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
index 8c4fee2092d8..11f0ccfc224b 100644
--- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.testFramework;
import com.intellij.analytics.AndroidStudioAnalytics;
@@ -76,32 +76,31 @@ import static org.junit.Assume.assumeTrue;
/**
* This class is compatible with both JUnit 3 and JUnit 4. To use JUnit 4, just annotate your test subclass
- * with @RunWith(JUnit4.class) or any other (like Parametrized.class), and you are all set.
- *
- * Don't annotate the JUnit 3 setUp()/tearDown() methods as @Before/@After, and don't call them from other @Before/@After methods.
- * Also don't define @Rule's calling runBare(), just subclassing this class (directly or indirectly) is enough. <p/>
- *
+ * with {@code @RunWith(JUnit4.class)} or any other (like {@code Parametrized.class}), and you are all set.
+ * <p>
+ * Don't annotate the JUnit 3 {@linkplain #setUp()}/{@linkplain #tearDown()} methods as {@code @Before}/{@code @After}, and don't call them from other {@code @Before}/{@code @After} methods.
+ * <p>
+ * Don't define {@code @Rule}s calling {@linkplain #runBare()}, just subclassing this class (directly or indirectly) is enough.
+ * <p>
* The execution order is the following:
- * <pre{@code
- *
- * - (JUnit 4 only) #checkShouldRunTest(Description) that can be used to ignore tests with meaningful message
- * - #shouldRunTest() is also called (both JUnit 3 and JUnit 4)
- *
- * - #setUp(), usually overridden so that it initializes classes in order from base to specific
- *
- * - (JUnit 4 only) any @Rule fields, then @Rule methods
- * - (JUnit 4 only) any @Before methods
- *
- * - the testXxx() method (JUnit 3), or the @Test method (JUnit 4)
- *
- * - (JUnit 4 only) any @After methods
- * - (JUnit 4 only) any @Rule methods, then @Rule fields, cleanup
- *
- * - #tearDown(), usually overridden in the reverse order: from specific to base
- * } </pre>
- *
- * Note that @Rule, @Before and @After methods execute within the same context/thread as the @Test method,
- * which may differ from how setUp()/tearDown() are executed.
+ * <ul>
+ * <li><em>(JUnit 4 only)</em> {@linkplain #checkShouldRunTest(Description)} that can be used to ignore tests with meaningful message
+ * <li>{@linkplain #shouldRunTest()} is also called (both JUnit 3 and JUnit 4)
+ * <li>{@linkplain #setUp()}, usually overridden so that it initializes classes in order from base to specific
+ * <ul>
+ * <li><em>(JUnit 4 only)</em> any {@code @Rule} fields, then {@code @Rule} methods
+ * <li><em>(JUnit 4 only)</em> any {@code @Before} methods
+ * <ul>
+ * <li>the testXxx() method (JUnit 3), or the {@code @Test} method (JUnit 4)
+ * </ul>
+ * <li><em>(JUnit 4 only)</em> any {@code @After} methods
+ * <li><em>(JUnit 4 only)</em> any {@code @Rule} methods, then {@code @Rule} fields, cleanup
+ * </ul>
+ * <li>{@linkplain #tearDown()}, usually overridden in the reverse order: from specific to base
+ * </ul>
+ * <p>
+ * Note that {@code @Rule}, {@code @Before} and {@code @After} methods execute within the same context/thread as the @Test method,
+ * which may differ from how {@linkplain #setUp()}/{@linkplain #tearDown()} are executed.
*/
public abstract class UsefulTestCase extends TestCase {
public static final boolean IS_UNDER_TEAMCITY = System.getenv("TEAMCITY_VERSION") != null;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.kt
index 56339620c747..b1a91a03739a 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.kt
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.kt
@@ -136,27 +136,28 @@ internal class ModuleVcsDetector(private val project: Project) {
when (change) {
is EntityChange.Removed<ContentRootEntity> -> {
removedUrls.add(change.entity.url)
- addedUrls.remove(change.entity.url)
}
is EntityChange.Added<ContentRootEntity> -> {
addedUrls.add(change.entity.url)
- removedUrls.remove(change.entity.url)
}
is EntityChange.Replaced<ContentRootEntity> -> {
if (change.oldEntity.url != change.newEntity.url) {
removedUrls.add(change.oldEntity.url)
- addedUrls.remove(change.oldEntity.url)
-
addedUrls.add(change.newEntity.url)
- removedUrls.remove(change.newEntity.url)
}
}
}
}
val fileManager = VirtualFileManager.getInstance()
- val removed = removedUrls.mapNotNull { fileManager.findFileByUrl(it.url) }.filter { it.isDirectory }
- val added = addedUrls.mapNotNull { fileManager.findFileByUrl(it.url) }.filter { it.isDirectory }
+ val removed = removedUrls
+ .filter { !addedUrls.contains(it) } // do not process 'modifications' of any kind
+ .mapNotNull { fileManager.findFileByUrl(it.url) }
+ .filter { it.isDirectory }
+ val added = addedUrls
+ .filter { !removedUrls.contains(it) } // do not process 'modifications' of any kind
+ .mapNotNull { fileManager.findFileByUrl(it.url) }
+ .filter { it.isDirectory }
if (added.isNotEmpty() && vcsManager.haveDefaultMapping() == null) {
synchronized(dirtyContentRoots) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/details/commit/CommitDetailsPanel.kt b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/details/commit/CommitDetailsPanel.kt
index bfcf7e99b2e9..538379d4e3fe 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/details/commit/CommitDetailsPanel.kt
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/details/commit/CommitDetailsPanel.kt
@@ -7,7 +7,6 @@ import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl
import com.intellij.openapi.project.DumbAwareAction
-import com.intellij.openapi.ui.VerticalFlowLayout
import com.intellij.openapi.ui.popup.Balloon
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.util.text.HtmlChunk
@@ -38,6 +37,7 @@ class CommitDetailsPanel @JvmOverloads constructor(navigate: (CommitId) -> Unit
const val SIDE_BORDER = 14
const val INTERNAL_BORDER = 10
const val EXTERNAL_BORDER = 14
+ const val VCS_LOG_DESCRIPTION_MIN_WIDTH = 40
}
private val statusesActionGroup = DefaultActionGroup()
@@ -65,7 +65,7 @@ class CommitDetailsPanel @JvmOverloads constructor(navigate: (CommitId) -> Unit
isOpaque = false
val mainPanel = JPanel(null).apply {
- layout = VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)
+ layout = MigLayout(LC().gridGap("0", "0").insets("0").fill().flowY())
isOpaque = false
val metadataPanel = BorderLayoutPanel().apply {
@@ -75,11 +75,12 @@ class CommitDetailsPanel @JvmOverloads constructor(navigate: (CommitId) -> Unit
addToCenter(hashAndAuthorPanel)
}
- add(messagePanel)
- add(metadataPanel)
- add(branchesPanel)
- add(tagsPanel)
- add(containingBranchesPanel)
+ val componentLayout = CC().minWidth("$VCS_LOG_DESCRIPTION_MIN_WIDTH").grow().push()
+ add(messagePanel, componentLayout)
+ add(metadataPanel, componentLayout)
+ add(branchesPanel, componentLayout)
+ add(tagsPanel, componentLayout)
+ add(containingBranchesPanel, componentLayout)
}
add(mainPanel, CC().grow().push())
@@ -232,7 +233,8 @@ private class ContainingBranchesPanel : HtmlPanel() {
override fun getBody(): String {
val insets = insets
- val text = getBranchesText(branches, expanded, width - insets.left - insets.right, getFontMetrics(bodyFont))
+ val availableWidth = width - insets.left - insets.right
+ val text = getBranchesText(branches, expanded, availableWidth, getFontMetrics(bodyFont))
return if (expanded) text else HtmlChunk.raw(text).wrapWith("nobr").toString()
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java
index c1a27c740625..de3f49d9c62d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java
@@ -7,6 +7,7 @@ import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.text.LiteralFormatUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -65,7 +66,7 @@ public class UnpredictableBigDecimalConstructorCallInspection extends BaseInspec
}
static String getLiteralText(PsiLiteralExpression firstArgument) {
- final String text = firstArgument.getText();
+ final String text = LiteralFormatUtil.removeUnderscores(firstArgument.getText());
final char c = text.charAt(text.length() - 1);
return c == 'd' || c == 'D' || c == 'f' || c == 'F'
? text.substring(0, text.length() - 1)
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/numeric/unpredictable_big_decimal/Underscores.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/numeric/unpredictable_big_decimal/Underscores.after.java
new file mode 100644
index 000000000000..7e035d3d809c
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/numeric/unpredictable_big_decimal/Underscores.after.java
@@ -0,0 +1,6 @@
+import java.math.BigDecimal;
+
+class Underscores {
+
+ BigDecimal bd = new BigDecimal("1000.1");
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/numeric/unpredictable_big_decimal/Underscores.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/numeric/unpredictable_big_decimal/Underscores.java
new file mode 100644
index 000000000000..7cfdafc41a57
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/numeric/unpredictable_big_decimal/Underscores.java
@@ -0,0 +1,6 @@
+import java.math.BigDecimal;
+
+class Underscores {
+
+ BigDecimal bd = new <caret>BigDecimal(1_000.1d);
+} \ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/numeric/UnpredictableBigDecimalConstructorCallFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/numeric/UnpredictableBigDecimalConstructorCallFixTest.java
index 1de7059b78a3..ce3e12b367aa 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/numeric/UnpredictableBigDecimalConstructorCallFixTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/numeric/UnpredictableBigDecimalConstructorCallFixTest.java
@@ -1,4 +1,4 @@
-// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.siyeh.ig.fixes.numeric;
import com.intellij.codeInspection.CommonQuickFixBundle;
@@ -40,4 +40,8 @@ public class UnpredictableBigDecimalConstructorCallFixTest extends IGQuickFixesT
public void testLiteral() {
doTest(CommonQuickFixBundle.message("fix.replace.with.x", "new BigDecimal(\"2\")"));
}
+
+ public void testUnderscores() {
+ doTest(CommonQuickFixBundle.message("fix.replace.with.x", "new BigDecimal(\"1000.1\")"));
+ }
}
diff --git a/plugins/devkit/devkit-core/resources/fileTemplates/j2ee/devkit-build.gradle.kts.ft b/plugins/devkit/devkit-core/resources/fileTemplates/j2ee/devkit-build.gradle.kts.ft
index 92c6c3ff1ea8..095d8b379afa 100644
--- a/plugins/devkit/devkit-core/resources/fileTemplates/j2ee/devkit-build.gradle.kts.ft
+++ b/plugins/devkit/devkit-core/resources/fileTemplates/j2ee/devkit-build.gradle.kts.ft
@@ -13,7 +13,8 @@ repositories {
mavenCentral()
}
-// Configure Gradle IntelliJ Plugin - read more: https://github.com/JetBrains/gradle-intellij-plugin
+// Configure Gradle IntelliJ Plugin
+// Read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html
intellij {
version.set("${context.getBomProperty("intellij.version")}")
type.set("IC") // Target IDE Platform
diff --git a/plugins/git4idea/src/git4idea/checkin/GitSkipHooksCommitHandlerFactory.kt b/plugins/git4idea/src/git4idea/checkin/GitSkipHooksCommitHandlerFactory.kt
index 1ccbda46cf20..ba10b15dcb13 100644
--- a/plugins/git4idea/src/git4idea/checkin/GitSkipHooksCommitHandlerFactory.kt
+++ b/plugins/git4idea/src/git4idea/checkin/GitSkipHooksCommitHandlerFactory.kt
@@ -3,7 +3,6 @@ package git4idea.checkin
import com.intellij.openapi.util.Key
import com.intellij.openapi.vcs.CheckinProjectPanel
-import com.intellij.openapi.vcs.ProjectLevelVcsManager
import com.intellij.openapi.vcs.changes.CommitContext
import com.intellij.openapi.vcs.changes.LocalChangeList
import com.intellij.openapi.vcs.checkin.CheckinChangeListSpecificComponent
@@ -13,7 +12,6 @@ import com.intellij.openapi.vcs.ui.RefreshableOnComponent
import com.intellij.ui.NonFocusableCheckBox
import com.intellij.util.ui.JBUI
import com.intellij.vcs.commit.commitProperty
-import git4idea.GitUtil.getRepositoryManager
import git4idea.GitVcs
import git4idea.i18n.GitBundle
import git4idea.repo.GitRepository
@@ -46,33 +44,30 @@ private class GitSkipHooksConfigurationPanel(
) : RefreshableOnComponent,
CheckinChangeListSpecificComponent {
- private val vcs = GitVcs.getInstance(panel.project)
+ private val repositoryManager get() = GitRepositoryManager.getInstance(panel.project)
private val runHooks = NonFocusableCheckBox(GitBundle.message("checkbox.run.git.hooks")).apply {
+ isSelected = true
mnemonic = KeyEvent.VK_H
toolTipText = GitBundle.message("tooltip.run.git.hooks")
}
- private var selectedState = true
override fun getComponent(): JComponent = JBUI.Panels.simplePanel(runHooks)
+ private fun refreshAvailability() {
+ runHooks.isVisible = repositoryManager.repositories.any { it.hasCommitHooks() }
+ }
+
override fun onChangeListSelected(list: LocalChangeList) {
- if (runHooks.isEnabled) selectedState = runHooks.isSelected
- val affectedGitRoots = panel.roots.intersect(setOf(*ProjectLevelVcsManager.getInstance(panel.project).getRootsUnderVcs(vcs)))
- val repositoryManager = GitRepositoryManager.getInstance(panel.project)
- runHooks.isEnabled = affectedGitRoots.any { repositoryManager.getRepositoryForRootQuick(it)?.hasCommitHooks() == true }
- runHooks.isSelected = if (runHooks.isEnabled) selectedState else false
+ refreshAvailability()
}
override fun saveState() {
- commitContext.isSkipHooks = shouldSkipHook()
+ commitContext.isSkipHooks = runHooks.isVisible && !runHooks.isSelected
}
override fun restoreState() {
- runHooks.isVisible = getRepositoryManager(panel.project).repositories.any { it.hasCommitHooks() }
- runHooks.isSelected = true
+ refreshAvailability()
}
- private fun shouldSkipHook() = runHooks.isVisible && !runHooks.isSelected
-
private fun GitRepository.hasCommitHooks() = info.hooksInfo.areCommitHooksAvailable
}
diff --git a/plugins/grazie/src/main/kotlin/com/intellij/grazie/grammar/LanguageToolChecker.kt b/plugins/grazie/src/main/kotlin/com/intellij/grazie/grammar/LanguageToolChecker.kt
index 024b3d87577d..5148c64e799b 100644
--- a/plugins/grazie/src/main/kotlin/com/intellij/grazie/grammar/LanguageToolChecker.kt
+++ b/plugins/grazie/src/main/kotlin/com/intellij/grazie/grammar/LanguageToolChecker.kt
@@ -130,7 +130,8 @@ open class LanguageToolChecker : TextChecker() {
private val logger = LoggerFactory.getLogger(LanguageToolChecker::class.java)
private val interner = Interner.createWeakInterner<String>()
private val sentenceSeparationRules = setOf("LC_AFTER_PERIOD", "PUNT_GEEN_HL", "KLEIN_NACH_PUNKT")
- private val openClosedRegexp = Regex("[\\[(].+(\\.\\.|:|,).+[])]")
+ private val openClosedRangeStart = Regex("[\\[(].+?(\\.\\.|:|,).+[])]")
+ private val openClosedRangeEnd = Regex(".*" + openClosedRangeStart.pattern)
internal fun grammarRules(tool: JLanguageTool, lang: Lang): List<LanguageToolRule> {
return tool.allRules.asSequence()
@@ -174,10 +175,11 @@ open class LanguageToolChecker : TextChecker() {
}
// https://github.com/languagetool-org/languagetool/issues/6566
+ @OptIn(ExperimentalStdlibApi::class)
private fun couldBeOpenClosedRange(text: TextContent, index: Int): Boolean {
val unpaired = text[index]
- return "([".contains(unpaired) && openClosedRegexp.find(text, index)?.range?.start == index ||
- ")]".contains(unpaired) && openClosedRegexp.findAll(text.subSequence(0, index + 1)).any { it.range.last == index }
+ return "([".contains(unpaired) && openClosedRangeStart.matchesAt(text, index) ||
+ ")]".contains(unpaired) && openClosedRangeEnd.matches(text.subSequence(0, index + 1))
}
// https://github.com/languagetool-org/languagetool/issues/5230
diff --git a/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/TextContentBuilder.java b/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/TextContentBuilder.java
index fc74f70278fb..cd99ec822d5a 100644
--- a/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/TextContentBuilder.java
+++ b/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/TextContentBuilder.java
@@ -102,25 +102,32 @@ public class TextContentBuilder {
@Nullable
public TextContent build(PsiElement root, TextContent.TextDomain domain, TextRange valueRange) {
- int rootStart = root.getTextRange().getStartOffset();
- String rootText = root.getText();
- if (isWrongRange(valueRange, rootText.length())) {
- LOG.error("The range " + valueRange + " is out of the PSI element, length " + rootText.length());
+ TextRange rootRange = root.getTextRange();
+ if (isWrongRange(valueRange, rootRange.getLength())) {
+ LOG.error("The range " + valueRange + " is out of the PSI element, length " + rootRange.getLength());
+ return null;
+ }
+
+ int rootStart = rootRange.getStartOffset();
+ TextRange fileValueRange = valueRange.shiftRight(rootStart);
+ CharSequence fileText = root.getContainingFile().getViewProvider().getContents();
+ if (isWrongRange(fileValueRange, fileText.length())) {
+ LOG.error("The range " + fileValueRange + " is out of the file, length " + fileText.length());
return null;
}
TextContent content = new PsiRecursiveElementWalkingVisitor() {
final List<TextContentImpl.TokenInfo> tokens = new ArrayList<>();
- int currentStart = valueRange.getStartOffset();
+ int currentStart = fileValueRange.getStartOffset();
@Override
public void visitElement(@NotNull PsiElement element) {
- TextRange range = element.getTextRange().shiftLeft(rootStart).intersection(valueRange);
+ TextRange range = element.getTextRange().intersection(fileValueRange);
if (range == null) return;
if (unknown.test(element)) {
exclusionStarted(range);
- tokens.add(new TextContentImpl.PsiToken("", root, TextRange.from(range.getStartOffset(), 0), true));
+ tokens.add(new TextContentImpl.PsiToken("", root, TextRange.from(range.getStartOffset(), 0).shiftLeft(rootStart), true));
}
else if (excluded.test(element)) {
exclusionStarted(range);
@@ -133,14 +140,15 @@ public class TextContentBuilder {
private void exclusionStarted(TextRange range) {
if (range.getStartOffset() != currentStart) {
TextRange tokenRange = new TextRange(currentStart, range.getStartOffset());
- tokens.add(new TextContentImpl.PsiToken(tokenRange.substring(rootText), root, tokenRange, false));
+ String tokenText = tokenRange.subSequence(fileText).toString();
+ tokens.add(new TextContentImpl.PsiToken(tokenText, root, tokenRange.shiftLeft(rootStart), false));
}
currentStart = range.getEndOffset();
}
@Nullable TextContent walkPsiTree() {
root.accept(this);
- exclusionStarted(TextRange.from(valueRange.getEndOffset(), 0));
+ exclusionStarted(TextRange.from(fileValueRange.getEndOffset(), 0));
return tokens.isEmpty() ? null : new TextContentImpl(domain, tokens);
}
}.walkPsiTree();
diff --git a/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/TextContentImpl.java b/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/TextContentImpl.java
index cacb0d0c66b6..3874b99039d6 100644
--- a/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/TextContentImpl.java
+++ b/plugins/grazie/src/main/kotlin/com/intellij/grazie/text/TextContentImpl.java
@@ -456,5 +456,15 @@ class TextContentImpl extends UserDataHolderBase implements TextContent {
static class WSTokenInfo extends TokenInfo {
WSTokenInfo(char ws) { super(String.valueOf(ws)); }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof WSTokenInfo && ((WSTokenInfo)obj).text.equals(text);
+ }
+
+ @Override
+ public int hashCode() {
+ return text.hashCode();
+ }
}
}
diff --git a/plugins/grazie/src/test/kotlin/com/intellij/grazie/text/TextContentTest.java b/plugins/grazie/src/test/kotlin/com/intellij/grazie/text/TextContentTest.java
index 7415b6f601f6..b5732abb5fd9 100644
--- a/plugins/grazie/src/test/kotlin/com/intellij/grazie/text/TextContentTest.java
+++ b/plugins/grazie/src/test/kotlin/com/intellij/grazie/text/TextContentTest.java
@@ -101,6 +101,8 @@ public class TextContentTest extends BasePlatformTestCase {
assertEquals("| c|", unknownOffsets(joined.markUnknown(new TextRange(0, 1))));
assertEquals("c|", unknownOffsets(joined.excludeRange(new TextRange(0, 1))));
+
+ assertEquals(joined, TextContent.joinWithWhitespace(' ', List.of(f1, f2)));
}
public static String unknownOffsets(TextContent text) {
diff --git a/plugins/grazie/src/test/kotlin/com/intellij/grazie/text/TextExtractionTest.java b/plugins/grazie/src/test/kotlin/com/intellij/grazie/text/TextExtractionTest.java
index f0facee7550b..16ae0a34ac8f 100644
--- a/plugins/grazie/src/test/kotlin/com/intellij/grazie/text/TextExtractionTest.java
+++ b/plugins/grazie/src/test/kotlin/com/intellij/grazie/text/TextExtractionTest.java
@@ -15,6 +15,7 @@ import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.manipulators.StringLiteralManipulator;
import com.intellij.psi.javadoc.PsiDocComment;
+import com.intellij.psi.javadoc.PsiDocTag;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlTag;
import com.intellij.testFramework.PlatformTestUtil;
@@ -320,6 +321,21 @@ public class TextExtractionTest extends BasePlatformTestCase {
}).assertTiming();
}
+ public void testBuildingPerformance_complexPsi() {
+ String link = "{@link foo.bar.goo1.goo2.goo3.goo4.goo5.goo6.goo7#zoo(x.x1.x2.x3,y.y1.y2.y3,z.z1.z2.z3)}";
+ var text = "/** @return something if " + link.repeat(10_000) + " is not too expensive */";
+ PsiFile file = myFixture.configureByText("a.java", text);
+ TextExtractor extractor = new JavaTextExtractor();
+ PsiElement tag = PsiTreeUtil.findElementOfClassAtOffset(file, text.indexOf("something"), PsiDocTag.class, false);
+ PlatformTestUtil.startPerformanceTest("TextContent building from complex PSI", 400, () -> {
+ for (int i = 0; i < 10; i++) {
+ TextContent content = extractor.buildTextContent(tag, TextContent.TextDomain.ALL);
+ assertEquals("something if is not too expensive", content.toString());
+ }
+ }).assertTiming();
+ }
+
+
public void testCachingWorks() {
TextExtractor delegate = TextExtractor.EP.forLanguage(MarkdownLanguage.INSTANCE);
var countingExtractor = new TextExtractor() {
diff --git a/plugins/ide-features-trainer/src/training/featuresSuggester/settings/FeatureSuggesterSettings.kt b/plugins/ide-features-trainer/src/training/featuresSuggester/settings/FeatureSuggesterSettings.kt
index 1ab5e7630d4c..6156bea8808b 100644
--- a/plugins/ide-features-trainer/src/training/featuresSuggester/settings/FeatureSuggesterSettings.kt
+++ b/plugins/ide-features-trainer/src/training/featuresSuggester/settings/FeatureSuggesterSettings.kt
@@ -1,7 +1,9 @@
+// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package training.featuresSuggester.settings
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.PersistentStateComponent
+import com.intellij.openapi.components.RoamingType
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.diagnostic.thisLogger
@@ -15,7 +17,7 @@ import kotlin.math.min
@State(
name = "FeatureSuggesterSettings",
- storages = [Storage("FeatureSuggester.xml")]
+ storages = [Storage("FeatureSuggester.xml", roamingType = RoamingType.DISABLED)]
)
class FeatureSuggesterSettings : PersistentStateComponent<FeatureSuggesterSettings> {
var suggesters: MutableMap<String, Boolean> = run {
diff --git a/plugins/package-search/src/com/jetbrains/packagesearch/intellij/plugin/extensibility/PackageVersionRangeInspection.kt b/plugins/package-search/src/com/jetbrains/packagesearch/intellij/plugin/extensibility/PackageVersionRangeInspection.kt
index ceead934202f..b913f81a2aa7 100644
--- a/plugins/package-search/src/com/jetbrains/packagesearch/intellij/plugin/extensibility/PackageVersionRangeInspection.kt
+++ b/plugins/package-search/src/com/jetbrains/packagesearch/intellij/plugin/extensibility/PackageVersionRangeInspection.kt
@@ -9,23 +9,17 @@ import com.jetbrains.packagesearch.intellij.plugin.util.packageSearchProjectServ
abstract class PackageVersionRangeInspection : AbstractPackageUpdateInspectionCheck() {
- companion object {
-
- private fun isRange(version: String) = version.any { !it.isLetter() && !it.isDigit() && it != '_' && it != '.' && it != '-' }
- }
-
override fun ProblemsHolder.checkFile(file: PsiFile, fileModule: Module) {
file.project.packageSearchProjectService.dependenciesByModuleStateFlow.value
.entries
.find { it.key.nativeModule == fileModule }
?.value
- ?.filter { dependency -> dependency.coordinates.version?.let { isRange(it) } ?: false }
+ ?.filter { dependency -> dependency.coordinates.version?.let { isIvyRange(it) } ?: false }
?.mapNotNull { coordinates ->
runCatching { getVersionPsiElement(file, coordinates) }.getOrNull()
?.let { coordinates to it }
}
?.forEach { (dependency, psiElement) ->
-
val message = dependency.coordinates.version
?.let { PackageSearchBundle.message("packagesearch.inspection.upgrade.range.withVersion", it) }
?: PackageSearchBundle.message("packagesearch.inspection.upgrade.range")
@@ -33,4 +27,18 @@ abstract class PackageVersionRangeInspection : AbstractPackageUpdateInspectionCh
registerProblem(psiElement, message, ProblemHighlightType.WEAK_WARNING)
}
}
-} \ No newline at end of file
+
+ private fun isIvyRange(version: String): Boolean {
+ // See https://ant.apache.org/ivy/history/2.1.0/ivyfile/dependency.html
+ val normalizedVersion = version.trimEnd()
+ if (normalizedVersion.endsWith('+')) return true
+
+ if (normalizedVersion.startsWith("latest.")) return true
+
+ val startsWithParenthesisOrBrackets = normalizedVersion.startsWith('(') || normalizedVersion.startsWith('[')
+ val endsWithParenthesisOrBrackets = normalizedVersion.endsWith(')') || normalizedVersion.endsWith(']')
+ if (startsWithParenthesisOrBrackets && endsWithParenthesisOrBrackets) return true
+
+ return false
+ }
+}
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltConfigurationProducer.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltConfigurationProducer.java
index 5daa71464bee..1541c5bf1808 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltConfigurationProducer.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltConfigurationProducer.java
@@ -2,12 +2,9 @@
package org.intellij.lang.xpath.xslt.run;
-import com.intellij.execution.RunManager;
-import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.actions.LazyRunConfigurationProducer;
import com.intellij.execution.configurations.ConfigurationFactory;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
@@ -28,10 +25,7 @@ public class XsltConfigurationProducer extends LazyRunConfigurationProducer<Xslt
if (file == null) {
return false;
}
- final Project project = file.getProject();
- final RunnerAndConfigurationSettings settings =
- RunManager.getInstance(project).createConfiguration(file.getName(), getConfigurationFactory());
- ((XsltRunConfiguration)settings.getConfiguration()).initFromFile(file);
+ configuration.initFromFile(file);
return true;
}
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java
index acf6a7d0affc..a58676104337 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java
@@ -479,6 +479,7 @@ public final class XsltRunConfiguration extends LocatableConfigurationBase imple
public XsltRunConfiguration initFromFile(@NotNull XmlFile file) {
assert XsltSupport.isXsltFile(file) : "Not an XSLT file: " + file.getName();
mySuggestedName = file.getName();
+ setName(mySuggestedName);
final VirtualFile virtualFile = file.getVirtualFile();
assert virtualFile != null : "No VirtualFile for " + file.getName();
diff --git a/python/ideCoreSrc/idea/PyCharmCoreApplicationInfo.xml b/python/ideCoreSrc/idea/PyCharmCoreApplicationInfo.xml
index 404b5c2b7cb7..5693151fde5c 100644
--- a/python/ideCoreSrc/idea/PyCharmCoreApplicationInfo.xml
+++ b/python/ideCoreSrc/idea/PyCharmCoreApplicationInfo.xml
@@ -2,7 +2,7 @@
<component xmlns="http://jetbrains.org/intellij/schema/application-info"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jetbrains.org/intellij/schema/application-info http://jetbrains.org/intellij/schema/ApplicationInfo.xsd">
- <version major="2022" minor="1.3" suffix="RC" eap="false"/>
+ <version suffix="RC" major="2022" minor="1.4" eap="false"/>
<company name="JetBrains s.r.o." url="https://www.jetbrains.com" copyrightStart="2010"/>
<build number="PC-__BUILD__" date="__BUILD_DATE__" majorReleaseDate="20220413"/>
<logo url="/pycharm_core_logo.png" textcolor="ffffff" progressColor="ffffff" progressY="396" progressHeight="4"/>
diff --git a/uast/uast-common/src/org/jetbrains/uast/UastUtils.kt b/uast/uast-common/src/org/jetbrains/uast/UastUtils.kt
index 38ead72a07a9..0a9adda0226c 100644
--- a/uast/uast-common/src/org/jetbrains/uast/UastUtils.kt
+++ b/uast/uast-common/src/org/jetbrains/uast/UastUtils.kt
@@ -27,7 +27,7 @@ fun <T : UElement> UElement.getParentOfType(parentClass: Class<out T>, strict: B
}
fun UElement.skipParentOfType(strict: Boolean, vararg parentClasses: Class<out UElement>): UElement? {
- var element = (if (strict) uastParent else this) ?: return null
+ var element = (if (strict) uastParent else this) ?: return null
while (true) {
if (!parentClasses.any { it.isInstance(element) }) {
return element
@@ -143,9 +143,9 @@ fun UElement.tryResolveNamed(): PsiNamedElement? = (this as? UResolvable)?.resol
fun UReferenceExpression?.getQualifiedName(): String? = (this?.resolve() as? PsiClass)?.qualifiedName
/**
- * Returns the String expression value, or null if the value can't be calculated or if the calculated value is not a String.
+ * Returns the String expression value, or null if the value can't be calculated, or if the calculated value is not a String or an integral literal.
*/
-fun UExpression.evaluateString(): String? = evaluate() as? String
+fun UExpression.evaluateString(): String? = evaluate().takeIf { it is String || isIntegralLiteral() }?.toString()
fun UExpression.skipParenthesizedExprDown(): UExpression? {
var expression = this
@@ -231,7 +231,7 @@ tailrec fun UElement.isLastElementInControlFlow(scopeElement: UElement? = null):
}
fun UNamedExpression.getAnnotationMethod(): PsiMethod? {
- val annotation : UAnnotation? = getParentOfType(UAnnotation::class.java, true)
+ val annotation: UAnnotation? = getParentOfType(UAnnotation::class.java, true)
val fqn = annotation?.qualifiedName ?: return null
val annotationSrc = annotation.sourcePsi
if (annotationSrc == null) return null