Esempio n. 1
0
        private async Task ValidateChecksumAsync(Checksum checksumFromRequest, Solution incrementalSolutionBuilt)
        {
#if DEBUG
            var currentSolutionChecksum = await incrementalSolutionBuilt.State.GetChecksumAsync(CancellationToken.None).ConfigureAwait(false);

            if (checksumFromRequest == currentSolutionChecksum)
            {
                return;
            }

            var solutionFromScratch = await CreateSolutionFromScratchAsync(checksumFromRequest).ConfigureAwait(false);

            await TestUtils.AssertChecksumsAsync(_assetService, checksumFromRequest, solutionFromScratch, incrementalSolutionBuilt).ConfigureAwait(false);

            async Task <Solution> CreateSolutionFromScratchAsync(Checksum checksum)
            {
                var solutionInfo = await SolutionInfoCreator.CreateSolutionInfoAsync(_assetService, checksum, _cancellationToken).ConfigureAwait(false);

                var workspace = new TemporaryWorkspace(solutionInfo);

                return(workspace.CurrentSolution);
            }
#else
            // have this to avoid error on async
            await Task.CompletedTask.ConfigureAwait(false);
#endif
        }
Esempio n. 2
0
        private async Task <Solution> GetSolutionAsync(IRemotableDataService service, PinnedRemotableDataScope syncScope)
        {
            var(solutionInfo, _) = await SolutionInfoCreator.CreateSolutionInfoAndOptionsAsync(new AssetProvider(service), syncScope.SolutionChecksum, CancellationToken.None).ConfigureAwait(false);

            var workspace = new AdhocWorkspace();

            return(workspace.AddSolution(solutionInfo));
        }
Esempio n. 3
0
        private async Task <Solution> UpdateProjectsAsync(Solution solution, HashSet <Checksum> oldChecksums, HashSet <Checksum> newChecksums)
        {
            var oldMap = await GetProjectMapAsync(solution, oldChecksums).ConfigureAwait(false);

            var newMap = await GetProjectMapAsync(_assetService, newChecksums).ConfigureAwait(false);

            // bulk sync assets
            await SynchronizeAssetsAsync(solution, oldMap, newMap).ConfigureAwait(false);

            // added project
            foreach (var kv in newMap)
            {
                if (!oldMap.ContainsKey(kv.Key))
                {
                    var projectInfo = await SolutionInfoCreator.CreateProjectInfoAsync(_assetService, kv.Value.Checksum, _cancellationToken).ConfigureAwait(false);

                    if (projectInfo == null)
                    {
                        // this project is not supported in OOP
                        continue;
                    }

                    // we have new project added
                    solution = solution.AddProject(projectInfo);
                }
            }

            // changed project
            foreach (var kv in newMap)
            {
                if (!oldMap.TryGetValue(kv.Key, out var oldProjectChecksums))
                {
                    continue;
                }

                var newProjectChecksums = kv.Value;
                Contract.ThrowIfTrue(oldProjectChecksums.Checksum == newProjectChecksums.Checksum);

                solution = await UpdateProjectAsync(solution.GetProject(kv.Key), oldProjectChecksums, newProjectChecksums).ConfigureAwait(false);
            }

            // removed project
            foreach (var kv in oldMap)
            {
                if (!newMap.ContainsKey(kv.Key))
                {
                    // we have a project removed
                    solution = solution.RemoveProject(kv.Key);
                }
            }

            return(solution);
        }
