From 5dfbf73d71a27de6778511d042dfb18918e541f6 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 19 Sep 2025 12:30:12 +0200 Subject: [PATCH] Cleanup (salvaging `expandUserHome` from `FileUtil`) GitOrigin-RevId: 27f7b33848e0a8d20d86dfe83192cef411d03253 --- grid/impl/src/view/ui/DumpDataDialog.java | 4 ++-- .../starters/shared/ValidationFunctions.java | 7 +++--- .../src/com/intellij/util/PathUtil.java | 23 ++++++++----------- .../src/StartUpPerformanceReporter.kt | 4 ++-- .../com/intellij/dvcs/ui/CloneDvcsDialog.java | 6 ++--- .../ProjectSettingsStepBase.java | 5 ++-- .../navigation/NavigatorWithinProject.kt | 10 +++++--- .../impl/jdkDownloader/JdkDownloadDialog.kt | 6 ++--- .../impl/jdkDownloader/JdkInstaller.kt | 3 ++- .../impl/jdkDownloader/RuntimeChooserModel.kt | 5 ++-- .../openapi/ui/TextFieldWithBrowseButton.java | 6 ++--- .../src/com/intellij/openapi/ui/UiUtils.kt | 8 +++---- .../ide/impl/TrustedHostsConfigurable.kt | 6 ++--- .../openapi/fileChooser/ex/LocalFsFinder.java | 3 +-- .../impl/FileChooserPanelImpl.java | 6 ++--- platform/util/api-dump-unreviewed.txt | 9 -------- platform/util/api-dump.txt | 10 ++++++++ .../intellij/openapi/util/io/FileUtil.java | 13 ++++------- .../openapi/util/io/OSAgnosticPathUtil.java | 17 +++++++++++++- .../patch/CreatePatchConfigurationPanel.kt | 13 ++++------- .../maven/wizards/archetype/CatalogUiUtil.kt | 8 +++---- .../mcpserver/impl/McpClientDetector.kt | 14 +++++------ .../org/jetbrains/ide/OpenFileHttpService.kt | 8 ++++--- plugins/settings-repository/src/IcsManager.kt | 8 +++---- .../ShFilePathCompletionContributor.java | 7 +++--- .../spec/ShellRuntimeContextExtensions.kt | 8 +++---- .../runner/LocalShellIntegrationInjector.java | 4 ++-- 27 files changed, 116 insertions(+), 105 deletions(-) diff --git a/grid/impl/src/view/ui/DumpDataDialog.java b/grid/impl/src/view/ui/DumpDataDialog.java index d47f77f7b8b6..64d2474a6a13 100644 --- a/grid/impl/src/view/ui/DumpDataDialog.java +++ b/grid/impl/src/view/ui/DumpDataDialog.java @@ -12,7 +12,7 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.*; -import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.OSAgnosticPathUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.ReadonlyStatusHandler; @@ -92,7 +92,7 @@ public abstract class DumpDataDialog extends DialogWrapper { } private String getDirPath() { - return FileUtil.expandUserHome(myForm.getOutputFileOrDirectoryField().getText().trim()); + return OSAgnosticPathUtil.expandUserHome(myForm.getOutputFileOrDirectoryField().getText().trim()); } private void addDocumentListener(JTextComponent component) { diff --git a/java/idea-ui/src/com/intellij/ide/starters/shared/ValidationFunctions.java b/java/idea-ui/src/com/intellij/ide/starters/shared/ValidationFunctions.java index 8cfdec777e7b..46ae9cd37104 100644 --- a/java/idea-ui/src/com/intellij/ide/starters/shared/ValidationFunctions.java +++ b/java/idea-ui/src/com/intellij/ide/starters/shared/ValidationFunctions.java @@ -1,9 +1,10 @@ -// Copyright 2000-2021 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-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide.starters.shared; import com.intellij.ide.starters.JavaStartersBundle; import com.intellij.openapi.observable.properties.GraphProperty; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.OSAgnosticPathUtil; import com.intellij.psi.impl.PsiNameHelperImpl; import java.io.File; @@ -116,7 +117,7 @@ public final class ValidationFunctions { public static TextValidationFunction createLocationWarningValidator(GraphProperty locationProperty) { return fieldText -> { try { - File file = Paths.get(FileUtil.expandUserHome(FileUtil.join(locationProperty.get(), fieldText))).toFile(); + File file = Paths.get(OSAgnosticPathUtil.expandUserHome(FileUtil.join(locationProperty.get(), fieldText))).toFile(); if (file.exists()) { String[] children = file.list(); if (children != null && children.length > 0) { @@ -133,7 +134,7 @@ public final class ValidationFunctions { public static final TextValidationFunction CHECK_LOCATION_FOR_ERROR = fieldText -> { Path locationPath; try { - locationPath = Paths.get(FileUtil.expandUserHome(fieldText)); + locationPath = Paths.get(OSAgnosticPathUtil.expandUserHome(fieldText)); } catch (InvalidPathException e) { return JavaStartersBundle.message("message.specified.path.is.illegal"); } diff --git a/platform/core-api/src/com/intellij/util/PathUtil.java b/platform/core-api/src/com/intellij/util/PathUtil.java index 0ba1e4d74414..7623ea58ce57 100644 --- a/platform/core-api/src/com/intellij/util/PathUtil.java +++ b/platform/core-api/src/com/intellij/util/PathUtil.java @@ -1,9 +1,8 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.util; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.util.NlsSafe; -import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.io.OSAgnosticPathUtil; @@ -11,10 +10,8 @@ import com.intellij.openapi.util.text.Strings; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.io.URLUtil; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import com.intellij.util.system.OS; +import org.jetbrains.annotations.*; public final class PathUtil { private PathUtil() { } @@ -43,10 +40,10 @@ public final class PathUtil { return getLocalPath(VirtualFileManager.extractPath(url)); } - /** - * @deprecated Use {@link FileUtil#toCanonicalPath(String)} - */ + /** @deprecated Use NIO API instead */ @Deprecated + @ApiStatus.ScheduledForRemoval + @SuppressWarnings("UsagesOfObsoleteApi") public static String getCanonicalPath(@NonNls String path) { return FileUtil.toCanonicalPath(path); } @@ -90,13 +87,11 @@ public final class PathUtil { } public static @NotNull String driveLetterToLowerCase(@NotNull String path) { - if (SystemInfoRt.isWindows && OSAgnosticPathUtil.isAbsoluteDosPath(path) && Character.isUpperCase(path.charAt(0))) { - return Character.toLowerCase(path.charAt(0)) + path.substring(1); - } - return path; + boolean convert = OS.CURRENT == OS.Windows && OSAgnosticPathUtil.isAbsoluteDosPath(path) && Character.isUpperCase(path.charAt(0)); + return convert ? Character.toLowerCase(path.charAt(0)) + path.substring(1) : path; } public static @NotNull String makeFileName(@NotNull String name, @Nullable String extension) { return extension == null || extension.isEmpty() ? name : name + '.' + extension; } -} \ No newline at end of file +} diff --git a/platform/diagnostic/startUpPerformanceReporter/src/StartUpPerformanceReporter.kt b/platform/diagnostic/startUpPerformanceReporter/src/StartUpPerformanceReporter.kt index cdb5d56f3d52..9b3ffcf6bba8 100644 --- a/platform/diagnostic/startUpPerformanceReporter/src/StartUpPerformanceReporter.kt +++ b/platform/diagnostic/startUpPerformanceReporter/src/StartUpPerformanceReporter.kt @@ -13,7 +13,7 @@ import com.intellij.openapi.application.PathManager import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.project.Project -import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import com.intellij.platform.diagnostic.telemetry.TelemetryManager import com.intellij.platform.diagnostic.telemetry.impl.TelemetryManagerImpl import com.intellij.util.SystemProperties @@ -155,7 +155,7 @@ private suspend fun logAndClearStats(projectName: String, perfFilePath: String?) val classReport = System.getProperty("idea.log.class.list.file") if (!classReport.isNullOrBlank()) { - generateJarAccessLog(Path.of(FileUtil.expandUserHome(classReport))) + generateJarAccessLog(Path.of(OSAgnosticPathUtil.expandUserHome(classReport))) } for (instantEvent in instantEvents.filter { setOf("splash shown", "splash hidden").contains(it.name) }) { diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java index 206b7e3e34d9..69db3134ea20 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/ui/CloneDvcsDialog.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.dvcs.ui; import com.intellij.dvcs.DvcsRememberedInputs; @@ -16,7 +16,7 @@ import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.OSAgnosticPathUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; import com.intellij.ui.awt.RelativePoint; @@ -231,7 +231,7 @@ public abstract class CloneDvcsDialog extends DialogWrapper { } private @NotNull String getCurrentUrlText() { - return FileUtil.expandUserHome(myRepositoryUrlField.getText().trim()); + return OSAgnosticPathUtil.expandUserHome(myRepositoryUrlField.getText().trim()); } /** diff --git a/platform/lang-impl/src/com/intellij/ide/util/projectWizard/ProjectSettingsStepBase.java b/platform/lang-impl/src/com/intellij/ide/util/projectWizard/ProjectSettingsStepBase.java index 0ff59394c216..1c2d346eee38 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/projectWizard/ProjectSettingsStepBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/projectWizard/ProjectSettingsStepBase.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ide.util.projectWizard; import com.intellij.BundleBase; @@ -17,6 +17,7 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.NlsSafe; import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.OSAgnosticPathUtil; import com.intellij.openapi.util.text.HtmlChunk; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.impl.welcomeScreen.AbstractActionWithPanel; @@ -353,7 +354,7 @@ public class ProjectSettingsStepBase extends AbstractActionWithPanel implemen } public String getProjectLocation() { - return FileUtil.expandUserHome(FileUtil.toSystemIndependentName(myLocationField.getText())); + return OSAgnosticPathUtil.expandUserHome(FileUtil.toSystemIndependentName(myLocationField.getText())); } public final void setLocation(final @NotNull String location) { diff --git a/platform/lang-impl/src/com/intellij/navigation/NavigatorWithinProject.kt b/platform/lang-impl/src/com/intellij/navigation/NavigatorWithinProject.kt index fbf69ac3d3b0..584579d374e1 100644 --- a/platform/lang-impl/src/com/intellij/navigation/NavigatorWithinProject.kt +++ b/platform/lang-impl/src/com/intellij/navigation/NavigatorWithinProject.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. @file:Suppress("ReplaceGetOrSet") package com.intellij.navigation @@ -14,7 +14,10 @@ import com.intellij.ide.impl.getProjectOriginUrl import com.intellij.openapi.actionSystem.ActionPlaces import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.impl.SimpleDataContext -import com.intellij.openapi.application.* +import com.intellij.openapi.application.EDT +import com.intellij.openapi.application.JBProtocolCommand +import com.intellij.openapi.application.readAction +import com.intellij.openapi.application.writeIntentReadAction import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.ScrollType import com.intellij.openapi.fileEditor.FileEditorManager @@ -27,6 +30,7 @@ import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.startup.StartupManager import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.wm.IdeFocusManager @@ -194,7 +198,7 @@ class NavigatorWithinProject( } val locationInFile = LocationInFile(line?.toInt() ?: 0, column?.toInt() ?: 0) - path = FileUtil.expandUserHome(path) + path = OSAgnosticPathUtil.expandUserHome(path) withBackgroundProgress(project, IdeBundle.message("navigate.command.search.reference.progress.title", pathText)) { val virtualFile = findFileByStringPath(path) ?: return@withBackgroundProgress val textEditor = withContext(Dispatchers.EDT) { diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/JdkDownloadDialog.kt b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/JdkDownloadDialog.kt index 55f0ef3aa6d6..90d5f9cdb066 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/JdkDownloadDialog.kt +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/JdkDownloadDialog.kt @@ -11,6 +11,7 @@ import com.intellij.openapi.ui.* import com.intellij.openapi.util.NlsContexts import com.intellij.openapi.util.NlsSafe import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import com.intellij.openapi.util.registry.Registry import com.intellij.platform.eel.EelApi import com.intellij.ui.CollectionComboBoxModel @@ -45,8 +46,7 @@ class JdkDownloaderModel( @Internal class JdkVersionItem( - @NlsSafe - val jdkVersion: String, + val jdkVersion: @NlsSafe String, /* we should prefer the default selected item from the JDKs.json feed, * the list below is sorted by vendor, and default item is not necessarily first */ @@ -366,7 +366,7 @@ internal class JdkDownloadDialog( private fun onTargetPathChanged(path: String) { @Suppress("NAME_SHADOWING") - val path = FileUtil.expandUserHome(path) + val path = OSAgnosticPathUtil.expandUserHome(path) selectedPath = path setModel(WslPath.isWslUncPath(path)) diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/JdkInstaller.kt b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/JdkInstaller.kt index 0af89c42ef13..8f41acb3c6c3 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/JdkInstaller.kt +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/JdkInstaller.kt @@ -23,6 +23,7 @@ import com.intellij.openapi.projectRoots.JdkUtil import com.intellij.openapi.projectRoots.impl.jdkDownloader.JdkInstallerEel.unpackJdkOnEel import com.intellij.openapi.projectRoots.impl.jdkDownloader.JdkInstallerWSL.unpackJdkOnWsl import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import com.intellij.openapi.util.registry.Registry import com.intellij.platform.eel.* import com.intellij.platform.eel.path.EelPath @@ -259,7 +260,7 @@ abstract class JdkInstallerBase { return null to ProjectBundle.message("dialog.message.error.target.path.empty") } - val targetDir = runCatching { Path.of(FileUtil.expandUserHome(selectedPath)) }.getOrElse { t -> + val targetDir = runCatching { Path.of(OSAgnosticPathUtil.expandUserHome(selectedPath)) }.getOrElse { t -> LOG.warn("Failed to resolve user path: $selectedPath. ${t.message}", t) return null to ProjectBundle.message("dialog.message.error.resolving.path") } diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/RuntimeChooserModel.kt b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/RuntimeChooserModel.kt index 76e46eb5b142..3477f33e049b 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/RuntimeChooserModel.kt +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/jdkDownloader/RuntimeChooserModel.kt @@ -1,10 +1,11 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.projectRoots.impl.jdkDownloader import com.intellij.openapi.Disposable import com.intellij.openapi.observable.properties.GraphProperty import com.intellij.openapi.observable.properties.PropertyGraph import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths @@ -40,7 +41,7 @@ internal class RuntimeChooserModel { } fun getInstallPathFromText(item: JdkItem, text: String?) : Path { - val path = text?.trim()?.takeIf { it.isNotBlank() }?.let { FileUtil.expandUserHome(it) } + val path = text?.trim()?.takeIf { it.isNotBlank() }?.let { OSAgnosticPathUtil.expandUserHome(it) } if (path != null) { var file = Paths.get(path) repeat(1000) { diff --git a/platform/platform-api/src/com/intellij/openapi/ui/TextFieldWithBrowseButton.java b/platform/platform-api/src/com/intellij/openapi/ui/TextFieldWithBrowseButton.java index 1a7118a02ae0..ba673533de01 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/TextFieldWithBrowseButton.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/TextFieldWithBrowseButton.java @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.ui; import com.intellij.openapi.Disposable; @@ -10,7 +10,7 @@ import com.intellij.openapi.fileChooser.FileChooserFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NlsContexts; import com.intellij.openapi.util.NlsSafe; -import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.OSAgnosticPathUtil; import com.intellij.openapi.util.text.Strings; import com.intellij.ui.TextAccessor; import com.intellij.ui.components.JBTextField; @@ -102,7 +102,7 @@ public class TextFieldWithBrowseButton extends ComponentWithBrowseButton implement return wrapper.path; } if (object instanceof String str && !str.isBlank()) { - var path = findByPath(FileUtil.expandUserHome(str.trim())); + var path = findByPath(OSAgnosticPathUtil.expandUserHome(str.trim())); if (path != null && path.isAbsolute()) { return path; } diff --git a/platform/util/api-dump-unreviewed.txt b/platform/util/api-dump-unreviewed.txt index ad4bf3efd39b..52dfa9585cd5 100644 --- a/platform/util/api-dump-unreviewed.txt +++ b/platform/util/api-dump-unreviewed.txt @@ -1128,15 +1128,6 @@ f:com.intellij.openapi.util.io.NioPathUtil - sf:getResolvedPath(java.nio.file.Path,java.lang.String):java.nio.file.Path - sf:toCanonicalPath(java.nio.file.Path):java.lang.String - sf:toNioPathOrNull(java.lang.String):java.nio.file.Path -f:com.intellij.openapi.util.io.OSAgnosticPathUtil -- sf:COMPARATOR:java.util.Comparator -- s:getParent(java.lang.String):java.lang.String -- s:isAbsolute(java.lang.String):Z -- s:isAbsoluteDosPath(java.lang.String):Z -- s:isDriveLetter(C):Z -- s:isUncPath(java.lang.String):Z -- s:startsWith(java.lang.String,java.lang.String):Z -- s:startsWithWindowsDrive(java.lang.String):Z f:com.intellij.openapi.util.io.StreamUtil - sf:BUFFER_SIZE:I - s:closeStream(java.io.Closeable):V diff --git a/platform/util/api-dump.txt b/platform/util/api-dump.txt index 751723d0837f..0dc9b690db42 100644 --- a/platform/util/api-dump.txt +++ b/platform/util/api-dump.txt @@ -212,6 +212,16 @@ a:com.intellij.openapi.util.io.NioFiles$StatsCollectingVisitor - visitFileFailed(java.nio.file.Path,java.io.IOException):java.nio.file.FileVisitResult f:com.intellij.openapi.util.io.NioJarUtilKt - sf:getJarAttribute(java.nio.file.Path,java.util.jar.Attributes$Name):java.lang.String +f:com.intellij.openapi.util.io.OSAgnosticPathUtil +- sf:COMPARATOR:java.util.Comparator +- s:expandUserHome(java.lang.String):java.lang.String +- s:getParent(java.lang.String):java.lang.String +- s:isAbsolute(java.lang.String):Z +- s:isAbsoluteDosPath(java.lang.String):Z +- s:isDriveLetter(C):Z +- s:isUncPath(java.lang.String):Z +- s:startsWith(java.lang.String,java.lang.String):Z +- s:startsWithWindowsDrive(java.lang.String):Z com.intellij.openapi.util.registry.RegistryValueListener - afterValueChanged(com.intellij.openapi.util.registry.RegistryValue):V - beforeValueChanged(com.intellij.openapi.util.registry.RegistryValue):V diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index 5b477e9fe0a7..4ffedd27de3b 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -1310,17 +1310,12 @@ public class FileUtil { return path; } + /** @deprecated use {@link OSAgnosticPathUtil#expandUserHome} instead. */ @Contract(pure = true) + @Deprecated + @ApiStatus.ScheduledForRemoval public static @NotNull String expandUserHome(@NotNull String path) { - if (path.equals("~")) { - return SystemProperties.getUserHome(); - } - else if (path.startsWith("~/") || path.startsWith("~\\")) { - return SystemProperties.getUserHome() + path.substring(1); - } - else { - return path; - } + return OSAgnosticPathUtil.expandUserHome(path); } public static File @NotNull [] notNullize(File @Nullable [] files) { diff --git a/platform/util/src/com/intellij/openapi/util/io/OSAgnosticPathUtil.java b/platform/util/src/com/intellij/openapi/util/io/OSAgnosticPathUtil.java index 06c36660ea91..0fb50efeea68 100644 --- a/platform/util/src/com/intellij/openapi/util/io/OSAgnosticPathUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/OSAgnosticPathUtil.java @@ -1,10 +1,12 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.util.io; import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.Strings; import com.intellij.util.PathUtilRt; +import com.intellij.util.SystemProperties; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -169,4 +171,17 @@ public final class OSAgnosticPathUtil { public static boolean isDriveLetter(char c) { return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'; } + + @Contract(pure = true) + public static @NotNull String expandUserHome(@NotNull String path) { + if (path.equals("~")) { + return SystemProperties.getUserHome(); + } + else if (path.startsWith("~/") || path.startsWith("~\\")) { + return SystemProperties.getUserHome() + path.substring(1); + } + else { + return path; + } + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.kt index d74d27d62d50..50b4b5e1ad2f 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/CreatePatchConfigurationPanel.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-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.openapi.vcs.changes.patch import com.intellij.ide.IdeBundle @@ -8,6 +8,7 @@ import com.intellij.openapi.fileChooser.FileSaverDescriptor import com.intellij.openapi.project.Project import com.intellij.openapi.ui.* import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import com.intellij.openapi.vcs.VcsBundle.message import com.intellij.openapi.vfs.CharsetToolkit import com.intellij.openapi.vfs.encoding.EncodingProjectManager @@ -116,13 +117,9 @@ class CreatePatchConfigurationPanel(val project: Project) { return panel } - fun getFileName(): String { - return FileUtil.expandUserHome(fileNameField.text.trim()) - } + fun getFileName(): String = OSAgnosticPathUtil.expandUserHome(fileNameField.text.trim()) - fun getBaseDirName(): String { - return FileUtil.expandUserHome(basePathField.getText().trim()) - } + fun getBaseDirName(): String = OSAgnosticPathUtil.expandUserHome(basePathField.text.trim()) fun setFileName(file: Path) { fileNameField.text = file.toString() @@ -185,4 +182,4 @@ class CreatePatchConfigurationPanel(val project: Project) { } return null } -} \ No newline at end of file +} diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/archetype/CatalogUiUtil.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/archetype/CatalogUiUtil.kt index 266a40805309..5086c2e4b33a 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/archetype/CatalogUiUtil.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/archetype/CatalogUiUtil.kt @@ -1,8 +1,8 @@ -// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.idea.maven.wizards.archetype import com.intellij.openapi.ui.validation.validationErrorFor -import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import com.intellij.util.text.nullize import org.jetbrains.idea.maven.indices.archetype.MavenCatalog import org.jetbrains.idea.maven.indices.archetype.MavenCatalogManager @@ -32,7 +32,7 @@ internal fun createCatalog(location: String): MavenCatalog? { return null } -internal fun getPathOrError(location: String) = runCatching { Path(FileUtil.expandUserHome(location)) } +internal fun getPathOrError(location: String) = runCatching { Path(OSAgnosticPathUtil.expandUserHome(location)) } internal fun getUrlOrError(location: String) = runCatching { URL(location) } internal fun getPathOrNull(location: String) = getPathOrError(location).getOrNull() @@ -77,4 +77,4 @@ private fun validateRemoteLocation(location: String): String? { return MavenWizardBundle.message("maven.new.project.wizard.archetype.catalog.dialog.location.error.invalid", message) } return null -} \ No newline at end of file +} diff --git a/plugins/mcp-server/src/com/intellij/mcpserver/impl/McpClientDetector.kt b/plugins/mcp-server/src/com/intellij/mcpserver/impl/McpClientDetector.kt index da9e3add3e6d..09c11c1d2b52 100644 --- a/plugins/mcp-server/src/com/intellij/mcpserver/impl/McpClientDetector.kt +++ b/plugins/mcp-server/src/com/intellij/mcpserver/impl/McpClientDetector.kt @@ -3,7 +3,7 @@ package com.intellij.mcpserver.impl import com.intellij.mcpserver.clientConfiguration.* import com.intellij.openapi.project.Project import com.intellij.openapi.util.SystemInfo -import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import com.intellij.util.containers.addIfNotNull import kotlinx.serialization.ExperimentalSerializationApi import java.nio.file.Path @@ -78,7 +78,7 @@ object McpClientDetector { else -> null } if (configPath == null) return null - val path = Paths.get(FileUtil.expandUserHome(configPath)) + val path = Paths.get(OSAgnosticPathUtil.expandUserHome(configPath)) if (path.exists() && path.isRegularFile()) { return VSCodeClient(path) } @@ -93,7 +93,7 @@ object McpClientDetector { else -> null } if (configPath == null) return null - val path = Paths.get(FileUtil.expandUserHome(configPath)) + val path = Paths.get(OSAgnosticPathUtil.expandUserHome(configPath)) if (path.exists() && path.isRegularFile()) { return ClaudeCodeMcpClient(path) @@ -109,7 +109,7 @@ object McpClientDetector { else -> null } if (configPath == null) return null - val path = Paths.get(FileUtil.expandUserHome(configPath)) + val path = Paths.get(OSAgnosticPathUtil.expandUserHome(configPath)) if (path.parent.exists() && path.parent.toFile().isDirectory()) { return ClaudeMcpClient(path) @@ -118,7 +118,7 @@ object McpClientDetector { } private fun detectCursorGlobal(): McpClient? { - val path = Paths.get(FileUtil.expandUserHome("~/.cursor/mcp.json")) + val path = Paths.get(OSAgnosticPathUtil.expandUserHome("~/.cursor/mcp.json")) if (path.parent.exists() && path.parent.toFile().isDirectory()) { return CursorClient(path) } @@ -126,7 +126,7 @@ object McpClientDetector { } private fun detectWindsurf(): McpClient? { - val path = Paths.get(FileUtil.expandUserHome("~/.codeium/windsurf/mcp_config.json")) + val path = Paths.get(OSAgnosticPathUtil.expandUserHome("~/.codeium/windsurf/mcp_config.json")) if (path.parent.exists() && path.parent.toFile().isDirectory()) { return WindsurfClient(path) } @@ -162,4 +162,4 @@ object McpClientDetector { } return null } -} \ No newline at end of file +} diff --git a/plugins/remote-control/src/org/jetbrains/ide/OpenFileHttpService.kt b/plugins/remote-control/src/org/jetbrains/ide/OpenFileHttpService.kt index 126b5ade688f..7753fd58e37e 100644 --- a/plugins/remote-control/src/org/jetbrains/ide/OpenFileHttpService.kt +++ b/plugins/remote-control/src/org/jetbrains/ide/OpenFileHttpService.kt @@ -10,9 +10,11 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.project.ProjectManager import com.intellij.openapi.project.guessProjectForContentFile import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import com.intellij.openapi.util.text.StringUtilRt import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VirtualFile +import com.intellij.util.PathUtil import com.intellij.util.PathUtilRt import io.netty.channel.ChannelHandlerContext import io.netty.handler.codec.http.* @@ -93,12 +95,12 @@ internal class OpenFileHttpService : RestService() { if (requestedFile == null) { return parameterMissedErrorMessage("file") } - if (PathUtilRt.startsWithSeparatorSeparator(FileUtil.toSystemIndependentName(requestedFile))) { + if (PathUtilRt.startsWithSeparatorSeparator(PathUtil.toSystemIndependentName(requestedFile))) { return "UNC paths are not supported" } - val vfsPath = FileUtil.toSystemIndependentName(FileUtil.expandUserHome(requestedFile)) - val file = Path.of(FileUtil.toSystemDependentName(vfsPath)) + val vfsPath = PathUtil.toSystemIndependentName(OSAgnosticPathUtil.expandUserHome(requestedFile)) + val file = Path.of(PathUtil.toSystemDependentName(vfsPath)) val fileAndProject = if (!file.isAbsolute) { findByRelativePath(FileUtil.toCanonicalPath(vfsPath, '/')) } diff --git a/plugins/settings-repository/src/IcsManager.kt b/plugins/settings-repository/src/IcsManager.kt index 504ec1b875a8..3dce1dca6a15 100644 --- a/plugins/settings-repository/src/IcsManager.kt +++ b/plugins/settings-repository/src/IcsManager.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.settingsRepository import com.intellij.configurationStore.StreamProvider @@ -20,7 +20,7 @@ import com.intellij.openapi.progress.runBackgroundableTask import com.intellij.openapi.progress.runBlockingCancellable import com.intellij.openapi.project.Project import com.intellij.openapi.project.ProjectCloseListener -import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.channels.BufferOverflow @@ -246,7 +246,7 @@ private class IcsManagerService(private val coroutineScope: CoroutineScope) { fun init(app: Application, configPath: Path) { val customPath = System.getProperty("ics.settingsRepository") - val dir = if (customPath == null) configPath.resolve("settingsRepository") else Path.of(FileUtil.expandUserHome(customPath)) + val dir = if (customPath == null) configPath.resolve("settingsRepository") else Path.of(OSAgnosticPathUtil.expandUserHome(customPath)) val icsManager = IcsManager(dir = dir, coroutineScope = coroutineScope) this.icsManager = icsManager icsManager.beforeApplicationLoaded(app) @@ -261,4 +261,4 @@ private class IcsApplicationLoadListener : ApplicationLoadListener { application.serviceAsync().init(application, configPath) } -} \ No newline at end of file +} diff --git a/plugins/sh/backend/src/com/intellij/sh/backend/completion/ShFilePathCompletionContributor.java b/plugins/sh/backend/src/com/intellij/sh/backend/completion/ShFilePathCompletionContributor.java index db624647ba3f..b78cebf006ce 100644 --- a/plugins/sh/backend/src/com/intellij/sh/backend/completion/ShFilePathCompletionContributor.java +++ b/plugins/sh/backend/src/com/intellij/sh/backend/completion/ShFilePathCompletionContributor.java @@ -10,7 +10,7 @@ import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.io.OSAgnosticPathUtil; import com.intellij.patterns.StandardPatterns; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; @@ -31,7 +31,6 @@ import java.util.List; import static com.intellij.patterns.PlatformPatterns.psiElement; import static com.intellij.sh.ShStringUtil.quote; -import static com.intellij.sh.ShStringUtil.unquote; public class ShFilePathCompletionContributor extends CompletionContributor implements DumbAware { private static final InsertHandler FILE_INSERT_HANDLER = (context, item) -> { @@ -95,7 +94,7 @@ public class ShFilePathCompletionContributor extends CompletionContributor imple if (beforeSlash.startsWith("/") || isRoot || beforeSlash.startsWith("~")) { // absolute paths String path = beforeSlash.equals("~") ? "~/" : beforeSlash; - String maybeFilePath = FileUtil.expandUserHome(unquote(path)); + String maybeFilePath = OSAgnosticPathUtil.expandUserHome(ShStringUtil.unquote(path)); File dir = isRoot ? new File("/") : new File(maybeFilePath); if (dir.exists() && dir.isDirectory()) { File[] files = dir.listFiles(); @@ -168,4 +167,4 @@ public class ShFilePathCompletionContributor extends CompletionContributor imple if (index + 1 <= 0) return variable; return variable.substring(index + 1); } -} \ No newline at end of file +} diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/block/completion/spec/ShellRuntimeContextExtensions.kt b/plugins/terminal/src/org/jetbrains/plugins/terminal/block/completion/spec/ShellRuntimeContextExtensions.kt index fe5826827de8..741dff5b7051 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/block/completion/spec/ShellRuntimeContextExtensions.kt +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/block/completion/spec/ShellRuntimeContextExtensions.kt @@ -1,10 +1,10 @@ -// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package org.jetbrains.plugins.terminal.block.completion.spec import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.project.Project import com.intellij.openapi.util.Key -import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.io.OSAgnosticPathUtil import com.intellij.terminal.completion.spec.ShellFileInfo import com.intellij.terminal.completion.spec.ShellRuntimeContext import org.jetbrains.annotations.ApiStatus @@ -51,7 +51,7 @@ suspend fun ShellRuntimeContext.getChildFiles( private suspend fun ShellRuntimeContext.getChildFilesReworked(path: String, onlyDirectories: Boolean): List { check(isReworkedTerminal) - val adjustedPath = FileUtil.expandUserHome(path) + val adjustedPath = OSAgnosticPathUtil.expandUserHome(path) val absolutePath = try { val nioPath = Path(adjustedPath) if (nioPath.isAbsolute) { @@ -92,4 +92,4 @@ private suspend fun ShellRuntimeContext.getChildFilesExp(path: String, onlyDirec ShellFileInfoImpl(it.removeSuffix(separator.toString()), type) } .toList() -} \ No newline at end of file +} diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/runner/LocalShellIntegrationInjector.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/runner/LocalShellIntegrationInjector.java index e0b1c9183fbf..0ed38943dbcf 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/runner/LocalShellIntegrationInjector.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/runner/LocalShellIntegrationInjector.java @@ -9,8 +9,8 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.NioFiles; +import com.intellij.openapi.util.io.OSAgnosticPathUtil; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.platform.eel.EelDescriptor; @@ -262,7 +262,7 @@ public final class LocalShellIntegrationInjector { if (idx >= 0) { arguments.remove(idx); if (idx < arguments.size()) { - String userRcFile = FileUtil.expandUserHome(arguments.get(idx)); + String userRcFile = OSAgnosticPathUtil.expandUserHome(arguments.get(idx)); // do not set the same RC file path to avoid sourcing recursion if (!userRcFile.equals(rcFilePath)) { envs.put(JEDITERM_USER_RCFILE, userRcFile);