diff --git a/Directory.Build.props b/Directory.Build.props index 5caf712761..32aa0164a9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -143,6 +143,10 @@ + + + + diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/IO/WindowsFileExplorer.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/IO/WindowsFileExplorer.cs index 923cb47418..ae067258f7 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/IO/WindowsFileExplorer.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/IO/WindowsFileExplorer.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE.md file in the project root for more information. using System.Runtime.InteropServices; -using Path = Microsoft.IO.Path; namespace Microsoft.VisualStudio.IO; diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/CreateFileFromTemplateService.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/CreateFileFromTemplateService.cs index 9061c2bfd1..28d39bbd44 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/CreateFileFromTemplateService.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/CreateFileFromTemplateService.cs @@ -35,12 +35,20 @@ public async Task CreateFileAsync(string templateFile, string path) Requires.NotNull(templateFile); Requires.NotNullOrEmpty(path); - string directoryName = Path.GetDirectoryName(path); string fileName = Path.GetFileName(path); + string? directoryName = Path.GetDirectoryName(path); + + if (directoryName is null) + { + return false; + } string? templateLanguage = await GetTemplateLanguageAsync(); + if (string.IsNullOrEmpty(templateLanguage)) + { return false; + } await _projectVsServices.ThreadingService.SwitchToUIThread(); diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/LanguageServices/Handlers/CompileItemHandler.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/LanguageServices/Handlers/CompileItemHandler.cs index c037c05a93..41e2dfa659 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/LanguageServices/Handlers/CompileItemHandler.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/LanguageServices/Handlers/CompileItemHandler.cs @@ -43,7 +43,7 @@ IEnumerable GetFilePaths(BuildOptions options) protected override void AddToContext(IWorkspaceProjectContext context, string fullPath, IImmutableDictionary metadata, bool isActiveContext, IManagedProjectDiagnosticOutputService logger) { - string[]? folderNames = FileItemServices.GetLogicalFolderNames(Path.GetDirectoryName(Project.FullPath), fullPath, metadata); + string[]? folderNames = FileItemServices.GetLogicalFolderNames(Path.GetDirectoryName(Project.FullPath)!, fullPath, metadata); logger.WriteLine("Adding source file '{0}'", fullPath); context.AddSourceFile(fullPath, isInCurrentContext: isActiveContext, folderNames: folderNames); diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Rename/FileMoveNotificationListener.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Rename/FileMoveNotificationListener.cs index d46edf61fc..a21531d6d4 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Rename/FileMoveNotificationListener.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Rename/FileMoveNotificationListener.cs @@ -11,7 +11,6 @@ using Microsoft.VisualStudio.Threading; // Debug collides with Microsoft.VisualStudio.ProjectSystem.VS.Debug using DiagDebug = System.Diagnostics.Debug; -using Path = System.IO.Path; using static Microsoft.CodeAnalysis.Rename.Renamer; namespace Microsoft.VisualStudio.ProjectSystem.VS.Rename; @@ -75,7 +74,13 @@ public async Task OnBeforeFilesMovedAsync(IReadOnlyCollection ite } // Get the relative folder path from the project to the destination. - string destinationFolderPath = Path.GetDirectoryName(_unconfiguredProject.MakeRelative(itemToMove.Destination)); + string? destinationFolderPath = Path.GetDirectoryName(_unconfiguredProject.MakeRelative(itemToMove.Destination)); + + if ( (destinationFolderPath is null)) + { + continue; + } + string[] destinationFolders = destinationFolderPath.Split(Delimiter.Path, StringSplitOptions.RemoveEmptyEntries); // Since this rename only moves the location of the file to another directory, it will use the SyncNamespaceDocumentAction in Roslyn as the rename action within this set. diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Rename/RenamerProjectTreeActionHandler.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Rename/RenamerProjectTreeActionHandler.cs index 38c1c36986..3e0648741e 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Rename/RenamerProjectTreeActionHandler.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Rename/RenamerProjectTreeActionHandler.cs @@ -78,13 +78,14 @@ public override async Task RenameAsync(IProjectTreeActionHandlerContext context, Requires.NotNullOrEmpty(value); string? oldFilePath = node.FilePath; - string oldName = Path.GetFileNameWithoutExtension(oldFilePath); + string? oldName = Path.GetFileNameWithoutExtension(oldFilePath); string newFileWithExtension = value; CodeAnalysis.Project? project = GetCurrentProject(); await CpsFileRenameAsync(context, node, value); - if (project is null || + if (oldName is null || + project is null || await IsAutomationFunctionAsync() || node.IsFolder || _vsOnlineServices.ConnectedToVSOnline || diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Retargeting/DotNetReleasesProvider.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Retargeting/DotNetReleasesProvider.cs index 90ef55bf35..e5f259d3fb 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Retargeting/DotNetReleasesProvider.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Retargeting/DotNetReleasesProvider.cs @@ -4,7 +4,6 @@ using Microsoft.VisualStudio.Linq; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Threading; -using Path = Microsoft.IO.Path; namespace Microsoft.VisualStudio.ProjectSystem.VS.Retargeting; diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Retargeting/ProjectRetargetHandler.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Retargeting/ProjectRetargetHandler.cs index 5246f56afc..204c5321a2 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Retargeting/ProjectRetargetHandler.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Retargeting/ProjectRetargetHandler.cs @@ -6,7 +6,6 @@ using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.Threading; using IFileSystem = Microsoft.VisualStudio.IO.IFileSystem; -using Path = Microsoft.IO.Path; namespace Microsoft.VisualStudio.ProjectSystem.VS.Retargeting; diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Setup/DotNetEnvironment.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Setup/DotNetEnvironment.cs index 4ed5c81b06..1e9449a8d3 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Setup/DotNetEnvironment.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Setup/DotNetEnvironment.cs @@ -69,7 +69,7 @@ public bool IsSdkInstalled(string sdkVersion) registryKey, "InstallLocation"); - if (!string.IsNullOrEmpty(installLocation)) + if (!Strings.IsNullOrEmpty(installLocation)) { string dotnetExePath = Path.Combine(installLocation, "dotnet.exe"); if (_fileSystem.FileExists(dotnetExePath)) diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/TempPE/DesignTimeInputsChangeTracker.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/TempPE/DesignTimeInputsChangeTracker.cs index da7a3b4139..1f7a0bda97 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/TempPE/DesignTimeInputsChangeTracker.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/TempPE/DesignTimeInputsChangeTracker.cs @@ -196,6 +196,12 @@ internal void ProcessDataflowChanges(IProjectVersionedValue GetAssemblyPath(); private string? GetAssemblyPath() => Path is not null - ? System.IO.Path.GetFullPath(System.IO.Path.Combine(Framework.Path, Path)) + ? Microsoft.IO.Path.GetFullPath(Microsoft.IO.Path.Combine(Framework.Path, Path)) : null; private sealed class BrowseObject(FrameworkReferenceAssemblyItem item) : LocalizableProperties diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/BuildUpToDateCheck.FileSystemOperationAggregator.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/BuildUpToDateCheck.FileSystemOperationAggregator.cs index e90ad7068f..afc7a368c0 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/BuildUpToDateCheck.FileSystemOperationAggregator.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/BuildUpToDateCheck.FileSystemOperationAggregator.cs @@ -169,7 +169,7 @@ public void AddCopy(string source, string destination) if (destinationInfo is null) { // Ensure the destination directory actually exists on disk - _fileSystem.CreateDirectory(Path.GetDirectoryName(destination)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(destination)!); } // TODO add retry logic in case of failed copies? MSBuild does this with CopyRetryCount and CopyRetryDelayMilliseconds diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/BuildUpToDateCheck.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/BuildUpToDateCheck.cs index fc9d3147e4..d45174b4c4 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/BuildUpToDateCheck.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/BuildUpToDateCheck.cs @@ -722,7 +722,7 @@ private bool CheckCopyToOutputDirectoryItems(Log log, UpToDateCheckImplicitConfi { ITimestampCache timestampCache = solutionBuildContext.CopyItemTimestamps; - string outputFullPath = Path.Combine(state.MSBuildProjectDirectory, state.OutputRelativeOrFullPath); + string outputFullPath = Path.Combine(state.MSBuildProjectDirectory!, state.OutputRelativeOrFullPath!); Log.Scope? scope1 = null; @@ -1074,7 +1074,7 @@ private async Task IsUpToDateInternalAsync( var configuredFileSystemOperations = new ConfiguredFileSystemOperationAggregator(fileSystemOperations, isBuildAccelerationEnabled, copyInfo.TargetsWithoutReferenceAssemblies); - string outputFullPath = Path.Combine(implicitState.MSBuildProjectDirectory, implicitState.OutputRelativeOrFullPath); + string outputFullPath = Path.Combine(implicitState.MSBuildProjectDirectory!, implicitState.OutputRelativeOrFullPath!); copyItemPaths.UnionWith(implicitState.ProjectCopyData.CopyItems.Select(copyItem => Path.Combine(outputFullPath, copyItem.RelativeTargetPath))); diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/LaunchSettingsProvider.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/LaunchSettingsProvider.cs index fbe2cc24c2..559e6cfe55 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/LaunchSettingsProvider.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/LaunchSettingsProvider.cs @@ -563,7 +563,9 @@ protected async Task EnsureSettingsFolderAsync() { string fileName = await GetLaunchSettingsFilePathAsync(); - string parentPath = Path.GetDirectoryName(fileName); + string? parentPath = Path.GetDirectoryName(fileName); + + Assumes.NotNull(parentPath); _fileSystem.CreateDirectory(parentPath); } diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/ProjectTreeProviderExtensions.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/ProjectTreeProviderExtensions.cs index 7491a59a93..c75a471879 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/ProjectTreeProviderExtensions.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/ProjectTreeProviderExtensions.cs @@ -40,7 +40,12 @@ internal static class ProjectTreeProviderExtensions string? projectFilePath = provider.GetPath(target.Root); - string rootPath = Path.GetDirectoryName(projectFilePath); + string? rootPath = Path.GetDirectoryName(projectFilePath); + + if (rootPath is null) + { + return null; + } return Path.Combine(rootPath, relativePath); } diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/SpecialFileProviders/AppDesignerFolderSpecialFileProvider.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/SpecialFileProviders/AppDesignerFolderSpecialFileProvider.cs index 01b24cd924..f45eab1d81 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/SpecialFileProviders/AppDesignerFolderSpecialFileProvider.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/SpecialFileProviders/AppDesignerFolderSpecialFileProvider.cs @@ -40,7 +40,7 @@ public AppDesignerFolderSpecialFileProvider(IPhysicalProjectTree projectTree, Pr return null; string? folderName = await GetDefaultAppDesignerFolderNameAsync(); - if (string.IsNullOrEmpty(folderName)) + if (Strings.IsNullOrEmpty(folderName)) return null; // Developer has set the AppDesigner path to empty return Path.Combine(projectPath, folderName); diff --git a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Tree/Order/TreeItemOrderPropertyProvider.cs b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Tree/Order/TreeItemOrderPropertyProvider.cs index 25bbaf4de6..d46dccd149 100644 --- a/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Tree/Order/TreeItemOrderPropertyProvider.cs +++ b/src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Tree/Order/TreeItemOrderPropertyProvider.cs @@ -24,7 +24,13 @@ private static string[] GetPathComponents(string evaluatedInclude) private static string[] GetPathFolders(string path) { - return GetPathComponents(Path.GetDirectoryName(path)); + string? evaluatedInclude = Path.GetDirectoryName(path); + if (evaluatedInclude is null) + { + return []; + } + + return GetPathComponents(evaluatedInclude); } /// diff --git a/tests/Microsoft.VisualStudio.ProjectSystem.Managed.TestServices/ProjectSystem/ProjectTreeProvider.cs b/tests/Microsoft.VisualStudio.ProjectSystem.Managed.TestServices/ProjectSystem/ProjectTreeProvider.cs index 33e88d9526..d9d3005365 100644 --- a/tests/Microsoft.VisualStudio.ProjectSystem.Managed.TestServices/ProjectSystem/ProjectTreeProvider.cs +++ b/tests/Microsoft.VisualStudio.ProjectSystem.Managed.TestServices/ProjectSystem/ProjectTreeProvider.cs @@ -68,7 +68,7 @@ public Task CanRenameAsync(IProjectTree node) if (target.IsRoot()) return string.Empty; - return Path.Combine(GetAddNewItemDirectory(target.Parent!), target.Caption); + return Path.Combine(GetAddNewItemDirectory(target.Parent!)!, target.Caption); } public string? GetPath(IProjectTree node) diff --git a/tests/Microsoft.VisualStudio.ProjectSystem.Managed.UnitTests/Utilities/RepoUtil.cs b/tests/Microsoft.VisualStudio.ProjectSystem.Managed.UnitTests/Utilities/RepoUtil.cs index 548f30af51..37e8e2a9b5 100644 --- a/tests/Microsoft.VisualStudio.ProjectSystem.Managed.UnitTests/Utilities/RepoUtil.cs +++ b/tests/Microsoft.VisualStudio.ProjectSystem.Managed.UnitTests/Utilities/RepoUtil.cs @@ -17,10 +17,10 @@ public static string FindRepoRootPath() if (_root is null) { // Start with this DLL's location - string path = typeof(RepoUtil).Assembly.Location; + string? path = typeof(RepoUtil).Assembly.Location; // Walk up the tree until we find the 'artifacts' folder - while (!Path.GetFileName(path).Equals("artifacts", StringComparisons.Paths)) + while (Path.GetFileName(path)?.Equals("artifacts", StringComparisons.Paths) is false) { path = Path.GetDirectoryName(path); } @@ -29,6 +29,8 @@ public static string FindRepoRootPath() _root = Path.GetDirectoryName(path); } + Assumes.NotNull(_root); + return _root; } } diff --git a/tests/Microsoft.VisualStudio.ProjectSystem.Managed.VS.UnitTests/ProjectSystem/VS/Rules/DependencyRuleTests.cs b/tests/Microsoft.VisualStudio.ProjectSystem.Managed.VS.UnitTests/ProjectSystem/VS/Rules/DependencyRuleTests.cs index 6e6774212b..6628a1a52b 100644 --- a/tests/Microsoft.VisualStudio.ProjectSystem.Managed.VS.UnitTests/ProjectSystem/VS/Rules/DependencyRuleTests.cs +++ b/tests/Microsoft.VisualStudio.ProjectSystem.Managed.VS.UnitTests/ProjectSystem/VS/Rules/DependencyRuleTests.cs @@ -273,7 +273,7 @@ public static IEnumerable GetResolvedAndUnresolvedDependencyRulePairs( { string unresolvedName = Path.GetFileNameWithoutExtension(unresolvedPath); string resolvedName = "Resolved" + unresolvedName; - string resolvedPath = Path.Combine(Path.GetDirectoryName(unresolvedPath), resolvedName + ".xaml"); + string resolvedPath = Path.Combine(Path.GetDirectoryName(unresolvedPath)!, resolvedName + ".xaml"); Assert.Contains(resolvedPath, resolvedPaths); diff --git a/tests/Microsoft.VisualStudio.ProjectSystem.Managed.VS.UnitTests/ProjectSystem/VS/Rules/XamlRuleTestBase.cs b/tests/Microsoft.VisualStudio.ProjectSystem.Managed.VS.UnitTests/ProjectSystem/VS/Rules/XamlRuleTestBase.cs index 8b75a887a2..a761c2b8a4 100644 --- a/tests/Microsoft.VisualStudio.ProjectSystem.Managed.VS.UnitTests/ProjectSystem/VS/Rules/XamlRuleTestBase.cs +++ b/tests/Microsoft.VisualStudio.ProjectSystem.Managed.VS.UnitTests/ProjectSystem/VS/Rules/XamlRuleTestBase.cs @@ -24,7 +24,7 @@ public abstract class XamlRuleTestBase foreach ((string basePath, Type assemblyExporterType) in projects) { - string path = string.IsNullOrEmpty(suffix) ? basePath : Path.Combine(basePath, suffix); + string path = Strings.IsNullOrEmpty(suffix) ? basePath : Path.Combine(basePath, suffix); if (Directory.Exists(path)) {