Esempio n. 4
0
        private async Task <Solution> LoadAsync(CancellationToken cancellationToken)
        {
            var adhocWorkspace = new AdhocWorkspace();
            var serializer     = adhocWorkspace.Services.GetService <ISerializerService>();

            var solutionChecksum = default(Checksum);
            var map = new Dictionary <Checksum, object>();

            using (var stream = new FileStream(_fileName, FileMode.Open))
                using (var compressed = new DeflateStream(stream, CompressionMode.Decompress))
                    using (var reader = ObjectReader.TryGetReader(compressed, cancellationToken))
                    {
                        // save root checksum and number of entries
                        solutionChecksum = Checksum.ReadFrom(reader);

                        // number of items in the package
                        var count = reader.ReadInt32();

                        for (var i = 0; i < count; i++)
                        {
                            var itemChecksum = Checksum.ReadFrom(reader);

                            var kind = (WellKnownSynchronizationKind)reader.ReadInt32();

                            // in service hub, cancellation means simply closed stream
                            var @object = serializer.Deserialize <object>(kind, reader, cancellationToken);

                            Debug.Assert(itemChecksum == serializer.CreateChecksum(@object, cancellationToken));

                            map.Add(itemChecksum, @object);
                        }
                    }

            var assetSource  = new SimpleAssetSource(AssetStorage.Default, map);
            var assetService = new AssetService(scopeId: 0, AssetStorage.Default, serializer);

            var solutionCreator = new SolutionCreator(assetService, _solution, cancellationToken);

            // check whether solution is update to the given base solution
            if (await solutionCreator.IsIncrementalUpdateAsync(solutionChecksum).ConfigureAwait(false))
            {
                // create updated solution off the baseSolution
                return(await solutionCreator.CreateSolutionAsync(solutionChecksum).ConfigureAwait(false));
            }

            // get new solution info
            var solutionInfo = await SolutionInfoCreator.CreateSolutionInfoAsync(assetService, solutionChecksum, cancellationToken).ConfigureAwait(false);

            // otherwise, just return new solution
            return(adhocWorkspace.AddSolution(solutionInfo));
        }
Esempio n. 5
0
        /// <summary>
        /// SolutionService is designed to be stateless. if someone asks a solution (through solution checksum),
        /// it will create one and return the solution. the engine takes care of synching required data and creating a solution
        /// correspoing to the given checksum.
        ///
        /// but doing that from scratch all the time wil be expansive in terms of synching data, compilation being cached, file being parsed
        /// and etc. so even if the service itself is stateless, internally it has several caches to improve perf of various parts.
        ///
        /// first, it holds onto last solution got built. this will take care of common cases where multiple services running off same solution.
        /// second, it uses assets cache to hold onto data just synched (within 3 min) so that if it requires to build new solution,
        ///         it can save some time to re-sync data which might just used by other solution.
        /// third, it holds onto solution from primary branch from Host. and it will try to see whether it can build new solution off the
        ///        primary solution it is holding onto. this will make many solution level cache to be re-used.
        ///
        /// the primary solution can be updated in 2 ways.
        /// first, host will keep track of primary solution changes in host, and call OOP to synch to latest time to time.
        /// second, engine keeps track of whether a certain request is for primary solution or not, and if it is,
        ///         it let that request to update primary solution cache to latest.
        ///
        /// these 2 are complimentary to each other. #1 makes OOP's primary solution to be ready for next call (push), #2 makes OOP's primary
        /// solution be not stale as much as possible. (pull)
        /// </summary>
        private async Task <Solution> CreateSolution_NoLockAsync(Checksum solutionChecksum, bool fromPrimaryBranch, Solution baseSolution, CancellationToken cancellationToken)
        {
            var updater = new SolutionCreator(_assetService, baseSolution, cancellationToken);

            // check whether solution is update to the given base solution
            if (await updater.IsIncrementalUpdateAsync(solutionChecksum).ConfigureAwait(false))
            {
                // create updated solution off the baseSolution
                var solution = await updater.CreateSolutionAsync(solutionChecksum).ConfigureAwait(false);

                if (fromPrimaryBranch)
                {
                    // if the solutionChecksum is for primary branch, update primary workspace cache with the solution
                    PrimaryWorkspace.UpdateSolution(solution);
                    return(PrimaryWorkspace.CurrentSolution);
                }

                // otherwise, just return the solution
                return(solution);
            }

            // we need new solution. bulk sync all asset for the solution first.
            await _assetService.SynchronizeSolutionAssetsAsync(solutionChecksum, cancellationToken).ConfigureAwait(false);

            // get new solution info
            var solutionInfo = await SolutionInfoCreator.CreateSolutionInfoAsync(_assetService, solutionChecksum, cancellationToken).ConfigureAwait(false);

            if (fromPrimaryBranch)
            {
                // if the solutionChecksum is for primary branch, update primary workspace cache with new solution
                PrimaryWorkspace.ClearSolution();
                PrimaryWorkspace.AddSolution(solutionInfo);

                return(PrimaryWorkspace.CurrentSolution);
            }

            // otherwise, just return new solution
            var workspace = new TemporaryWorkspace(await SolutionInfoCreator.CreateSolutionInfoAsync(_assetService, solutionChecksum, cancellationToken).ConfigureAwait(false));

            return(workspace.CurrentSolution);
        }
