├── .gitattributes ├── .gitignore ├── .gitmodules ├── GitInfo.txt ├── LICENSE ├── README.md ├── VisualStudio.AndroidX.Migration.Console ├── App.config ├── ConsoleProgress.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── VisualStudio.AndroidX.Migration.Console.csproj ├── VisualStudio.AndroidX.Migration.Core ├── Directory.Build.targets ├── MigrationRunner.cs ├── ProjectRewriter.cs ├── Rewriters │ ├── MigrationRewriter.cs │ ├── NamespaceRewriter.cs │ ├── SemanticRewriter.cs │ └── TypeRewriter.cs ├── TranslationResolver.cs ├── VisualStudio.AndroidX.Migration.Core.csproj └── xamarin.snk ├── VisualStudio.AndroidX.Migration.Test ├── NameTests.cs ├── NamespaceTests.cs ├── NullProgress.cs ├── ProjectTests.cs ├── ResolverTests.cs ├── TestBase.cs └── VisualStudio.AndroidX.Migration.Tests.csproj ├── VisualStudio.AndroidX.Migration.sln ├── azure-pipelines.yml └── build.cake /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.sh eol=lf 4 | gradlew eol=lf 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | tools 7 | !tools/packages.config 8 | .gradle 9 | output 10 | externals 11 | Resource.designer.cs 12 | 13 | # User-specific files 14 | *.suo 15 | *.user 16 | *.userosscache 17 | *.sln.docstates 18 | 19 | # User-specific files (MonoDevelop/Xamarin Studio) 20 | *.userprefs 21 | 22 | # Build results 23 | [Dd]ebug/ 24 | [Dd]ebugPublic/ 25 | [Rr]elease/ 26 | [Rr]eleases/ 27 | x64/ 28 | x86/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUNIT 47 | *.VisualState.xml 48 | TestResult.xml 49 | 50 | # Build Results of an ATL Project 51 | [Dd]ebugPS/ 52 | [Rr]eleasePS/ 53 | dlldata.c 54 | 55 | # Benchmark Results 56 | BenchmarkDotNet.Artifacts/ 57 | 58 | # .NET Core 59 | project.lock.json 60 | project.fragment.lock.json 61 | artifacts/ 62 | **/Properties/launchSettings.json 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_i.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *.log 88 | *.vspscc 89 | *.vssscc 90 | .builds 91 | *.pidb 92 | *.svclog 93 | *.scc 94 | 95 | # Chutzpah Test files 96 | _Chutzpah* 97 | 98 | # Visual C++ cache files 99 | ipch/ 100 | *.aps 101 | *.ncb 102 | *.opendb 103 | *.opensdf 104 | *.sdf 105 | *.cachefile 106 | *.VC.db 107 | *.VC.VC.opendb 108 | 109 | # Visual Studio profiler 110 | *.psess 111 | *.vsp 112 | *.vspx 113 | *.sap 114 | 115 | # Visual Studio Trace Files 116 | *.e2e 117 | 118 | # TFS 2012 Local Workspace 119 | $tf/ 120 | 121 | # Guidance Automation Toolkit 122 | *.gpState 123 | 124 | # ReSharper is a .NET coding add-in 125 | _ReSharper*/ 126 | *.[Rr]e[Ss]harper 127 | *.DotSettings.user 128 | 129 | # JustCode is a .NET coding add-in 130 | .JustCode 131 | 132 | # TeamCity is a build add-in 133 | _TeamCity* 134 | 135 | # DotCover is a Code Coverage Tool 136 | *.dotCover 137 | 138 | # AxoCover is a Code Coverage Tool 139 | .axoCover/* 140 | !.axoCover/settings.json 141 | 142 | # Visual Studio code coverage results 143 | *.coverage 144 | *.coveragexml 145 | 146 | # NCrunch 147 | _NCrunch_* 148 | .*crunch*.local.xml 149 | nCrunchTemp_* 150 | 151 | # MightyMoose 152 | *.mm.* 153 | AutoTest.Net/ 154 | 155 | # Web workbench (sass) 156 | .sass-cache/ 157 | 158 | # Installshield output folder 159 | [Ee]xpress/ 160 | 161 | # DocProject is a documentation generator add-in 162 | DocProject/buildhelp/ 163 | DocProject/Help/*.HxT 164 | DocProject/Help/*.HxC 165 | DocProject/Help/*.hhc 166 | DocProject/Help/*.hhk 167 | DocProject/Help/*.hhp 168 | DocProject/Help/Html2 169 | DocProject/Help/html 170 | 171 | # Click-Once directory 172 | publish/ 173 | 174 | # Publish Web Output 175 | *.[Pp]ublish.xml 176 | *.azurePubxml 177 | # Note: Comment the next line if you want to checkin your web deploy settings, 178 | # but database connection strings (with potential passwords) will be unencrypted 179 | *.pubxml 180 | *.publishproj 181 | 182 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 183 | # checkin your Azure Web App publish settings, but sensitive information contained 184 | # in these scripts will be unencrypted 185 | PublishScripts/ 186 | 187 | # NuGet Packages 188 | *.nupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | 214 | # Visual Studio cache files 215 | # files ending in .cache can be ignored 216 | *.[Cc]ache 217 | # but keep track of directories ending in .cache 218 | !*.[Cc]ache/ 219 | 220 | # Others 221 | ClientBin/ 222 | ~$* 223 | *~ 224 | *.dbmdl 225 | *.dbproj.schemaview 226 | *.jfm 227 | *.pfx 228 | *.publishsettings 229 | orleans.codegen.cs 230 | 231 | # Including strong name files can present a security risk 232 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 233 | #*.snk 234 | 235 | # Since there are multiple workflows, uncomment next line to ignore bower_components 236 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 237 | #bower_components/ 238 | 239 | # RIA/Silverlight projects 240 | Generated_Code/ 241 | 242 | # Backup & report files from converting an old project file 243 | # to a newer Visual Studio version. Backup files are not needed, 244 | # because we have git ;-) 245 | _UpgradeReport_Files/ 246 | Backup*/ 247 | UpgradeLog*.XML 248 | UpgradeLog*.htm 249 | ServiceFabricBackup/ 250 | *.rptproj.bak 251 | 252 | # SQL Server files 253 | *.mdf 254 | *.ldf 255 | *.ndf 256 | 257 | # Business Intelligence projects 258 | *.rdl.data 259 | *.bim.layout 260 | *.bim_*.settings 261 | *.rptproj.rsuser 262 | 263 | # Microsoft Fakes 264 | FakesAssemblies/ 265 | 266 | # GhostDoc plugin setting file 267 | *.GhostDoc.xml 268 | 269 | # Node.js Tools for Visual Studio 270 | .ntvs_analysis.dat 271 | node_modules/ 272 | 273 | # Visual Studio 6 build log 274 | *.plg 275 | 276 | # Visual Studio 6 workspace options file 277 | *.opt 278 | 279 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 280 | *.vbw 281 | 282 | # Visual Studio LightSwitch build output 283 | **/*.HTMLClient/GeneratedArtifacts 284 | **/*.DesktopClient/GeneratedArtifacts 285 | **/*.DesktopClient/ModelManifest.xml 286 | **/*.Server/GeneratedArtifacts 287 | **/*.Server/ModelManifest.xml 288 | _Pvt_Extensions 289 | 290 | # Paket dependency manager 291 | .paket/paket.exe 292 | paket-files/ 293 | 294 | # FAKE - F# Make 295 | .fake/ 296 | 297 | # JetBrains Rider 298 | *.sln.iml 299 | 300 | # CodeRush 301 | .cr/ 302 | 303 | # Python Tools for Visual Studio (PTVS) 304 | __pycache__/ 305 | *.pyc 306 | 307 | # Cake - Uncomment if you are using it 308 | # tools/** 309 | # !tools/packages.config 310 | 311 | # Tabs Studio 312 | *.tss 313 | 314 | # Telerik's JustMock configuration file 315 | *.jmconfig 316 | 317 | # BizTalk build output 318 | *.btp.cs 319 | *.btm.cs 320 | *.odx.cs 321 | *.xsd.cs 322 | 323 | # OpenCover UI analysis results 324 | OpenCover/ 325 | 326 | # Azure Stream Analytics local run output 327 | ASALocalRun/ 328 | 329 | # MSBuild Binary and Structured Log 330 | *.binlog 331 | 332 | # NVidia Nsight GPU debugger configuration file 333 | *.nvuser 334 | 335 | # MFractors (Xamarin productivity tool) working folder 336 | .mfractor/ 337 | 338 | # Compiled class file 339 | *.class 340 | 341 | # Log file 342 | *.log 343 | 344 | # BlueJ files 345 | *.ctxt 346 | 347 | # Mobile Tools for Java (J2ME) 348 | .mtj.tmp/ 349 | 350 | # Package Files # 351 | *.jar 352 | *.war 353 | *.nar 354 | *.ear 355 | *.zip 356 | *.tar.gz 357 | *.rar 358 | 359 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 360 | hs_err_pid* 361 | 362 | *.DS_Store 363 | 364 | # Built application files 365 | *.apk 366 | *.ap_ 367 | *.aab 368 | 369 | # Files for the ART/Dalvik VM 370 | *.dex 371 | 372 | # Java class files 373 | *.class 374 | 375 | # Generated files 376 | bin/ 377 | gen/ 378 | out/ 379 | 380 | # Gradle files 381 | .gradle/ 382 | build/ 383 | 384 | # Local configuration file (sdk path, etc) 385 | local.properties 386 | 387 | # Proguard folder generated by Eclipse 388 | proguard/ 389 | 390 | # Log Files 391 | *.log 392 | 393 | # Android Studio Navigation editor temp files 394 | .navigation/ 395 | 396 | # Android Studio captures folder 397 | captures/ 398 | 399 | # IntelliJ 400 | .idea/workspace.xml 401 | .idea/tasks.xml 402 | .idea/gradle.xml 403 | .idea/assetWizardSettings.xml 404 | .idea/dictionaries 405 | .idea/libraries 406 | .idea/caches 407 | # Android Studio 3 in .gitignore file. 408 | .idea/caches/build_file_checksums.ser 409 | .idea/modules.xml 410 | 411 | # Keystore files 412 | # Uncomment the following lines if you do not want to check your keystore files in. 413 | #*.jks 414 | #*.keystore 415 | 416 | # External native build folder generated in Android Studio 2.2 and later 417 | .externalNativeBuild 418 | 419 | # Google Services (e.g. APIs or Firebase) 420 | # google-services.json 421 | 422 | # Freeline 423 | freeline.py 424 | freeline/ 425 | freeline_project_description.json 426 | 427 | # fastlane 428 | fastlane/report.xml 429 | fastlane/Preview.html 430 | fastlane/screenshots 431 | fastlane/test_output 432 | fastlane/readme.md 433 | 434 | # Version control 435 | vcs.xml 436 | 437 | # lint 438 | lint/intermediates/ 439 | lint/generated/ 440 | lint/outputs/ 441 | lint/tmp/ 442 | # lint/reports/ 443 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "externals/Java.Interop"] 2 | path = externals/Java.Interop 3 | url = https://github.com/xamarin/java.interop 4 | -------------------------------------------------------------------------------- /GitInfo.txt: -------------------------------------------------------------------------------- 1 | 1.0.9 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MOVED: https://github.com/xamarin/AndroidX/tree/master/source/migration 2 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Console/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Console/ConsoleProgress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace VisualStudio.AndroidX.Migration 8 | { 9 | class ConsoleProgress : IProgress 10 | { 11 | public void Report(string value) 12 | { 13 | Console.WriteLine(value); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Console/Program.cs: -------------------------------------------------------------------------------- 1 | using Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace VisualStudio.AndroidX.Migration 9 | { 10 | class Program 11 | { 12 | static void Main(string[] args) 13 | { 14 | var runner = new MigrationRunner(new ConsoleProgress()); 15 | runner.MigrateSolution(args[0]); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Console/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Console")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Console")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("29e0e329-b35e-4a6c-b24d-e4700c6ba58f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Console/VisualStudio.AndroidX.Migration.Console.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {29E0E329-B35E-4A6C-B24D-E4700C6BA58F} 8 | Exe 9 | Console 10 | Console 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 16.0.461 56 | 57 | 58 | 16.0.461 59 | 60 | 61 | 1.2.2 62 | 63 | 64 | 16.0.461 65 | 66 | 67 | 16.0.461 68 | 69 | 70 | 71 | 72 | {297b120f-de08-4460-bce6-5b2a74535c2d} 73 | VisualStudio.AndroidX.Migration.Core 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Core/Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | true 5 | 6 | 7 | 8 | $(NoWarn);NU5105 9 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 23 | 24 | 26 | 27 | 28 | 29 | $(GitSemVerMajor).$(GitSemVerMinor).$(GitSemVerPatch) 30 | $(GitSemVerDashLabel)+@(VersionMetadata -> '%(Identity)', '-') 31 | 32 | $(VersionPrefix) 33 | $(AssemblyVersion) 34 | $(VersionPrefix)$(VersionSuffix) 35 | $(InformationalVersion) 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Core/MigrationRunner.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.MSBuild; 3 | using System; 4 | using System.Linq; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using VisualStudio.AndroidX.Migration; 8 | using System.Reflection; 9 | 10 | namespace Core 11 | { 12 | public class MigrationRunner 13 | { 14 | private TranslationResolver resolver; 15 | private IProgress progress; 16 | 17 | public MigrationRunner(IProgress progress) 18 | { 19 | var androidDirectory = Path.Combine(Path.GetDirectoryName(typeof(MigrationRunner).Assembly.Location), "Assemblies", "Android"); 20 | var androidXDirectory = Path.Combine(Path.GetDirectoryName(typeof(MigrationRunner).Assembly.Location), "Assemblies", "AndroidX"); 21 | 22 | resolver = new TranslationResolver(null, null); 23 | this.progress = progress; 24 | } 25 | 26 | public void MigrateSolution(string solutionPath, bool addMigrationNuget = false, bool migrateCode = false) 27 | { 28 | var workspace = MSBuildWorkspace.Create(); 29 | workspace.WorkspaceFailed += (s,e) => { Console.WriteLine(e.Diagnostic.Message); }; 30 | var solution = workspace.OpenSolutionAsync(solutionPath).Result; 31 | 32 | var newSolution = solution; 33 | 34 | progress.Report("Migrating Solution"); 35 | 36 | foreach (var project in solution.Projects) 37 | { 38 | progress.Report(project.Name); 39 | newSolution = MigrateProject(project, newSolution, addMigrationNuget, migrateCode); 40 | } 41 | 42 | workspace.TryApplyChanges(newSolution); 43 | } 44 | 45 | public Solution MigrateProject(Project project, Solution solution, bool addMigrationNuget, bool migrateCode) 46 | { 47 | //foreach (var reference in project.MetadataReferences) 48 | // if (resolver.Nugets.Keys.Contains(Path.GetFileNameWithoutExtension(reference.Display)) && !resolver.AndroidAssemblies.Any(a => Path.GetFileName(a.CodeBase) == Path.GetFileName(reference.Display))) 49 | // resolver.AndroidAssemblies.Add(Assembly.ReflectionOnlyLoadFrom(reference.Display)); 50 | //solution = MigrateDocuments(project, solution); 51 | MigrateNugets(project, addMigrationNuget); 52 | //foreach (var reference in project.MetadataReferences) 53 | // if (resolver.Nugets.Values.Any(v => v.Key == (Path.GetFileNameWithoutExtension(reference.Display))) && !resolver.AndroidXAssemblies.Any(a => Path.GetFileName(a.CodeBase) == Path.GetFileName(reference.Display))) 54 | // resolver.AndroidXAssemblies.Add(Assembly.ReflectionOnlyLoadFrom(reference.Display)); 55 | //solution = PostProcessProject(project, solution); 56 | Jetify(project); 57 | 58 | return solution; 59 | } 60 | 61 | private Solution MigrateDocuments(Project project, Solution solution) 62 | { 63 | var rewriters = new List 64 | { 65 | new TypeRewriter(resolver, progress), 66 | new SemanticRewriter(resolver, progress) 67 | }; 68 | 69 | foreach (var document in project.Documents) 70 | { 71 | solution = MigrateDocument(document, solution, rewriters); 72 | } 73 | 74 | return solution; 75 | } 76 | 77 | private void MigrateNugets(Project project, bool addMigrationNuget) 78 | { 79 | var rewriter = new ProjectRewriter(resolver, progress); 80 | rewriter.RewriteProject(project.FilePath, addMigrationNuget); 81 | } 82 | 83 | private Solution PostProcessProject(Project project, Solution solution) 84 | { 85 | var rewriters = new List 86 | { 87 | new NamespaceRewriter(resolver, progress) 88 | }; 89 | 90 | foreach (var document in project.Documents) 91 | { 92 | solution = MigrateDocument(document, solution, rewriters); 93 | } 94 | 95 | return solution; 96 | } 97 | 98 | private Solution MigrateDocument(Document document, Solution solution, List rewriters) 99 | { 100 | foreach(var rewriter in rewriters) 101 | { 102 | solution = rewriter.Visit(solution, document); 103 | } 104 | 105 | return solution; 106 | } 107 | 108 | private void Jetify(Project project) 109 | { 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Core/ProjectRewriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Linq; 5 | using System.Xml; 6 | using System.IO; 7 | 8 | namespace VisualStudio.AndroidX.Migration 9 | { 10 | public class ProjectRewriter 11 | { 12 | private ITranslationResolver resolver; 13 | private IProgress progress; 14 | 15 | public ProjectRewriter(ITranslationResolver resolver, IProgress progress) 16 | { 17 | this.resolver = resolver; 18 | this.progress = progress; 19 | } 20 | 21 | public void RewriteProject(string projectFileName, bool addMigrationNuget) 22 | { 23 | var xml = RewriteCSProj(File.ReadAllText(projectFileName), addMigrationNuget); 24 | File.WriteAllText(projectFileName, xml); 25 | } 26 | 27 | public string RewriteCSProj(string csproj, bool addMigrationNuget = false) 28 | { 29 | bool hasAndroidNugets = false; 30 | var doc = new XmlDocument(); 31 | doc.PreserveWhitespace = true; 32 | doc.LoadXml(csproj); 33 | var itemGroups = doc.GetElementsByTagName("ItemGroup"); 34 | foreach (var group in itemGroups.OfType()) 35 | { 36 | var references = group.ChildNodes.OfType().Where(c => c.Name == "PackageReference"); 37 | foreach (var reference in references) 38 | { 39 | var androidNuget = reference.Attributes["Include"].InnerText; 40 | if (resolver.Nugets.ContainsKey(androidNuget)) 41 | { 42 | hasAndroidNugets = true; 43 | progress?.Report($"Migrating Nuget {androidNuget}"); 44 | reference.Attributes["Include"].InnerText = resolver.Nugets[reference.Attributes["Include"].InnerText].Key; 45 | var androidXVersion = resolver.Nugets[androidNuget].Value; 46 | if (reference.HasAttribute("Version")) 47 | { 48 | reference.Attributes["Version"].InnerText = androidXVersion; 49 | } 50 | else 51 | { 52 | var version = reference.ChildNodes.OfType().FirstOrDefault(n => n.Name == "Version"); 53 | if (version != null) 54 | { 55 | version.InnerText = androidXVersion; 56 | } 57 | else 58 | { 59 | var versionAttribute = doc.CreateAttribute("Version"); 60 | versionAttribute.InnerText = androidXVersion; 61 | reference.Attributes.Append(versionAttribute); 62 | } 63 | } 64 | } 65 | } 66 | if (addMigrationNuget && hasAndroidNugets) 67 | { 68 | addMigrationNuget = false; 69 | var node = doc.CreateNode(XmlNodeType.Element, "PackageReference", references.First().NamespaceURI); 70 | var includeAttribute = doc.CreateAttribute("Include"); 71 | includeAttribute.Value = "Xamarin.AndroidX.Migration"; 72 | node.Attributes.Append(includeAttribute); 73 | var versionAttribute = doc.CreateAttribute("Version"); 74 | versionAttribute.Value = "1.0.0-preview03"; 75 | node.Attributes.Append(versionAttribute); 76 | group.AppendChild(node); 77 | } 78 | } 79 | return doc.InnerXml; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Core/Rewriters/MigrationRewriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.CodeAnalysis; 3 | using Microsoft.CodeAnalysis.CSharp; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace VisualStudio.AndroidX.Migration 8 | { 9 | public abstract class MigrationRewriter : CSharpSyntaxRewriter, IRewriter 10 | { 11 | public SemanticModel Semantic { get; set; } 12 | protected ITranslationResolver resolver; 13 | private IProgress progress; 14 | 15 | internal abstract bool UsesSemantic { get; } 16 | 17 | public MigrationRewriter(ITranslationResolver resolver, IProgress progress) 18 | { 19 | this.resolver = resolver; 20 | this.progress = progress; 21 | } 22 | 23 | public Solution Visit(Solution solution, Document document) 24 | { 25 | if (UsesSemantic) 26 | this.Semantic = document.Project.GetCompilationAsync().Result.GetSemanticModel(document.GetSyntaxRootAsync().Result.SyntaxTree); 27 | var root = this.Visit(document.GetSyntaxRootAsync().Result); 28 | return solution.WithDocumentSyntaxRoot(document.Id, root); 29 | } 30 | 31 | internal bool TryGetValue(string name, out string typeName) 32 | { 33 | typeName = string.Empty; 34 | if (resolver.FullTypeNames.ContainsKey(name)) 35 | { 36 | typeName = resolver.FullTypeNames[name]; 37 | return true; 38 | } 39 | 40 | return false; 41 | } 42 | 43 | } 44 | 45 | public interface IRewriter 46 | { 47 | Solution Visit(Solution solution, Document document); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Core/Rewriters/NamespaceRewriter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace VisualStudio.AndroidX.Migration 9 | { 10 | public class NamespaceRewriter : MigrationRewriter 11 | { 12 | private ITranslationResolver assemblyResolver; 13 | 14 | internal override bool UsesSemantic => false; 15 | 16 | public NamespaceRewriter(ITranslationResolver assemblyResolver, IProgress progress) : base(assemblyResolver, progress) 17 | { 18 | this.assemblyResolver = assemblyResolver; 19 | } 20 | 21 | public override SyntaxNode VisitUsingDirective(UsingDirectiveSyntax node) 22 | { 23 | var name = node.Name.WithoutTrivia().ToFullString(); 24 | if (assemblyResolver.Namespaces.ContainsKey(name)) 25 | return base.VisitUsingDirective(node.WithName(SyntaxFactory.ParseName(assemblyResolver.Namespaces[name]) 26 | .WithLeadingTrivia(node.Name.GetLeadingTrivia()) 27 | .WithTrailingTrivia(node.Name.GetTrailingTrivia()))); 28 | else 29 | return base.VisitUsingDirective(node); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Core/Rewriters/SemanticRewriter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Microsoft.CodeAnalysis.CSharp; 3 | using Microsoft.CodeAnalysis.CSharp.Syntax; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace VisualStudio.AndroidX.Migration 9 | { 10 | public class SemanticRewriter : MigrationRewriter 11 | { 12 | private ITranslationResolver assemblyResolver; 13 | 14 | internal override bool UsesSemantic => true; 15 | 16 | public SemanticRewriter(ITranslationResolver assemblyResolver, IProgress progress) : base(assemblyResolver, progress) 17 | { 18 | this.assemblyResolver = assemblyResolver; 19 | } 20 | 21 | public override SyntaxNode VisitQualifiedName(QualifiedNameSyntax node) 22 | { 23 | var symbol = Semantic.GetSymbolInfo(node); 24 | if (symbol.Symbol != null && node.ToFullString() != symbol.Symbol.ToDisplayString()) 25 | return SyntaxFactory.ParseName(symbol.Symbol.ToDisplayString()) 26 | .WithLeadingTrivia(node.GetLeadingTrivia()) 27 | .WithTrailingTrivia(node.GetTrailingTrivia()); 28 | else 29 | return base.VisitQualifiedName(node); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Core/Rewriters/TypeRewriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.CSharp; 6 | using Microsoft.CodeAnalysis.CSharp.Syntax; 7 | 8 | namespace VisualStudio.AndroidX.Migration 9 | { 10 | public class TypeRewriter : MigrationRewriter 11 | { 12 | private ITranslationResolver assemblyResolver; 13 | 14 | internal override bool UsesSemantic => false; 15 | 16 | public TypeRewriter(ITranslationResolver assemblyResolver, IProgress progress) : base(assemblyResolver, progress) 17 | { 18 | this.assemblyResolver = assemblyResolver; 19 | } 20 | 21 | public override SyntaxNode VisitQualifiedName(QualifiedNameSyntax node) 22 | { 23 | var name = node.WithoutTrivia().ToFullString(); 24 | if (TryGetValue(name, out var typeName)) 25 | return SyntaxFactory.ParseName(typeName) 26 | .WithLeadingTrivia(node.GetLeadingTrivia()) 27 | .WithTrailingTrivia(node.GetTrailingTrivia()); 28 | else 29 | return base.VisitQualifiedName(node); 30 | } 31 | 32 | public override SyntaxNode VisitAttribute(AttributeSyntax node) 33 | { 34 | var typeName = string.Empty; 35 | var identifier = node.Name + "Attribute"; 36 | if (TryGetValue(identifier, out typeName)) 37 | { 38 | if (typeName.EndsWith("Attribute")) 39 | { 40 | typeName = typeName.Remove(typeName.Length - 9); 41 | return node.WithName(SyntaxFactory.ParseName(typeName) 42 | .WithLeadingTrivia(node.GetLeadingTrivia()) 43 | .WithTrailingTrivia(node.GetTrailingTrivia())); 44 | } 45 | } 46 | return base.VisitAttribute(node); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Core/TranslationResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Text; 7 | 8 | namespace VisualStudio.AndroidX.Migration 9 | { 10 | public class TranslationResolver : ITranslationResolver 11 | { 12 | int SupportNamespace = 0; 13 | int SupportTypeName = 1; 14 | int AndroidXNamespace = 2; 15 | int AndroidXTypeName = 3; 16 | 17 | int SupportNuget = 2; 18 | int AndroidXNuget = 3; 19 | int AndroidXVersion = 4; 20 | 21 | public TranslationResolver(IList androidAssemblyLocations, IList androidXAssemblyLocations) 22 | { 23 | Namespaces = new Dictionary(); 24 | FullTypeNames = new Dictionary(); 25 | Nugets = new Dictionary>(); 26 | 27 | using (var mapping = this.GetType().Assembly.GetManifestResourceStream("VisualStudio.AndroidX.Migration.Core.Resources.androidx-mapping.csv")) 28 | { 29 | using (var reader = new StreamReader(mapping)) 30 | { 31 | var line = reader.ReadLine(); //skip first line 32 | while ((line = reader.ReadLine()) != null) 33 | { 34 | var values = line.Split(','); 35 | if (values[SupportNamespace] != string.Empty && values[AndroidXNamespace] != string.Empty) 36 | { 37 | if (!Namespaces.Any(n => n.Key == values[SupportNamespace])) 38 | Namespaces.Add(values[SupportNamespace], values[AndroidXNamespace]); 39 | 40 | if (!FullTypeNames.Any(t => t.Key == $"{values[SupportNamespace]}.{values[SupportTypeName]}")) 41 | FullTypeNames.Add($"{values[SupportNamespace]}.{values[SupportTypeName]}", $"{values[AndroidXNamespace]}.{values[AndroidXTypeName]}"); 42 | } 43 | 44 | } 45 | } 46 | } 47 | 48 | AndroidAssemblies = AddAssemblies(androidAssemblyLocations ?? new List(), AndroidAssemblies); 49 | AndroidXAssemblies = AddAssemblies(androidXAssemblyLocations ?? new List(), AndroidXAssemblies); 50 | 51 | using (var nugets = this.GetType().Assembly.GetManifestResourceStream("VisualStudio.AndroidX.Migration.Core.Resources.androidx-assemblies.csv")) 52 | { 53 | using (var reader = new StreamReader(nugets)) 54 | { 55 | var line = reader.ReadLine(); //skip first line 56 | while ((line = reader.ReadLine()) != null) 57 | { 58 | var values = line.Split(','); 59 | if (!Nugets.Any(n => n.Key == values[SupportNuget])) 60 | Nugets.Add(values[SupportNuget], new KeyValuePair(values[AndroidXNuget], values[AndroidXVersion])); 61 | } 62 | } 63 | } 64 | } 65 | 66 | public IList AddAssemblies(IList assemblyLocations, IList assemblies) 67 | { 68 | assemblies = assemblies ?? new List(); 69 | foreach (var assembly in assemblyLocations) 70 | assemblies.Add(Assembly.ReflectionOnlyLoadFrom(assembly)); 71 | 72 | return assemblies; 73 | } 74 | 75 | public IList AndroidAssemblies { get; private set; } 76 | 77 | public IList AndroidXAssemblies { get; private set; } 78 | 79 | public Dictionary Namespaces { get; private set; } 80 | 81 | public Dictionary FullTypeNames { get; private set; } 82 | 83 | public Dictionary> Nugets { get; private set; } 84 | } 85 | 86 | public interface ITranslationResolver 87 | { 88 | IList AndroidAssemblies { get; } 89 | IList AndroidXAssemblies { get; } 90 | 91 | Dictionary Namespaces { get; } 92 | Dictionary FullTypeNames { get; } 93 | 94 | Dictionary> Nugets { get; } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Core/VisualStudio.AndroidX.Migration.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | VisualStudio.AndroidX.Migration.Core 5 | VisualStudio.AndroidX.Migration 6 | net472 7 | 8 | Xamarin.VisualStudio.AndroidX.Migration 9 | Migration Tools for Xamarin AndroidX (Visual Studio) 10 | This package provides a Roslyn based migrator to be used in Visual Studio and Visual Studio for Mac. 11 | This package provides a Roslyn based migrator to be used in Visual Studio and Visual Studio for Mac. 12 | Xamarin.AndroidX Xamarin Android Support AndroidX Migration VS VSMac 13 | Microsoft 14 | Microsoft 15 | https://go.microsoft.com/fwlink/?linkid=2099353 16 | https://go.microsoft.com/fwlink/?linkid=2099438 17 | true 18 | © Microsoft Corporation. All rights reserved. 19 | true 20 | xamarin.snk 21 | false 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | Resources\androidx-assemblies.csv 34 | PreserveNewest 35 | 36 | 37 | Resources\androidx-mapping.csv 38 | PreserveNewest 39 | 40 | 41 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Core/xamarin.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xamarin/XamarinAndroidXMigration/425ee3d0c0f67d7993780b0e03f9a227bd327ece/VisualStudio.AndroidX.Migration.Core/xamarin.snk -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Test/NameTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using Microsoft.CodeAnalysis; 6 | using Xunit; 7 | 8 | namespace VisualStudio.AndroidX.Migration 9 | { 10 | public class NameTests : TestBase 11 | { 12 | [Fact] 13 | public void when_defining_fully_qualified_fields_then_replace_namespace() 14 | { 15 | var solution = CreateSolution(@" 16 | using System; 17 | 18 | namespace ClassLibrary1 19 | { 20 | public class Class1 21 | { 22 | Android.Arch.Lifecycle.ViewModelProviders modelProvider; 23 | } 24 | }"); 25 | 26 | var methodFixer = new TypeRewriter(resolver, new NullProgress()); 27 | solution = methodFixer.Visit(solution, GetFirstDocument(solution)); 28 | 29 | var root = GetText(solution); 30 | 31 | Assert.Contains("AndroidX.Lifecycle.ViewModelProviders", root); 32 | Assert.DoesNotContain("Android.Arch.Lifecycle.ViewModelProviders", root); 33 | } 34 | 35 | [Fact] 36 | public void when_defining_fully_qualified_properties_then_replace_namespace() 37 | { 38 | var file = @" 39 | using System; 40 | 41 | namespace ClassLibrary1 42 | { 43 | public class Class1 44 | { 45 | Android.Arch.Lifecycle.ViewModelProviders modelProvider { get; set; } 46 | } 47 | }"; 48 | 49 | var solution = CreateSolution(file); 50 | 51 | var methodFixer = new TypeRewriter(resolver, new NullProgress()); 52 | solution = methodFixer.Visit(solution, GetFirstDocument(solution)); 53 | 54 | var root = GetText(solution); 55 | 56 | Assert.Contains("AndroidX.Lifecycle.ViewModelProviders", root); 57 | Assert.DoesNotContain("Android.Arch.Lifecycle.ViewModelProviders", root); 58 | } 59 | 60 | [Fact] 61 | public void when_defining_fully_qualified_parameters_then_replace_namespace() 62 | { 63 | var solution = CreateSolution(@" 64 | using System; 65 | 66 | namespace ClassLibrary1 67 | { 68 | public class Class1 69 | { 70 | public void Method(Android.Arch.Lifecycle.ViewModelProviders modelProvider) 71 | { 72 | } 73 | } 74 | }"); 75 | 76 | var methodFixer = new TypeRewriter(resolver, new NullProgress()); 77 | solution = methodFixer.Visit(solution, GetFirstDocument(solution)); 78 | 79 | var root = GetText(solution); 80 | 81 | Assert.Contains("public void Method(AndroidX.Lifecycle.ViewModelProviders modelProvider)", root); 82 | Assert.DoesNotContain("public void Method(Android.Arch.Lifecycle.ViewModelProviders modelProvider)", root); 83 | } 84 | 85 | [Fact] 86 | public void when_defining_fully_qualified_return_then_replace_namespace() 87 | { 88 | var solution = CreateSolution(@" 89 | using System; 90 | 91 | namespace ClassLibrary1 92 | { 93 | public class Class1 94 | { 95 | public Android.Arch.Lifecycle.ViewModelProviders Method() 96 | { 97 | return null; 98 | } 99 | } 100 | }"); 101 | 102 | var methodFixer = new TypeRewriter(resolver, new NullProgress()); 103 | solution = methodFixer.Visit(solution, GetFirstDocument(solution)); 104 | 105 | var root = GetText(solution); 106 | 107 | Assert.Contains("AndroidX.Lifecycle.ViewModelProviders", root); 108 | Assert.DoesNotContain("Android.Arch.Lifecycle.ViewModelProviders", root); 109 | } 110 | 111 | 112 | [Fact] 113 | public void when_defining_attribute_then_replace_attribute_name() 114 | { 115 | var solution = CreateSolution(@" 116 | using System; 117 | 118 | namespace ClassLibrary1 119 | { 120 | [Android.Support.V17.Leanback.Widget.Visibility] 121 | public class Class1 122 | { 123 | } 124 | }"); 125 | 126 | var methodFixer = new TypeRewriter(resolver, new NullProgress()); 127 | solution = methodFixer.Visit(solution, GetFirstDocument(solution)); 128 | 129 | var root = GetText(solution); 130 | 131 | Assert.Contains("AndroidX.Leanback.Widget.Visibility", root); 132 | Assert.DoesNotContain("Android.Support.V17.Leanback.Widget.Visibility", root); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Test/NamespaceTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using Xunit; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace VisualStudio.AndroidX.Migration 11 | { 12 | public class NamespaceTests : TestBase 13 | { 14 | [Fact] 15 | public void when_defining_namespaces_then_replace_namespace() 16 | { 17 | var solution = CreateSolution(@" 18 | using System; 19 | using Android.Arch.Lifecycle; 20 | 21 | namespace ClassLibrary1 22 | { 23 | public class Class1 24 | { 25 | } 26 | }"); 27 | 28 | var methodFixer = new NamespaceRewriter(resolver, new NullProgress()); 29 | solution = methodFixer.Visit(solution, GetFirstDocument(solution)); 30 | 31 | var root = GetText(solution); 32 | 33 | Assert.Contains("using AndroidX.Lifecycle;", root); 34 | Assert.DoesNotContain("using Android.Arch.Lifecycle;", root); 35 | } 36 | 37 | [Fact] 38 | public void when_defining_aliased_namespaces_then_replace_namespace() 39 | { 40 | var solution = CreateSolution(@" 41 | using System; 42 | using life = Android.Arch.Lifecycle; 43 | 44 | namespace ClassLibrary1 45 | { 46 | public class Class1 47 | { 48 | } 49 | }"); 50 | 51 | var methodFixer = new NamespaceRewriter(resolver, new NullProgress()); 52 | solution = methodFixer.Visit(solution, GetFirstDocument(solution)); 53 | 54 | var root = GetText(solution); 55 | 56 | Assert.Contains("using life = AndroidX.Lifecycle;", root); 57 | Assert.DoesNotContain("using life = Android.Arch.Lifecycle;", root); 58 | } 59 | 60 | [Fact] 61 | public void when_defining_aliased_namespaces_then_fully_qualify_if_needed() 62 | { 63 | var solution = CreateSolution(@" 64 | using System; 65 | using support = Android.Support; 66 | 67 | namespace ClassLibrary1 68 | { 69 | public class MainActivity : support.V7.App.AppCompatActivity 70 | { 71 | } 72 | }"); 73 | 74 | var methodFixer = new SemanticRewriter(resolver, new NullProgress()); 75 | var typeFixer = new TypeRewriter(resolver, new NullProgress()); 76 | solution = methodFixer.Visit(solution, GetFirstDocument(solution)); 77 | solution = typeFixer.Visit(solution, GetFirstDocument(solution)); 78 | 79 | var root = GetText(solution); 80 | 81 | Assert.Contains(": AndroidX.AppCompat.App.AppCompatActivity", root); 82 | Assert.DoesNotContain(": support.V7.App.AppCompatActivity", root); 83 | } 84 | 85 | [Fact] 86 | public void when_defining_types_then_dont_break_fully_qualified() 87 | { 88 | var solution = CreateSolution(@" 89 | using System; 90 | 91 | namespace ClassLibrary1 92 | { 93 | public class MainActivity : Android.Support.V7.App.AppCompatActivity 94 | { 95 | } 96 | }"); 97 | 98 | var methodFixer = new SemanticRewriter(resolver, new NullProgress()); 99 | solution = methodFixer.Visit(solution, GetFirstDocument(solution)); 100 | 101 | var root = GetText(solution); 102 | 103 | Assert.Contains(": Android.Support.V7.App.AppCompatActivity", root); 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Test/NullProgress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace VisualStudio.AndroidX.Migration 8 | { 9 | class NullProgress : IProgress 10 | { 11 | public void Report(string value) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Test/ProjectTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using Xunit; 5 | 6 | namespace VisualStudio.AndroidX.Migration 7 | { 8 | public class ProjectTests 9 | { 10 | [Fact] 11 | public void when_nuget_version_is_not_inlined_replace_it() 12 | { 13 | var csproj = versionedCsProj; 14 | 15 | var resolver = new TranslationResolver(new List(), new List { }); 16 | var projectFixer = new ProjectRewriter(resolver, new NullProgress()); 17 | 18 | csproj = projectFixer.RewriteCSProj(csproj); 19 | 20 | Assert.Contains(@"", csproj); 21 | Assert.DoesNotContain(@"28.0.0.1", csproj); 22 | Assert.Contains(@"1.0.0-preview02", csproj); //replace version number 23 | Assert.Contains(@"27.0.0.1", csproj); //don't remove version for xamarin.essentials 24 | } 25 | 26 | [Fact] 27 | public void when_include_migration_then_migration_is_present() 28 | { 29 | var csproj = sampleCsProj; 30 | 31 | var resolver = new TranslationResolver(new List(), new List { }); 32 | var projectFixer = new ProjectRewriter(resolver, new NullProgress()); 33 | 34 | csproj = projectFixer.RewriteCSProj(csproj, true); 35 | 36 | Assert.Contains(@"", csproj); 37 | } 38 | 39 | [Fact] 40 | public void when_nuget_is_àppcompat_replace_with_androidx() 41 | { 42 | var csproj = sampleCsProj; 43 | 44 | var resolver = new TranslationResolver(new List(), new List { }); 45 | var projectFixer = new ProjectRewriter(resolver, new NullProgress()); 46 | 47 | csproj = projectFixer.RewriteCSProj(csproj); 48 | 49 | Assert.Contains(@"", csproj); 50 | } 51 | 52 | 53 | [Fact] 54 | public void when_version_is_inline_replace_inline() 55 | { 56 | var csproj = sampleCsProj; 57 | 58 | var resolver = new TranslationResolver(new List(), new List { }); 59 | var projectFixer = new ProjectRewriter(resolver, new NullProgress()); 60 | 61 | csproj = projectFixer.RewriteCSProj(csproj); 62 | 63 | Assert.Contains(@"", csproj); 64 | } 65 | 66 | [Fact] 67 | public void in_poolmath_replace_androidx() 68 | { 69 | var csproj = poolMathCsproj; 70 | 71 | var resolver = new TranslationResolver(new List(), new List { }); 72 | var projectFixer = new ProjectRewriter(resolver, new NullProgress()); 73 | 74 | csproj = projectFixer.RewriteCSProj(csproj); 75 | 76 | Assert.Contains(@" 77 | 1.2.0.2 78 | ", csproj); 79 | } 80 | 81 | [Fact] 82 | public void when_nuget_is_support_replace_with_androidx() 83 | { 84 | var csproj = sampleCsProj; 85 | 86 | var resolver = new TranslationResolver(new List(), new List { }); 87 | var projectFixer = new ProjectRewriter(resolver, new NullProgress()); 88 | 89 | csproj = projectFixer.RewriteCSProj(csproj); 90 | 91 | Assert.Contains(@"", csproj); 92 | } 93 | 94 | string sampleCsProj = 95 | @" 96 | 97 | 98 | Debug 99 | AnyCPU 100 | 8.0.30703 101 | 2.0 102 | {EA94CF80-A750-4881-9468-638D0472C6C9} 103 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 104 | {84dd83c5-0fe3-4294-9419-09e7c8ba324f} 105 | Library 106 | Properties 107 | App43 108 | App43 109 | 512 110 | True 111 | Resources\Resource.designer.cs 112 | Resource 113 | Off 114 | false 115 | v9.0 116 | Properties\AndroidManifest.xml 117 | Resources 118 | Assets 119 | true 120 | Xamarin.Android.Net.AndroidClientHandler 121 | 122 | 123 | True 124 | portable 125 | False 126 | bin\Debug\ 127 | DEBUG;TRACE 128 | prompt 129 | 4 130 | True 131 | None 132 | False 133 | 134 | 135 | True 136 | portable 137 | True 138 | bin\Release\ 139 | TRACE 140 | prompt 141 | 4 142 | true 143 | False 144 | SdkOnly 145 | True 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | Designer 168 | 169 | 170 | Designer 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 211 | "; 212 | 213 | 214 | string versionedCsProj = 215 | @" 216 | 217 | 218 | Debug 219 | AnyCPU 220 | 8.0.30703 221 | 2.0 222 | {EA94CF80-A750-4881-9468-638D0472C6C9} 223 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 224 | {84dd83c5-0fe3-4294-9419-09e7c8ba324f} 225 | Library 226 | Properties 227 | App43 228 | App43 229 | 512 230 | True 231 | Resources\Resource.designer.cs 232 | Resource 233 | Off 234 | false 235 | v9.0 236 | Properties\AndroidManifest.xml 237 | Resources 238 | Assets 239 | true 240 | Xamarin.Android.Net.AndroidClientHandler 241 | 242 | 243 | True 244 | portable 245 | False 246 | bin\Debug\ 247 | DEBUG;TRACE 248 | prompt 249 | 4 250 | True 251 | None 252 | False 253 | 254 | 255 | True 256 | portable 257 | True 258 | bin\Release\ 259 | TRACE 260 | prompt 261 | 4 262 | true 263 | False 264 | SdkOnly 265 | True 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | Designer 288 | 289 | 290 | Designer 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 28.0.0.1 319 | 320 | 321 | 27.0.0.1 322 | 323 | 324 | 325 | 332 | "; 333 | 334 | string poolMathCsproj = @" 335 | 336 | 337 | Debug 338 | AnyCPU 339 | {C62B0A31-9EF4-46F9-A4FA-2CCDA1937444} 340 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 341 | Library 342 | TroubleFreePool.Droid 343 | com.troublefreepool.poolmath 344 | v9.0 345 | True 346 | Resources\Resource.designer.cs 347 | Resource 348 | Properties\AndroidManifest.xml 349 | Resources 350 | Assets 351 | false 352 | 353 | 354 | None 355 | true 356 | true 357 | Xamarin.Android.Net.AndroidClientHandler 358 | 359 | 360 | true 361 | full 362 | false 363 | bin\Debug 364 | DEBUG; 365 | prompt 366 | 4 367 | false 368 | arm64-v8a;armeabi-v7a;x86;x86_64 369 | true 370 | 371 | 372 | ..\Signing\poolmath.keystore 373 | poolmath 374 | poolmath 375 | poolmath 376 | true 377 | 378 | 379 | true 380 | pdbonly 381 | true 382 | bin\Release 383 | prompt 384 | 4 385 | true 386 | True 387 | ..\Signing\poolmath.keystore 388 | poolmath 389 | poolmath 390 | poolmath 391 | armeabi-v7a;arm64-v8a 392 | SdkOnly 393 | true 394 | 1G 395 | -Xss4096k 396 | true 397 | 398 | 399 | true 400 | pdbonly 401 | true 402 | bin\Release 403 | prompt 404 | 4 405 | true 406 | True 407 | ..\Signing\poolmath.keystore 408 | poolmath 409 | poolmath 410 | poolmath 411 | armeabi-v7a;arm64-v8a 412 | SdkOnly 413 | true 414 | 1G 415 | -Xss4096k 416 | true 417 | APPSTORE; 418 | 419 | 420 | $(MSBuildThisFileDirectory)..\ 421 | 422 | 423 | 26.0.2 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 1.4.1 475 | 476 | 477 | 28.0.0.1 478 | 479 | 480 | 28.0.0.1 481 | 482 | 483 | 28.0.0.1 484 | 485 | 486 | 28.0.0.1 487 | 488 | 489 | 28.0.0.1 490 | 491 | 492 | 28.0.0.1 493 | 494 | 495 | 28.0.0.1 496 | 497 | 498 | 28.0.0.1 499 | 500 | 501 | 28.0.0.1 502 | 503 | 504 | 28.0.0.1 505 | 506 | 507 | 28.0.0.1 508 | 509 | 510 | 28.0.0.1 511 | 512 | 513 | 60.1142.1 514 | 515 | 516 | 12.0.1 517 | 518 | 519 | 1.14.0 520 | 521 | 522 | 1.14.0 523 | 524 | 525 | 1.14.0 526 | 527 | 528 | 1.14.0 529 | 530 | 531 | 1.14.0 532 | 533 | 534 | 1.2.0-beta 535 | 536 | 537 | 1.2.0-beta 538 | 539 | 540 | 2.0.3 541 | 542 | 543 | 2.1.0.187-beta 544 | 545 | 546 | 3.0.0.12 547 | 548 | 549 | 0.4.12-preview3 550 | 551 | 552 | 4.38.0 553 | 554 | 555 | 3.6.0.344457 556 | 557 | 558 | 2.5.16 559 | 560 | 561 | 1.1.0 562 | 563 | 564 | 565 | 566 | {E0A1FD19-6E12-449D-8C07-5A00EB73C465} 567 | PoolMath.Core 568 | 569 | 570 | {C6C52109-A9B0-4027-A9A3-F1D2A3314F0E} 571 | PoolMathApp.Share 572 | 573 | 574 | {B986F10C-01CB-4F0A-881D-29C06A91DF89} 575 | AmazonIap 576 | 577 | 578 | 579 | 580 | "; 581 | } 582 | } 583 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Test/ResolverTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Xunit; 7 | 8 | namespace VisualStudio.AndroidX.Migration 9 | { 10 | public class ResolverTests 11 | { 12 | [Fact] 13 | public void when_translation_resolver_doesnt_have_assemblies_it_still_initializes() 14 | { 15 | var resolver = new TranslationResolver(null, null); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Test/TestBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace VisualStudio.AndroidX.Migration 8 | { 9 | public class TestBase 10 | { 11 | internal static ITranslationResolver resolver; 12 | 13 | static TestBase() 14 | { 15 | var codeBase = new Uri(typeof(TestBase).Assembly.CodeBase).AbsolutePath; 16 | var binDirectory = Path.GetDirectoryName(codeBase); 17 | 18 | var assembliesDirectory = Path.Combine(binDirectory, "Assemblies", "Android"); 19 | 20 | resolver = new TranslationResolver(Directory.GetFiles(assembliesDirectory), new List { }); 21 | } 22 | 23 | 24 | public static Solution CreateSolution(string file) 25 | { 26 | var workspace = new AdhocWorkspace(); 27 | var project = workspace.AddProject("MethodTest", "C#"); 28 | foreach (var assembly in resolver.AndroidAssemblies) 29 | project = project.AddMetadataReference(MetadataReference.CreateFromFile(assembly.Location)); 30 | var document = project.AddDocument("Class1.cs", file); 31 | return document.Project.Solution; 32 | } 33 | 34 | internal static string GetText(Solution solution) 35 | { 36 | return solution.Projects.First().Documents.First().GetSyntaxRootAsync().Result.ToFullString(); 37 | } 38 | 39 | internal static Document GetFirstDocument(Solution solution) 40 | { 41 | return solution.Projects.First().Documents.First(); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.Test/VisualStudio.AndroidX.Migration.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net472 5 | VisualStudio.AndroidX.Migration 6 | VisualStudio.AndroidX.Migration.Tests 7 | 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /VisualStudio.AndroidX.Migration.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28803.443 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualStudio.AndroidX.Migration.Core", "VisualStudio.AndroidX.Migration.Core\VisualStudio.AndroidX.Migration.Core.csproj", "{297B120F-DE08-4460-BCE6-5B2A74535C2D}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualStudio.AndroidX.Migration.Console", "VisualStudio.AndroidX.Migration.Console\VisualStudio.AndroidX.Migration.Console.csproj", "{29E0E329-B35E-4A6C-B24D-E4700C6BA58F}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VisualStudio.AndroidX.Migration.Tests", "VisualStudio.AndroidX.Migration.Test\VisualStudio.AndroidX.Migration.Tests.csproj", "{2E87329E-6B9A-4F80-9D80-A3147B15BBA9}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {297B120F-DE08-4460-BCE6-5B2A74535C2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {297B120F-DE08-4460-BCE6-5B2A74535C2D}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {297B120F-DE08-4460-BCE6-5B2A74535C2D}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {297B120F-DE08-4460-BCE6-5B2A74535C2D}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {29E0E329-B35E-4A6C-B24D-E4700C6BA58F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {29E0E329-B35E-4A6C-B24D-E4700C6BA58F}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {29E0E329-B35E-4A6C-B24D-E4700C6BA58F}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {29E0E329-B35E-4A6C-B24D-E4700C6BA58F}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {2E87329E-6B9A-4F80-9D80-A3147B15BBA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {2E87329E-6B9A-4F80-9D80-A3147B15BBA9}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {2E87329E-6B9A-4F80-9D80-A3147B15BBA9}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {2E87329E-6B9A-4F80-9D80-A3147B15BBA9}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {77E00823-76E8-4B60-ABF0-181ABA21AE6C} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - master 3 | - refs/tags/* 4 | 5 | resources: 6 | repositories: 7 | - repository: internal-templates 8 | type: github 9 | name: xamarin/yaml-templates 10 | endpoint: xamarin 11 | - repository: components 12 | type: github 13 | name: xamarin/XamarinComponents 14 | endpoint: xamarin 15 | 16 | jobs: 17 | - template: .ci/build.yml@components 18 | parameters: 19 | artifactsPath: 'output/nugets' 20 | postBuildSteps: 21 | - task: PublishTestResults@2 22 | displayName: Publish test results 23 | condition: always() 24 | inputs: 25 | testResultsFormat: xUnit 26 | testResultsFiles: output/test-results/**/*.xml 27 | testRunTitle: 'tests-$(System.JobName)' 28 | - ${{ if eq(variables['System.TeamProject'], 'devdiv') }}: 29 | - template: sign-artifacts/jobs/v1.yml@internal-templates 30 | parameters: 31 | dependsOn: [ 'build' ] 32 | -------------------------------------------------------------------------------- /build.cake: -------------------------------------------------------------------------------- 1 | #tool "nuget:?package=xunit.runner.console&version=2.4.1" 2 | 3 | #addin "nuget:?package=Cake.FileHelpers&version=3.2.1" 4 | 5 | var target = Argument("t", Argument("target", "ci")); 6 | var verbosity = Argument("v", Argument("verbosity", Verbosity.Normal)); 7 | var configuration = Argument("c", Argument("configuration", "Release")); 8 | 9 | var mappingVersion = "f48a9d16427ddc449e57fe73017cc2fecf52eb3d"; 10 | var mappingAssemblies = $"https://raw.githubusercontent.com/xamarin/AndroidX/{mappingVersion}/mappings/androidx-assemblies.csv"; 11 | var mappingMappings = $"https://raw.githubusercontent.com/xamarin/AndroidX/{mappingVersion}/mappings/androidx-mapping.csv"; 12 | 13 | Task("externals") 14 | .Does(() => 15 | { 16 | EnsureDirectoryExists("./externals/mappings/"); 17 | 18 | if (!FileExists("./externals/mappings/androidx-assemblies.csv")) 19 | DownloadFile(mappingAssemblies, "./externals/mappings/androidx-assemblies.csv"); 20 | if (!FileExists("./externals/mappings/androidx-mapping.csv")) 21 | DownloadFile(mappingMappings, "./externals/mappings/androidx-mapping.csv"); 22 | }); 23 | 24 | Task("tests-externals") 25 | .Does(() => 26 | { 27 | var testAssembliesFolder = "./externals/test-assets/Assemblies/"; 28 | 29 | if (DirectoryExists($"{testAssembliesFolder}AndroidX")) 30 | return; 31 | 32 | var androidXNugets = new [] { 33 | "https://globalcdn.nuget.org/packages/xamarin.androidx.appcompat.1.1.0.1.nupkg", 34 | "https://globalcdn.nuget.org/packages/xamarin.androidx.leanback.1.0.0.1.nupkg", 35 | "https://globalcdn.nuget.org/packages/xamarin.androidx.lifecycle.common.2.2.0.1.nupkg", 36 | }; 37 | var androidNugets = new [] { 38 | "https://globalcdn.nuget.org/packages/xamarin.android.arch.lifecycle.common.1.1.1.3.nupkg", 39 | "https://globalcdn.nuget.org/packages/xamarin.android.support.v7.appcompat.28.0.0.3.nupkg", 40 | "https://globalcdn.nuget.org/packages/xamarin.android.support.v17.leanback.28.0.0.3.nupkg", 41 | }; 42 | 43 | EnsureDirectoryExists($"{testAssembliesFolder}AndroidX"); 44 | foreach (var nuget in androidXNugets) { 45 | var tmp = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetRandomFileName()); 46 | CreateDirectory(tmp); 47 | DownloadFile(nuget, $"{tmp}/nuget.nupkg"); 48 | Unzip($"{tmp}/nuget.nupkg", tmp); 49 | CopyFiles(GetFiles($"{tmp}/lib/monoandroid90/*.dll"), $"{testAssembliesFolder}AndroidX"); 50 | DeleteDirectory(tmp, new DeleteDirectorySettings { Recursive = true, Force = true }); 51 | } 52 | 53 | EnsureDirectoryExists($"{testAssembliesFolder}Android"); 54 | foreach (var nuget in androidNugets) { 55 | var tmp = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetRandomFileName()); 56 | CreateDirectory(tmp); 57 | DownloadFile(nuget, $"{tmp}/nuget.nupkg"); 58 | Unzip($"{tmp}/nuget.nupkg", tmp); 59 | CopyFiles(GetFiles($"{tmp}/lib/monoandroid90/*.dll"), $"{testAssembliesFolder}Android"); 60 | DeleteDirectory(tmp, new DeleteDirectorySettings { Recursive = true, Force = true }); 61 | } 62 | }); 63 | 64 | Task("libs") 65 | .IsDependentOn("externals") 66 | .IsDependentOn("tests-externals") 67 | .Does(() => 68 | { 69 | MSBuild("./VisualStudio.AndroidX.Migration.sln", new MSBuildSettings { 70 | Configuration = configuration, 71 | Restore = true, 72 | BinaryLogger = new MSBuildBinaryLogSettings 73 | { 74 | Enabled = true, 75 | FileName = MakeAbsolute((DirectoryPath)"./output/binlogs/libs.binlog").FullPath, 76 | } 77 | }); 78 | }); 79 | 80 | Task("nuget") 81 | .IsDependentOn("libs") 82 | .Does(() => 83 | { 84 | DeleteFiles("./output/nugets/*.nupkg"); 85 | 86 | var csproj = "./VisualStudio.AndroidX.Migration.Core/VisualStudio.AndroidX.Migration.Core.csproj"; 87 | var settings = new MSBuildSettings { 88 | Configuration = configuration, 89 | Properties = { 90 | { "PackageOutputPath", new [] { MakeAbsolute((DirectoryPath)"./output/nugets/").FullPath } }, 91 | }, 92 | BinaryLogger = new MSBuildBinaryLogSettings 93 | { 94 | Enabled = true, 95 | FileName = MakeAbsolute((DirectoryPath)"./output/binlogs/pack.binlog").FullPath, 96 | } 97 | }; 98 | MSBuild(csproj, settings.WithTarget("Pack")); 99 | }); 100 | 101 | Task("tests") 102 | .IsDependentOn("libs") 103 | .Does(() => 104 | { 105 | try { 106 | var testAssemblies = GetFiles($"./VisualStudio.AndroidX.Migration.Test/bin/{configuration}/*/*.Tests.dll"); 107 | foreach (var assembly in testAssemblies) { 108 | XUnit2(new [] { assembly }, new XUnit2Settings { 109 | XmlReport = true, 110 | NoAppDomain = true, 111 | OutputDirectory = $"./output/test-results/VisualStudio.AndroidX.Migration.Tests", 112 | WorkingDirectory = assembly.GetDirectory(), 113 | }); 114 | } 115 | } catch (Exception ex) { 116 | Error("##[error]Tests failed: " + ex.Message); 117 | Error(ex); 118 | } 119 | }); 120 | 121 | Task("ci") 122 | .IsDependentOn("externals") 123 | .IsDependentOn("libs") 124 | .IsDependentOn("nuget") 125 | .IsDependentOn("tests"); 126 | 127 | RunTarget(target); 128 | --------------------------------------------------------------------------------