/ src / modules / cmdpal / Tests / Microsoft.CmdPal.Ext.Bookmarks.UnitTests / BookmarkResolverTests.Quoted.cs
BookmarkResolverTests.Quoted.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Collections.Generic; 7 using System.IO; 8 using System.Threading.Tasks; 9 using Microsoft.CmdPal.Ext.Bookmarks.Helpers; 10 using Microsoft.VisualStudio.TestTools.UnitTesting; 11 12 namespace Microsoft.CmdPal.Ext.Bookmarks.UnitTests; 13 14 public partial class BookmarkResolverTests 15 { 16 [DataTestMethod] 17 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.MixedQuotesScenarios), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 18 public async Task Quoted_ValidateMixedQuotesScenarios(PlaceholderClassificationCase c) => await RunShared(c: c); 19 20 [DataTestMethod] 21 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.EscapedQuotes), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 22 public async Task Quoted_ValidateEscapedQuotes(PlaceholderClassificationCase c) => await RunShared(c: c); 23 24 [DataTestMethod] 25 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.PartialMalformedQuotes), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 26 public async Task Quoted_ValidatePartialMalformedQuotes(PlaceholderClassificationCase c) => await RunShared(c: c); 27 28 [DataTestMethod] 29 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.EnvironmentVariablesWithQuotes), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 30 public async Task Quoted_ValidateEnvironmentVariablesWithQuotes(PlaceholderClassificationCase c) => await RunShared(c: c); 31 32 [DataTestMethod] 33 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.ShellProtocolPathsWithQuotes), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 34 public async Task Quoted_ValidateShellProtocolPathsWithQuotes(PlaceholderClassificationCase c) => await RunShared(c: c); 35 36 [DataTestMethod] 37 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.CommandFlagsAndOptions), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 38 public async Task Quoted_ValidateCommandFlagsAndOptions(PlaceholderClassificationCase c) => await RunShared(c: c); 39 40 [DataTestMethod] 41 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.NetworkPathsUnc), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 42 public async Task Quoted_ValidateNetworkPathsUnc(PlaceholderClassificationCase c) => await RunShared(c: c); 43 44 [DataTestMethod] 45 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.RelativePathsWithQuotes), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 46 public async Task Quoted_ValidateRelativePathsWithQuotes(PlaceholderClassificationCase c) => await RunShared(c: c); 47 48 [DataTestMethod] 49 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.EmptyAndWhitespaceCases), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 50 public async Task Quoted_ValidateEmptyAndWhitespaceCases(PlaceholderClassificationCase c) => await RunShared(c: c); 51 52 [DataTestMethod] 53 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.RealWorldCommandScenarios), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 54 public async Task Quoted_ValidateRealWorldCommandScenarios(PlaceholderClassificationCase c) => await RunShared(c: c); 55 56 [DataTestMethod] 57 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.SpecialCharactersInPaths), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 58 public async Task Quoted_ValidateSpecialCharactersInPaths(PlaceholderClassificationCase c) => await RunShared(c: c); 59 60 [DataTestMethod] 61 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.QuotedPathsCurrentlyBroken), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 62 public async Task Quoted_ValidateQuotedPathsCurrentlyBroken(PlaceholderClassificationCase c) => await RunShared(c: c); 63 64 [DataTestMethod] 65 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.QuotedPathsInCommands), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 66 public async Task Quoted_ValidateQuotedPathsInCommands(PlaceholderClassificationCase c) => await RunShared(c: c); 67 68 [DataTestMethod] 69 [DynamicData(dynamicDataSourceName: nameof(QuotedClassificationData.QuotedAumid), dynamicDataDeclaringType: typeof(QuotedClassificationData), DynamicDataDisplayName = nameof(FromCase))] 70 public async Task Quoted_ValidateQuotedUwpAppAumidCommands(PlaceholderClassificationCase c) => await RunShared(c: c); 71 72 public static class QuotedClassificationData 73 { 74 public static IEnumerable<object[]> MixedQuotesScenarios() => 75 [ 76 [ 77 new PlaceholderClassificationCase( 78 Name: "Executable with quoted argument", 79 Input: "C:\\Windows\\notepad.exe \"C:\\my file.txt\"", 80 ExpectSuccess: true, 81 ExpectedKind: CommandKind.FileExecutable, 82 ExpectedTarget: "C:\\Windows\\notepad.exe", 83 ExpectedArguments: "\"C:\\my file.txt\"", 84 ExpectedLaunch: LaunchMethod.ShellExecute, 85 ExpectedIsPlaceholder: false) 86 ], 87 [ 88 new PlaceholderClassificationCase( 89 Name: "App with quoted argument containing spaces", 90 Input: "app.exe \"argument with spaces\"", 91 ExpectSuccess: true, 92 ExpectedKind: CommandKind.Unknown, 93 ExpectedTarget: "app.exe", 94 ExpectedArguments: "\"argument with spaces\"", 95 ExpectedLaunch: LaunchMethod.ShellExecute, 96 ExpectedIsPlaceholder: false) 97 ], 98 [ 99 new PlaceholderClassificationCase( 100 Name: "Tool with input flag and quoted file", 101 Input: "C:\\tool.exe -input \"data file.txt\"", 102 ExpectSuccess: true, 103 ExpectedKind: CommandKind.FileExecutable, 104 ExpectedTarget: "C:\\tool.exe", 105 ExpectedArguments: "-input \"data file.txt\"", 106 ExpectedLaunch: LaunchMethod.ShellExecute, 107 ExpectedIsPlaceholder: false) 108 ], 109 [ 110 new PlaceholderClassificationCase( 111 Name: "Multiple quoted arguments after path", 112 Input: "\"C:\\Program Files\\app.exe\" -file \"C:\\data\\input.txt\" -output \"C:\\results\\output.txt\"", 113 ExpectSuccess: true, 114 ExpectedKind: CommandKind.FileExecutable, 115 ExpectedTarget: "C:\\Program Files\\app.exe", 116 ExpectedArguments: "-file \"C:\\data\\input.txt\" -output \"C:\\results\\output.txt\"", 117 ExpectedLaunch: LaunchMethod.ShellExecute, 118 ExpectedIsPlaceholder: false) 119 ], 120 [ 121 new PlaceholderClassificationCase( 122 Name: "Command with two quoted paths", 123 Input: "cmd /c \"C:\\First Path\\tool.exe\" \"C:\\Second Path\\file.txt\"", 124 ExpectSuccess: true, 125 ExpectedKind: CommandKind.PathCommand, 126 ExpectedTarget: "C:\\Windows\\system32\\cmd.EXE", 127 ExpectedArguments: "/c \"C:\\First Path\\tool.exe\" \"C:\\Second Path\\file.txt\"", 128 ExpectedLaunch: LaunchMethod.ShellExecute, 129 ExpectedIsPlaceholder: false) 130 ] 131 ]; 132 133 public static IEnumerable<object[]> EscapedQuotes() => 134 [ 135 [ 136 new PlaceholderClassificationCase( 137 Name: "Path with escaped quotes in folder name", 138 Input: "C:\\Windows\\\\\\\"System32\\\\\\\"CatRoot\\\\", 139 ExpectSuccess: true, 140 ExpectedKind: CommandKind.Unknown, 141 ExpectedTarget: "C:\\Windows\\\\\\\"System32\\\\\\\"CatRoot\\\\", 142 ExpectedLaunch: LaunchMethod.ShellExecute, 143 ExpectedIsPlaceholder: false) 144 ], 145 [ 146 new PlaceholderClassificationCase( 147 Name: "Quoted path with trailing escaped quote", 148 Input: "\"C:\\Windows\\\\\\\"\"", 149 ExpectSuccess: true, 150 ExpectedKind: CommandKind.Directory, 151 ExpectedTarget: "C:\\Windows\\", 152 ExpectedLaunch: LaunchMethod.ExplorerOpen, 153 ExpectedIsPlaceholder: false) 154 ] 155 ]; 156 157 public static IEnumerable<object[]> PartialMalformedQuotes() => 158 [ 159 [ 160 new PlaceholderClassificationCase( 161 Name: "Unclosed quote at start", 162 Input: "\"C:\\Program Files\\app.exe", 163 ExpectSuccess: true, 164 ExpectedKind: CommandKind.FileExecutable, 165 ExpectedTarget: "C:\\Program Files\\app.exe", 166 ExpectedLaunch: LaunchMethod.ShellExecute, 167 ExpectedIsPlaceholder: false) 168 ], 169 [ 170 new PlaceholderClassificationCase( 171 Name: "Quote in middle of unquoted path", 172 Input: "C:\\Some\\\"Path\\file.txt", 173 ExpectSuccess: true, 174 ExpectedKind: CommandKind.FileDocument, 175 ExpectedTarget: "C:\\Some\\\"Path\\file.txt", 176 ExpectedLaunch: LaunchMethod.ShellExecute, 177 ExpectedIsPlaceholder: false) 178 ], 179 [ 180 new PlaceholderClassificationCase( 181 Name: "Unclosed quote - never ends", 182 Input: "\"Starts quoted but never ends", 183 ExpectSuccess: true, 184 ExpectedKind: CommandKind.Unknown, 185 ExpectedTarget: "Starts quoted but never ends", 186 ExpectedLaunch: LaunchMethod.ShellExecute, 187 ExpectedIsPlaceholder: false) 188 ] 189 ]; 190 191 public static IEnumerable<object[]> EnvironmentVariablesWithQuotes() => 192 [ 193 [ 194 new PlaceholderClassificationCase( 195 Name: "Quoted environment variable path with spaces", 196 Input: "\"%ProgramFiles%\\MyApp\\app.exe\"", 197 ExpectSuccess: true, 198 ExpectedKind: CommandKind.FileExecutable, 199 ExpectedTarget: Path.Combine(path1: Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "MyApp", "app.exe"), 200 ExpectedLaunch: LaunchMethod.ShellExecute, 201 ExpectedIsPlaceholder: false) 202 ], 203 [ 204 new PlaceholderClassificationCase( 205 Name: "Quoted USERPROFILE with document path", 206 Input: "\"%USERPROFILE%\\Documents\\file with spaces.txt\"", 207 ExpectSuccess: true, 208 ExpectedKind: CommandKind.FileDocument, 209 ExpectedTarget: Path.Combine(path1: Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Documents", "file with spaces.txt"), 210 ExpectedLaunch: LaunchMethod.ShellExecute, 211 ExpectedIsPlaceholder: false) 212 ], 213 [ 214 new PlaceholderClassificationCase( 215 Name: "Environment variable with trailing args", 216 Input: "\"%ProgramFiles%\\App\" with args", 217 ExpectSuccess: true, 218 ExpectedKind: CommandKind.Unknown, 219 ExpectedTarget: Path.Combine(path1: Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "App"), 220 ExpectedArguments: "with args", 221 ExpectedLaunch: LaunchMethod.ShellExecute, 222 ExpectedIsPlaceholder: false) 223 ], 224 [ 225 new PlaceholderClassificationCase( 226 Name: "Environment variable with trailing args", 227 Input: "%ProgramFiles%\\App with args", 228 ExpectSuccess: true, 229 ExpectedKind: CommandKind.Unknown, 230 ExpectedTarget: Path.Combine(path1: Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "App"), 231 ExpectedArguments: "with args", 232 ExpectedLaunch: LaunchMethod.ShellExecute, 233 ExpectedIsPlaceholder: false) 234 ], 235 ]; 236 237 public static IEnumerable<object[]> ShellProtocolPathsWithQuotes() => 238 [ 239 [ 240 new PlaceholderClassificationCase( 241 Name: "Quoted shell:Downloads", 242 Input: "\"shell:Downloads\"", 243 ExpectSuccess: true, 244 ExpectedKind: CommandKind.Directory, 245 ExpectedTarget: Path.Combine(path1: Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads"), 246 ExpectedLaunch: LaunchMethod.ExplorerOpen, 247 ExpectedIsPlaceholder: false) 248 ], 249 [ 250 new PlaceholderClassificationCase( 251 Name: "Quoted shell:Downloads with subpath", 252 Input: "\"shell:Downloads\\file.txt\"", 253 ExpectSuccess: true, 254 ExpectedKind: CommandKind.FileDocument, 255 ExpectedTarget: Path.Combine(path1: Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads", "file.txt"), 256 ExpectedLaunch: LaunchMethod.ShellExecute, 257 ExpectedIsPlaceholder: false) 258 ], 259 [ 260 new PlaceholderClassificationCase( 261 Name: "Shell Desktop with subpath", 262 Input: "shell:Desktop\\file.txt", 263 ExpectSuccess: true, 264 ExpectedKind: CommandKind.FileDocument, 265 ExpectedTarget: Path.Combine(path1: Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "file.txt"), 266 ExpectedLaunch: LaunchMethod.ShellExecute, 267 ExpectedIsPlaceholder: false) 268 ], 269 [ 270 new PlaceholderClassificationCase( 271 Name: "Quoted shell path with trailing text", 272 Input: "\"shell:Programs\" extra", 273 ExpectSuccess: true, 274 ExpectedKind: CommandKind.Directory, 275 ExpectedTarget: Path.Combine(paths: Environment.GetFolderPath(Environment.SpecialFolder.Programs)), 276 ExpectedLaunch: LaunchMethod.ExplorerOpen, 277 ExpectedIsPlaceholder: false) 278 ] 279 ]; 280 281 public static IEnumerable<object[]> CommandFlagsAndOptions() => 282 [ 283 [ 284 new PlaceholderClassificationCase( 285 Name: "Path followed by flag with quoted value", 286 Input: "C:\\app.exe -flag \"value\"", 287 ExpectSuccess: true, 288 ExpectedKind: CommandKind.FileExecutable, 289 ExpectedTarget: "C:\\app.exe", 290 ExpectedArguments: "-flag \"value\"", 291 ExpectedLaunch: LaunchMethod.ShellExecute, 292 ExpectedIsPlaceholder: false) 293 ], 294 [ 295 new PlaceholderClassificationCase( 296 Name: "Quoted tool with equals-style flag", 297 Input: "\"C:\\Program Files\\tool.exe\" --input=file.txt", 298 ExpectSuccess: true, 299 ExpectedKind: CommandKind.FileExecutable, 300 ExpectedTarget: "C:\\Program Files\\tool.exe", 301 ExpectedArguments: "--input=file.txt", 302 ExpectedLaunch: LaunchMethod.ShellExecute, 303 ExpectedIsPlaceholder: false) 304 ], 305 [ 306 new PlaceholderClassificationCase( 307 Name: "Path with slash option and quoted value", 308 Input: "C:\\tool.exe /option \"quoted value\"", 309 ExpectSuccess: true, 310 ExpectedKind: CommandKind.FileExecutable, 311 ExpectedTarget: "C:\\tool.exe", 312 ExpectedArguments: "/option \"quoted value\"", 313 ExpectedLaunch: LaunchMethod.ShellExecute, 314 ExpectedIsPlaceholder: false) 315 ], 316 [ 317 new PlaceholderClassificationCase( 318 Name: "Flag before quoted path", 319 Input: "--path \"C:\\Program Files\\app.exe\"", 320 ExpectSuccess: true, 321 ExpectedKind: CommandKind.Unknown, 322 ExpectedTarget: "--path", 323 ExpectedArguments: "\"C:\\Program Files\\app.exe\"", 324 ExpectedLaunch: LaunchMethod.ShellExecute, 325 ExpectedIsPlaceholder: false) 326 ] 327 ]; 328 329 public static IEnumerable<object[]> NetworkPathsUnc() => 330 [ 331 [ 332 new PlaceholderClassificationCase( 333 Name: "UNC path unquoted", 334 Input: "\\\\server\\share\\folder\\file.txt", 335 ExpectSuccess: true, 336 ExpectedKind: CommandKind.FileDocument, 337 ExpectedTarget: "\\\\server\\share\\folder\\file.txt", 338 ExpectedLaunch: LaunchMethod.ShellExecute, 339 ExpectedIsPlaceholder: false) 340 ], 341 [ 342 new PlaceholderClassificationCase( 343 Name: "Quoted UNC path with spaces", 344 Input: "\"\\\\server\\share with spaces\\file.txt\"", 345 ExpectSuccess: true, 346 ExpectedKind: CommandKind.FileDocument, 347 ExpectedTarget: "\\\\server\\share with spaces\\file.txt", 348 ExpectedLaunch: LaunchMethod.ShellExecute, 349 ExpectedIsPlaceholder: false) 350 ], 351 [ 352 new PlaceholderClassificationCase( 353 Name: "UNC path with trailing args", 354 Input: "\"\\\\server\\share\\\" with args", 355 ExpectSuccess: true, 356 ExpectedKind: CommandKind.Unknown, 357 ExpectedTarget: "\\\\server\\share\\", 358 ExpectedArguments: "with args", 359 ExpectedLaunch: LaunchMethod.ShellExecute, 360 ExpectedIsPlaceholder: false) 361 ], 362 [ 363 new PlaceholderClassificationCase( 364 Name: "Quoted UNC app with flag", 365 Input: "\"\\\\server\\My Share\\app.exe\" --flag", 366 ExpectSuccess: true, 367 ExpectedKind: CommandKind.FileExecutable, 368 ExpectedTarget: "\\\\server\\My Share\\app.exe", 369 ExpectedArguments: "--flag", 370 ExpectedLaunch: LaunchMethod.ShellExecute, 371 ExpectedIsPlaceholder: false) 372 ] 373 ]; 374 375 public static IEnumerable<object[]> RelativePathsWithQuotes() => 376 [ 377 [ 378 new PlaceholderClassificationCase( 379 Name: "Quoted relative current path", 380 Input: "\".\\file.txt\"", 381 ExpectSuccess: true, 382 ExpectedKind: CommandKind.FileDocument, 383 ExpectedTarget: Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "file.txt")), 384 ExpectedLaunch: LaunchMethod.ShellExecute, 385 ExpectedIsPlaceholder: false) 386 ], 387 [ 388 new PlaceholderClassificationCase( 389 Name: "Quoted relative parent path", 390 Input: "\"..\\parent folder\\file.txt\"", 391 ExpectSuccess: true, 392 ExpectedKind: CommandKind.FileDocument, 393 ExpectedTarget: Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "..", "parent folder", "file.txt")), 394 ExpectedLaunch: LaunchMethod.ShellExecute, 395 ExpectedIsPlaceholder: false) 396 ], 397 [ 398 new PlaceholderClassificationCase( 399 Name: "Quoted relative home folder", 400 Input: "\"~\\current folder\\app.exe\"", 401 ExpectSuccess: true, 402 ExpectedKind: CommandKind.FileExecutable, 403 ExpectedTarget: Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "current folder\\app.exe"), 404 ExpectedLaunch: LaunchMethod.ShellExecute, 405 ExpectedIsPlaceholder: false) 406 ] 407 ]; 408 409 public static IEnumerable<object[]> EmptyAndWhitespaceCases() => 410 [ 411 [ 412 new PlaceholderClassificationCase( 413 Name: "Empty string", 414 Input: string.Empty, 415 ExpectSuccess: true, 416 ExpectedKind: CommandKind.Unknown, 417 ExpectedTarget: string.Empty, 418 ExpectedLaunch: LaunchMethod.ShellExecute, 419 ExpectedIsPlaceholder: false) 420 ], 421 [ 422 new PlaceholderClassificationCase( 423 Name: "Only whitespace", 424 Input: " ", 425 ExpectSuccess: true, 426 ExpectedKind: CommandKind.Unknown, 427 ExpectedTarget: " ", 428 ExpectedLaunch: LaunchMethod.ShellExecute, 429 ExpectedIsPlaceholder: false) 430 ], 431 [ 432 new PlaceholderClassificationCase( 433 Name: "Just empty quotes", 434 Input: "\"\"", 435 ExpectSuccess: true, 436 ExpectedKind: CommandKind.Unknown, 437 ExpectedTarget: string.Empty, 438 ExpectedLaunch: LaunchMethod.ShellExecute, 439 ExpectedIsPlaceholder: false) 440 ], 441 [ 442 new PlaceholderClassificationCase( 443 Name: "Quoted single space", 444 Input: "\" \"", 445 ExpectSuccess: true, 446 ExpectedKind: CommandKind.Unknown, 447 ExpectedTarget: " ", 448 ExpectedLaunch: LaunchMethod.ShellExecute, 449 ExpectedIsPlaceholder: false) 450 ] 451 ]; 452 453 public static IEnumerable<object[]> RealWorldCommandScenarios() => 454 [ 455 #if CMDPAL_ENABLE_UNSAFE_TESTS 456 [ 457 new PlaceholderClassificationCase( 458 Name: "Git clone command with full exe path with quoted path", 459 Input: "\"C:\\Program Files\\Git\\bin\\git.exe\" clone repo", 460 ExpectSuccess: true, 461 ExpectedKind: CommandKind.FileExecutable, 462 ExpectedTarget: "C:\\Program Files\\Git\\bin\\git.exe", 463 ExpectedArguments: "clone repo", 464 ExpectedLaunch: LaunchMethod.ShellExecute, 465 ExpectedIsPlaceholder: false) 466 ], 467 [ 468 new PlaceholderClassificationCase( 469 Name: "Git clone command with quoted path", 470 Input: "git clone repo", 471 ExpectSuccess: true, 472 ExpectedKind: CommandKind.PathCommand, 473 ExpectedTarget: "C:\\Program Files\\Git\\cmd\\git.EXE", 474 ExpectedArguments: "clone repo", 475 ExpectedLaunch: LaunchMethod.ShellExecute, 476 ExpectedIsPlaceholder: false) 477 ], 478 [ 479 new PlaceholderClassificationCase( 480 Name: "Visual Studio devenv with solution", 481 Input: "\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Preview\\Common7\\IDE\\devenv.exe\" solution.sln", 482 ExpectSuccess: true, 483 ExpectedKind: CommandKind.FileExecutable, 484 ExpectedTarget: "C:\\Program Files\\Microsoft Visual Studio\\2022\\Preview\\Common7\\IDE\\devenv.exe", 485 ExpectedArguments: "solution.sln", 486 ExpectedLaunch: LaunchMethod.ShellExecute, 487 ExpectedIsPlaceholder: false) 488 ], 489 [ 490 new PlaceholderClassificationCase( 491 Name: "Double-quoted Windows cmd pattern", 492 Input: "cmd /c \"\"C:\\Program Files\\app.exe\" arg1 arg2\"", 493 ExpectSuccess: true, 494 ExpectedKind: CommandKind.PathCommand, 495 ExpectedTarget: "C:\\Windows\\system32\\cmd.EXE", 496 ExpectedLaunch: LaunchMethod.ShellExecute, 497 ExpectedArguments: "/c \"\"C:\\Program Files\\app.exe\" arg1 arg2\"", 498 ExpectedIsPlaceholder: false) 499 ], 500 #endif 501 [ 502 new PlaceholderClassificationCase( 503 Name: "PowerShell script with execution policy", 504 Input: "powershell -ExecutionPolicy Bypass -File \"C:\\Scripts\\My Script.ps1\" -param \"value\"", 505 ExpectSuccess: true, 506 ExpectedKind: CommandKind.PathCommand, 507 ExpectedTarget: "C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\PowerShell.exe", 508 ExpectedArguments: "-ExecutionPolicy Bypass -File \"C:\\Scripts\\My Script.ps1\" -param \"value\"", 509 ExpectedLaunch: LaunchMethod.ShellExecute, 510 ExpectedIsPlaceholder: false) 511 ], 512 ]; 513 514 public static IEnumerable<object[]> SpecialCharactersInPaths() => 515 [ 516 [ 517 new PlaceholderClassificationCase( 518 Name: "Quoted path with square brackets", 519 Input: "\"C:\\Path\\file[1].txt\"", 520 ExpectSuccess: true, 521 ExpectedKind: CommandKind.FileDocument, 522 ExpectedTarget: "C:\\Path\\file[1].txt", 523 ExpectedLaunch: LaunchMethod.ShellExecute, 524 ExpectedIsPlaceholder: false) 525 ], 526 [ 527 new PlaceholderClassificationCase( 528 Name: "Quoted path with parentheses", 529 Input: "\"C:\\Folder (2)\\app.exe\"", 530 ExpectSuccess: true, 531 ExpectedKind: CommandKind.FileExecutable, 532 ExpectedTarget: "C:\\Folder (2)\\app.exe", 533 ExpectedLaunch: LaunchMethod.ShellExecute, 534 ExpectedIsPlaceholder: false) 535 ], 536 [ 537 new PlaceholderClassificationCase( 538 Name: "Quoted path with hyphens and underscores", 539 Input: "\"C:\\Path\\file_name-123.txt\"", 540 ExpectSuccess: true, 541 ExpectedKind: CommandKind.FileDocument, 542 ExpectedTarget: "C:\\Path\\file_name-123.txt", 543 ExpectedLaunch: LaunchMethod.ShellExecute, 544 ExpectedIsPlaceholder: false) 545 ] 546 ]; 547 548 public static IEnumerable<object[]> QuotedPathsCurrentlyBroken() => 549 [ 550 [ 551 new PlaceholderClassificationCase( 552 Name: "Quoted path with spaces - complete path", 553 Input: "\"C:\\Program Files\\MyApp\\app.exe\"", 554 ExpectSuccess: true, 555 ExpectedKind: CommandKind.FileExecutable, 556 ExpectedTarget: "C:\\Program Files\\MyApp\\app.exe", 557 ExpectedArguments: string.Empty, 558 ExpectedLaunch: LaunchMethod.ShellExecute, 559 ExpectedIsPlaceholder: false) 560 ], 561 [ 562 new PlaceholderClassificationCase( 563 Name: "Quoted path with spaces in user folder", 564 Input: "\"C:\\Users\\John Doe\\Documents\\file.txt\"", 565 ExpectSuccess: true, 566 ExpectedKind: CommandKind.FileDocument, 567 ExpectedTarget: "C:\\Users\\John Doe\\Documents\\file.txt", 568 ExpectedArguments: string.Empty, 569 ExpectedLaunch: LaunchMethod.ShellExecute, 570 ExpectedIsPlaceholder: false) 571 ], 572 [ 573 new PlaceholderClassificationCase( 574 Name: "Quoted path with trailing arguments", 575 Input: "\"C:\\Program Files\\app.exe\" --flag", 576 ExpectSuccess: true, 577 ExpectedKind: CommandKind.FileExecutable, 578 ExpectedTarget: "C:\\Program Files\\app.exe", 579 ExpectedArguments: "--flag", 580 ExpectedLaunch: LaunchMethod.ShellExecute, 581 ExpectedIsPlaceholder: false) 582 ], 583 [ 584 new PlaceholderClassificationCase( 585 Name: "Quoted path with multiple arguments", 586 Input: "\"C:\\My Documents\\file.txt\" -output result.txt", 587 ExpectSuccess: true, 588 ExpectedKind: CommandKind.FileDocument, 589 ExpectedTarget: "C:\\My Documents\\file.txt", 590 ExpectedArguments: "-output result.txt", 591 ExpectedLaunch: LaunchMethod.ShellExecute, 592 ExpectedIsPlaceholder: false) 593 ], 594 [ 595 new PlaceholderClassificationCase( 596 Name: "Quoted path with trailing flag and value", 597 Input: "\"C:\\Tools\\converter.exe\" input.txt output.txt", 598 ExpectSuccess: true, 599 ExpectedKind: CommandKind.FileExecutable, 600 ExpectedTarget: "C:\\Tools\\converter.exe", 601 ExpectedArguments: "input.txt output.txt", 602 ExpectedLaunch: LaunchMethod.ShellExecute, 603 ExpectedIsPlaceholder: false) 604 ] 605 ]; 606 607 public static IEnumerable<object[]> QuotedPathsInCommands() => 608 [ 609 [ 610 new PlaceholderClassificationCase( 611 Name: "cmd /c with quoted path", 612 Input: "cmd /c \"C:\\Program Files\\tool.exe\"", 613 ExpectSuccess: true, 614 ExpectedKind: CommandKind.PathCommand, 615 ExpectedTarget: "C:\\Windows\\system32\\cmd.exe", 616 ExpectedArguments: "/c \"C:\\Program Files\\tool.exe\"", 617 ExpectedLaunch: LaunchMethod.ShellExecute, 618 ExpectedIsPlaceholder: false) 619 ], 620 [ 621 new PlaceholderClassificationCase( 622 Name: "PowerShell with quoted script path", 623 Input: "powershell -File \"C:\\Scripts\\my script.ps1\"", 624 ExpectSuccess: true, 625 ExpectedKind: CommandKind.PathCommand, 626 ExpectedTarget: Path.Combine(path1: Environment.GetFolderPath(Environment.SpecialFolder.System), "WindowsPowerShell", "v1.0", path4: "powershell.exe"), 627 ExpectedArguments: "-File \"C:\\Scripts\\my script.ps1\"", 628 ExpectedLaunch: LaunchMethod.ShellExecute, 629 ExpectedIsPlaceholder: false) 630 ], 631 [ 632 new PlaceholderClassificationCase( 633 Name: "runas with quoted executable", 634 Input: "runas /user:admin \"C:\\Windows\\System32\\cmd.exe\"", 635 ExpectSuccess: true, 636 ExpectedKind: CommandKind.PathCommand, 637 ExpectedTarget: "C:\\Windows\\system32\\runas.exe", 638 ExpectedArguments: "/user:admin \"C:\\Windows\\System32\\cmd.exe\"", 639 ExpectedLaunch: LaunchMethod.ShellExecute, 640 ExpectedIsPlaceholder: false) 641 ] 642 ]; 643 644 public static IEnumerable<object[]> QuotedAumid() => 645 [ 646 [ 647 new PlaceholderClassificationCase( 648 Name: "Quoted UWP AUMID via AppsFolder", 649 Input: "\"shell:AppsFolder\\Microsoft.WindowsTerminal_8wekyb3d8bbwe!App\"", 650 ExpectSuccess: true, 651 ExpectedKind: CommandKind.Aumid, 652 ExpectedTarget: "shell:AppsFolder\\Microsoft.WindowsTerminal_8wekyb3d8bbwe!App", 653 ExpectedLaunch: LaunchMethod.ActivateAppId, 654 ExpectedIsPlaceholder: false), 655 ], 656 [ 657 new PlaceholderClassificationCase( 658 Name: "Quoted UWP AUMID with AppsFolder prefix and argument", 659 Input: "\"shell:AppsFolder\\Microsoft.WindowsTerminal_8wekyb3d8bbwe!App\" --maximized", 660 ExpectSuccess: true, 661 ExpectedKind: CommandKind.Aumid, 662 ExpectedTarget: "shell:AppsFolder\\Microsoft.WindowsTerminal_8wekyb3d8bbwe!App", 663 ExpectedArguments: "--maximized", 664 ExpectedLaunch: LaunchMethod.ActivateAppId, 665 ExpectedIsPlaceholder: false), 666 ], 667 ]; 668 } 669 }