Esempio n. 6
0
 public Task <(SolutionInfo, SerializableOptionSet)> GetSolutionInfoAndOptionsAsync(Checksum solutionChecksum, CancellationToken cancellationToken)
 {
     return(SolutionInfoCreator.CreateSolutionInfoAndOptionsAsync(_assetService, solutionChecksum, cancellationToken));
 }
Esempio n. 7
0
        private async Task <Project> UpdateDocumentsAsync(
            Project project,
            IEnumerable <TextDocumentState> existingTextDocumentStates,
            ChecksumCollection oldChecksums,
            ChecksumCollection newChecksums,
            Func <Solution, ImmutableArray <DocumentInfo>, Solution> addDocuments,
            Func <Solution, DocumentId, Solution> removeDocument)
        {
            using (var olds = SharedPools.Default <HashSet <Checksum> >().GetPooledObject())
                using (var news = SharedPools.Default <HashSet <Checksum> >().GetPooledObject())
                {
                    olds.Object.UnionWith(oldChecksums);
                    news.Object.UnionWith(newChecksums);

                    // remove documents that exist in both side
                    olds.Object.ExceptWith(newChecksums);
                    news.Object.ExceptWith(oldChecksums);

                    var oldMap = await GetDocumentMapAsync(project, existingTextDocumentStates, olds.Object).ConfigureAwait(false);

                    var newMap = await GetDocumentMapAsync(_assetService, news.Object).ConfigureAwait(false);

                    // added document
                    ImmutableArray <DocumentInfo> .Builder documentsToAdd = null;
                    foreach (var kv in newMap)
                    {
                        if (!oldMap.ContainsKey(kv.Key))
                        {
                            documentsToAdd = documentsToAdd ?? ImmutableArray.CreateBuilder <DocumentInfo>();

                            // we have new document added
                            var documentInfo = await SolutionInfoCreator.CreateDocumentInfoAsync(_assetService, kv.Value.Checksum, _cancellationToken).ConfigureAwait(false);

                            documentsToAdd.Add(documentInfo);
                        }
                    }

                    if (documentsToAdd != null)
                    {
                        project = addDocuments(project.Solution, documentsToAdd.ToImmutable()).GetProject(project.Id);
                    }

                    // changed document
                    foreach (var kv in newMap)
                    {
                        if (!oldMap.TryGetValue(kv.Key, out var oldDocumentChecksums))
                        {
                            continue;
                        }

                        var newDocumentChecksums = kv.Value;
                        Contract.ThrowIfTrue(oldDocumentChecksums.Checksum == newDocumentChecksums.Checksum);

                        var document = project.GetDocument(kv.Key) ?? project.GetAdditionalDocument(kv.Key) ?? project.GetAnalyzerConfigDocument(kv.Key);
                        project = await UpdateDocumentAsync(document, oldDocumentChecksums, newDocumentChecksums).ConfigureAwait(false);
                    }

                    // removed document
                    foreach (var kv in oldMap)
                    {
                        if (!newMap.ContainsKey(kv.Key))
                        {
                            // we have a document removed
                            project = removeDocument(project.Solution, kv.Key).GetProject(project.Id);
                        }
                    }

                    return(project);
                }
        }
Esempio n. 8
0
 public Task <SolutionInfo> GetSolutionInfoAsync(Checksum solutionChecksum, CancellationToken cancellationToken)
 {
     return(SolutionInfoCreator.CreateSolutionInfoAsync(_assetService, solutionChecksum, cancellationToken));
 }
