예제 #1
0
        static async Task AddAssemblyReference(MonoDevelopWorkspace ws, DotNetProject from, DotNetProject to, string name)
        {
            var manager = ws.MetadataReferenceManager;

            var assemblies = await from.GetReferencedAssemblies(IdeApp.Workspace?.ActiveConfiguration ?? ConfigurationSelector.Default);

            var messagingAsm      = assemblies.Single(x => x.Metadata.GetValue <string> ("Filename") == name);
            var metadataReference = manager.GetOrCreateMetadataReference(messagingAsm.FilePath, MetadataReferenceProperties.Assembly);

            await FileWatcherService.Update();

            var roslynProj = ws.GetProjectId(to);

            var oldRefs     = ws.CurrentSolution.GetProject(roslynProj).MetadataReferences;
            var newRefs     = oldRefs.ToImmutableArray().Add(metadataReference.CurrentSnapshot);
            var newSolution = ws.CurrentSolution.WithProjectMetadataReferences(roslynProj, newRefs);

            Assert.IsTrue(ws.TryApplyChanges(newSolution));
            await ws.ProjectSaveTask;

            var reference = to.References.Single(x => x.Include == name);

            Assert.IsTrue(reference.HintPath.IsNull);
            Assert.AreEqual(ReferenceType.Package, reference.ReferenceType);
        }
        public async Task ReferenceCacheSnapshotUpdates()
        {
            string solFile = Util.GetSampleProject("console-project", "ConsoleProject.sln");

            var tempPath = Path.GetFullPath(Path.GetTempFileName());
            var oldAsm   = typeof(MonoDevelopMetadataReferenceManagerTests).Assembly.Location;

            File.Copy(oldAsm, tempPath, true);

            try {
                using (var sol = (MonoDevelop.Projects.Solution) await Services.ProjectService.ReadWorkspaceItem(Util.GetMonitor(), solFile))
                    using (var ws = await TypeSystemServiceTestExtensions.LoadSolution(sol)) {
                        await FileWatcherService.Add(sol);

                        var manager = ws.MetadataReferenceManager;
                        var item    = manager.GetOrCreateMetadataReference(tempPath, MetadataReferenceProperties.Assembly);
                        Assert.IsNotNull(item);

                        await FileWatcherService.Update();

                        var initialId = item.CurrentSnapshot.GetMetadataId();

                        var taskForNewAsm = WaitForSnapshotChange(item);

                        // Replace the assembly with another one.
                        var newAsm = typeof(MonoDevelopMetadataReference).Assembly.Location;
                        File.Copy(newAsm, tempPath, true);

                        var argsForNewAsm = await taskForNewAsm;

                        Assert.AreSame(item.CurrentSnapshot, argsForNewAsm.OldSnapshot);

                        Assert.AreNotSame(argsForNewAsm.OldSnapshot, argsForNewAsm.NewSnapshot.Value);
                        // item.CurrentSnapshot is now updated
                        Assert.AreNotEqual(initialId, item.CurrentSnapshot.GetMetadataId());

                        var taskForOldAsm = WaitForSnapshotChange(item);
                        File.Copy(newAsm, tempPath, true);

                        var argsForOldAsm = await taskForOldAsm;

                        Assert.AreSame(item.CurrentSnapshot, argsForOldAsm.OldSnapshot);

                        Assert.AreNotSame(argsForNewAsm.OldSnapshot, argsForNewAsm.NewSnapshot.Value);
                        // Even though the old assembly was put back, it has a new id this time.
                        Assert.AreNotEqual(initialId, item.CurrentSnapshot.GetMetadataId());
                    }

                await FileWatcherService.Update();

                // At this point, the metadata reference should be disposed.
                // Check to see if file updates will trigger a file service noification
                var tcsShouldTimeout = new TaskCompletionSource <bool> ();
                var ctsFail          = new CancellationTokenSource();
                ctsFail.Token.Register(() => tcsShouldTimeout.TrySetResult(true));
                Core.FileService.FileChanged += (sender, args) => {
                    foreach (var file in args)
                    {
                        if (file.FileName == tempPath)
                        {
                            tcsShouldTimeout.TrySetResult(false);
                        }
                    }
                };

                ctsFail.CancelAfter(1000 * 5);
                File.WriteAllText(tempPath, "");
                Assert.AreEqual(true, await tcsShouldTimeout.Task);
            } finally {
                File.Delete(tempPath);
            }
        }