Esempio n. 9
0
        /// <summary>
        /// This function is the callback used to execute the command when the menu item is clicked.
        /// See the constructor to see how the menu item is associated with this function using
        /// OleMenuCommandService service and MenuCommand class.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event args.</param>
        private void Execute(object sender, EventArgs e)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            try
            {
                VisualStudioWorkspace workspace = ((IComponentModel)Package.GetGlobalService(typeof(SComponentModel))).GetService <VisualStudioWorkspace>();

                ProjectItem selectedItem = this.GetSelectedSolutionExplorerItem();
                if (selectedItem != null && selectedItem.Name != null && !selectedItem.Name.EndsWith(".cs"))
                {
                    "52ABP代码生成器(官网:52abp.com),仅支持C#文件!".ErrorMsg();
                }
                else
                {
                    Document currentSelectedDocument;
                    if (((selectedItem != null) ? selectedItem.Document : null) != null)
                    {
                        currentSelectedDocument = workspace.CurrentSolution.GetDocumentByFilePath(selectedItem.Document.FullName);
                    }
                    else
                    {
                        if (selectedItem == null)
                        {
                            "致命异常-无法获得当前选择的解决方案:请重新打开这个解决方案,然后重试本工具。(官网:52abp.com)".ErrorMsg();
                            return;
                        }
                        string         file        = selectedItem.Name;
                        string         projectName = selectedItem.ContainingProject.Name;
                        List <Project> allProjects = workspace.CurrentSolution.Projects.ToList <Project>();
                        List <Project> tmpProjects = (from o in allProjects
                                                      where o.Name.StartsWith(projectName + "(net")
                                                      select o).ToList <Project>();
                        List <Document> docs;
                        if (allProjects.Exists((Project p) => p.Name.Contains(".Shared")))
                        {
                            docs = (from d in (from p in allProjects
                                               where p.Name.Contains(projectName) && !p.Name.Contains(".Shared")
                                               select p).FirstOrDefault <Project>().Documents
                                    where d.Name == file
                                    select d).ToList <Document>();
                        }
                        else if (tmpProjects.Count > 1)
                        {
                            docs = (from d in tmpProjects.FirstOrDefault <Project>().Documents
                                    where d.Name == file
                                    select d).ToList <Document>();
                        }
                        else
                        {
                            docs = (from d in (from p in allProjects
                                               where p.Name == projectName
                                               select p).SelectMany((Project p) => p.Documents)
                                    where d.Name == file
                                    select d).ToList <Document>();
                        }
                        if (docs.Count == 0)
                        {
                            "致命异常-无法获得当前选择的解决方案。请尝试重新打开解决方案,然后再使用本工具(官网:52abp.com)".ErrorMsg();
                            return;
                        }
                        if (docs.Count > 1)
                        {
                            "当前解决方案中,有多个同名的类文件,请处理之后再使用本工具,比如删除一个^_^(官网:52abp.com)。".ErrorMsg();
                            return;
                        }
                        currentSelectedDocument = docs.FirstOrDefault <Document>();
                    }
                    SolutionInfoModel solutionInfo     = SolutionInfoCreator.Create(currentSelectedDocument);
                    string            path             = Path.Combine(solutionInfo.SolutionPath, "solutionInfo.json");
                    string            solutionInfoJson = JsonConvert.SerializeObject(solutionInfo);
                    path.CreateFile(solutionInfoJson);
                    ProcessStartInfo processStartInfo = new ProcessStartInfo();
                    string           exePath          = Path.Combine(Path.GetDirectoryName(typeof(CommonConsts).Assembly.Location), "YoyoAbpCodePowerProject.WPF.exe");
                    processStartInfo.FileName  = exePath;
                    processStartInfo.Arguments = " \"" + solutionInfo.SolutionPath + "\"";
                    Process.Start(processStartInfo);
                }
            }
            catch (Exception ex)
            {
                try
                {
                    "发生了一个异常。请复制 c/p 堆栈信息,然后打开项目网站(https://github.com/52ABP/52ABP.CodeGenerator),补充问题和增加简短描述。".ErrorMsg();
                    StringBuilder sb = new StringBuilder();
                    sb.Append("<html><head></head><body><a hrf='https://github.com/52ABP/52ABP.CodeGenerator/issues/new'>baidu</a><br>");
                    sb.Append(ex.ToString());
                    sb.Append("</body></html>");
                    string tmpFile = Path.GetTempFileName();
                    File.WriteAllText(tmpFile, sb.ToString());
                    VsShellUtilities.OpenBrowser("file:///" + tmpFile);
                }
                catch (Exception)
                {
                    "发生了一个异常。 无法将堆栈跟踪写入临时目录.".ErrorMsg();
                }
            }
        }