public void ApiAnalysis_Returns_Compatible_When_ApiVersion_Matches_A_CompatibleVersion()
        {
            var sourceFileToInvocations = new Dictionary <string, List <CodeEntityDetails> >
            {
                {
                    "file1", new UstList <CodeEntityDetails>
                    {
                        new CodeEntityDetails
                        {
                            Name = "JsonConvert.SerializeObject",
                            OriginalDefinition = "Newtonsoft.Json.JsonConvert.SerializeObject(object)",
                            Namespace          = "Newtonsoft.Json",
                            Package            = new PackageVersionPair
                            {
                                PackageId = "Newtonsoft.Json",
                                Version   = "10.2.0"
                            },
                            TextSpan       = new TextSpan(),
                            CodeEntityType = CodeEntityType.Method
                        }
                    }
                }
            };

            var package = new PackageVersionPair
            {
                PackageId = "Newtonsoft.Json",
                Version   = "10.2.0"
            };

            var packageTask = new TaskCompletionSource <PackageDetails>();

            packageTask.SetResult(_packageDetails);
            _packageResults = new Dictionary <PackageVersionPair, Task <PackageDetails> >
            {
                { package, packageTask.Task }
            };

            var results = CodeEntityModelToCodeEntities.AnalyzeResults(
                sourceFileToInvocations, _packageResults, _recommendationResults, new Dictionary <string, List <RecommendedAction> >());

            var apiAnalysisResults = results.First().ApiAnalysisResults;

            Assert.AreEqual("10.2.0", apiAnalysisResults.First().CodeEntityDetails.Package.Version);
            Assert.AreEqual(Compatibility.COMPATIBLE, apiAnalysisResults.First().CompatibilityResults.GetValueOrDefault(DEFAULT_TARGET).Compatibility);
            Assert.AreEqual("12.0.3", apiAnalysisResults[0].Recommendations.RecommendedActions.First().Description);
        }
        public void BadVersion()
        {
            var sourceFileToInvocations = new Dictionary <string, UstList <UstNode> >
            {
                {
                    "file1", new UstList <UstNode>
                    {
                        new MockInvocationExpressionModel("definition", "namespace.namespace2.namespace3", "namespace2")
                    }
                }
            };

            var project = new AnalyzerResult
            {
                ProjectResult = new ProjectWorkspace("")
                {
                    ExternalReferences = new ExternalReferences
                    {
                        NugetReferences = new List <ExternalReference>
                        {
                            new ExternalReference
                            {
                                AssemblyLocation = "namespace.dll",
                                Identity         = "namespace",
                                Version          = "*"
                            },
                            new ExternalReference
                            {
                                AssemblyLocation = "namespace2.dll",
                                Identity         = "namespace.namespace2",
                                Version          = "NOT_SEMVER"
                            }
                        }
                    }
                },
                OutputJsonFilePath = null,
                ProjectBuildResult = null
            };

            var result = CodeEntityModelToCodeEntities.Convert(
                sourceFileToInvocations, project);

            Assert.AreEqual(1, result["file1"].Count);
            Assert.AreEqual("namespace.namespace2", result["file1"][0].Package.PackageId);
            Assert.AreEqual("NOT_SEMVER", result["file1"][0].Package.Version);
        }
        public void MultipleNuget()
        {
            var sourceFileToInvocations = new Dictionary <string, UstList <UstNode> >
            {
                {
                    "file1", new UstList <UstNode>
                    {
                        new MockInvocationExpressionModel("Newtonsoft.Json.JsonConvert.SerializeObject(object)", "namespace.namespace2.namespace3", "test")
                    }
                }
            };

            var project = new AnalyzerResult
            {
                ProjectResult = new ProjectWorkspace("")
                {
                    ExternalReferences = new ExternalReferences
                    {
                        NugetReferences = new List <ExternalReference>
                        {
                            new ExternalReference
                            {
                                AssemblyLocation = "test.dll",
                                Identity         = "namespace",
                                Version          = "1.2"
                            },
                            new ExternalReference
                            {
                                AssemblyLocation = "test2.dll",
                                Identity         = "namespace.namespace2",
                                Version          = "1.2"
                            }
                        }
                    }
                },
                OutputJsonFilePath = null,
                ProjectBuildResult = null
            };

            var result = CodeEntityModelToCodeEntities.Convert(
                sourceFileToInvocations, project);

            Assert.AreEqual(1, result["file1"].Count);
            Assert.AreEqual("1.2.0", result["file1"][0].Package.Version);
        }
        public void NoPackageResultsTest()
        {
            var sourceFileToInvocations = new Dictionary <string, List <CodeEntityDetails> >
            {
                {
                    "file1", new List <CodeEntityDetails>
                    {
                        _codeEntityDetails
                    }
                }
            };

            var result = CodeEntityModelToCodeEntities.AnalyzeResults(
                sourceFileToInvocations, new Dictionary <PackageVersionPair, Task <PackageDetails> >(), _recommendationResults, new Dictionary <string, List <RecommendedAction> >());

            Assert.AreEqual(1, result.First().ApiAnalysisResults.Count);
            Assert.AreEqual("11.0.1", result.First().ApiAnalysisResults.First().CodeEntityDetails.Package.Version);
            Assert.AreEqual(Compatibility.UNKNOWN, result.First().ApiAnalysisResults.First().CompatibilityResults.GetValueOrDefault(DEFAULT_TARGET).Compatibility);
            Assert.IsNull(result[0].ApiAnalysisResults[0].Recommendations.RecommendedActions.First().Description);
        }
Пример #5
0
        public void NormalAnalyzeCaseTest()
        {
            var sourceFileToInvocations = new Dictionary <string, List <CodeEntityDetails> >
            {
                {
                    "file1", new UstList <CodeEntityDetails>
                    {
                        _codeEntityDetails
                    }
                }
            };

            var result = CodeEntityModelToCodeEntities.AnalyzeResults(
                sourceFileToInvocations, packageResults, recommendationResults, new Dictionary <string, List <RecommendedAction> >());

            Assert.AreEqual(1, result.First().ApiAnalysisResults.Count);
            Assert.AreEqual("11.0.1", result.First().ApiAnalysisResults.First().CodeEntityDetails.Package.Version);
            Assert.AreEqual(Compatibility.COMPATIBLE, result.First().ApiAnalysisResults.First().CompatibilityResults.GetValueOrDefault(DEFAULT_TARGET).Compatibility);
            Assert.AreEqual("12.0.3", result[0].ApiAnalysisResults[0].Recommendations.RecommendedActions.First().Description);
        }
Пример #6
0
        public async Task <List <SourceFileAnalysisResult> > AnalyzeFileIncremental(string filePath, string fileContent, string projectFile, string solutionFilePath, List <string> preportReferences
                                                                                    , List <string> currentReferences, RootNodes projectRules, ExternalReferences externalReferences, bool actionsOnly = false, bool compatibleOnly = false, string targetFramework = DEFAULT_TARGET)
        {
            try
            {
                List <SourceFileAnalysisResult> sourceFileAnalysisResults = new List <SourceFileAnalysisResult>();

                var fileAnalysis = await AnalyzeProjectFiles(projectFile, fileContent, filePath, preportReferences, currentReferences);

                var fileActions = AnalyzeFileActionsIncremental(projectFile, projectRules, targetFramework, solutionFilePath, filePath, fileAnalysis);

                var sourceFileResult = fileAnalysis.RootNodes.FirstOrDefault();

                Dictionary <string, List <CodeEntityDetails> >          sourceFileToCodeEntityDetails = new Dictionary <string, List <CodeEntityDetails> >();
                Dictionary <string, Task <RecommendationDetails> >      recommendationResults         = new Dictionary <string, Task <RecommendationDetails> >();
                Dictionary <PackageVersionPair, Task <PackageDetails> > packageResults = new Dictionary <PackageVersionPair, Task <PackageDetails> >();

                if (!actionsOnly)
                {
                    var sourceFileToInvocations = new[] { SourceFileToCodeTokens(sourceFileResult) }.ToDictionary(result => result.Key, result => result.Value);

                    sourceFileToCodeEntityDetails = CodeEntityModelToCodeEntities.Convert(sourceFileToInvocations, externalReferences);

                    var namespaces = sourceFileToCodeEntityDetails.Aggregate(new HashSet <string>(), (agg, cur) =>
                    {
                        agg.UnionWith(cur.Value.Select(i => i.Namespace).Where(i => i != null));
                        return(agg);
                    });

                    var nugetPackages = externalReferences?.NugetReferences?
                                        .Select(r => CodeEntityModelToCodeEntities.ReferenceToPackageVersionPair(r))?
                                        .ToHashSet();

                    var subDependencies = externalReferences?.NugetDependencies?
                                          .Select(r => CodeEntityModelToCodeEntities.ReferenceToPackageVersionPair(r))
                                          .ToHashSet();

                    var sdkPackages = namespaces.Select(n => new PackageVersionPair {
                        PackageId = n, Version = "0.0.0", PackageSourceType = PackageSourceType.SDK
                    });

                    var allPackages = nugetPackages
                                      .Union(subDependencies)
                                      .Union(sdkPackages)
                                      .ToList();

                    packageResults = _handler.GetNugetPackages(allPackages, solutionFilePath, isIncremental: true, incrementalRefresh: false);

                    recommendationResults = _recommendationHandler.GetApiRecommendation(namespaces.ToList());
                }

                var portingActionResults = new Dictionary <string, List <RecommendedAction> >();

                var recommendedActions = fileActions.Select(f => new RecommendedAction()
                {
                    Description           = f.Description,
                    RecommendedActionType = RecommendedActionType.ReplaceApi,
                    TextSpan = new Model.TextSpan()
                    {
                        StartCharPosition = f.TextSpan.StartCharPosition,
                        EndCharPosition   = f.TextSpan.EndCharPosition,
                        StartLinePosition = f.TextSpan.StartLinePosition,
                        EndLinePosition   = f.TextSpan.EndLinePosition
                    },
                    TextChanges = f.TextChanges
                }).ToHashSet().ToList();

                portingActionResults.Add(filePath, recommendedActions);

                var sourceFileAnalysisResult = CodeEntityModelToCodeEntities.AnalyzeResults(
                    sourceFileToCodeEntityDetails, packageResults, recommendationResults, portingActionResults, targetFramework, compatibleOnly);

                //In case actions only, result will be empty, so we populate with actions
                if (actionsOnly)
                {
                    sourceFileAnalysisResult.Add(new SourceFileAnalysisResult()
                    {
                        SourceFileName     = Path.GetFileName(filePath),
                        SourceFilePath     = filePath,
                        RecommendedActions = recommendedActions,
                        ApiAnalysisResults = new List <ApiAnalysisResult>()
                    });
                }

                sourceFileAnalysisResults.AddRange(sourceFileAnalysisResult);


                return(sourceFileAnalysisResults);
            }
            finally
            {
                CommonUtils.RunGarbageCollection(_logger, "PortingAssistantAnalysisHandler.AnalyzeFileIncremental");
            }
        }
Пример #7
0
        private ProjectAnalysisResult AnalyzeProject(
            string project, string solutionFileName, List <AnalyzerResult> analyzers, List <ProjectResult> analysisActions, bool isIncremental = false, string targetFramework = DEFAULT_TARGET)
        {
            try
            {
                var analyzer = analyzers.Find((a) => a.ProjectResult?.ProjectFilePath != null &&
                                              a.ProjectResult.ProjectFilePath.Equals(project));

                var projectFeatureType = analysisActions.Find((a) => a.ProjectFile != null &&
                                                              a.ProjectFile.Equals(project))?.FeatureType.ToString();

                var projectActions = analysisActions.FirstOrDefault(p => p.ProjectFile == project)?.ProjectActions ?? new ProjectActions();

                if (analyzer == null || analyzer.ProjectResult == null)
                {
                    _logger.LogError("Unable to build {0}.", project);
                    return(null);
                }

                var sourceFileToCodeTokens = analyzer.ProjectResult.SourceFileResults.Select((sourceFile) =>
                {
                    return(SourceFileToCodeTokens(sourceFile));
                }).ToDictionary(p => p.Key, p => p.Value);

                var sourceFileToCodeEntityDetails = CodeEntityModelToCodeEntities.Convert(sourceFileToCodeTokens, analyzer);

                var namespaces = sourceFileToCodeEntityDetails.Aggregate(new HashSet <string>(), (agg, cur) =>
                {
                    agg.UnionWith(cur.Value.Select(i => i.Namespace).Where(i => i != null));
                    return(agg);
                });

                var targetframeworks = analyzer.ProjectResult.TargetFrameworks.Count == 0 ?
                                       new List <string> {
                    analyzer.ProjectResult.TargetFramework
                } : analyzer.ProjectResult.TargetFrameworks;

                var nugetPackages = analyzer.ProjectResult.ExternalReferences.NugetReferences
                                    .Select(r => CodeEntityModelToCodeEntities.ReferenceToPackageVersionPair(r))
                                    .ToHashSet();
                var nugetPackageNameLookup = nugetPackages.Select(package => package.PackageId).ToHashSet();

                var subDependencies = analyzer.ProjectResult.ExternalReferences.NugetDependencies
                                      .Select(r => CodeEntityModelToCodeEntities.ReferenceToPackageVersionPair(r))
                                      .ToHashSet();

                var sdkPackages = namespaces.Select(n => new PackageVersionPair
                {
                    PackageId         = n,
                    Version           = "0.0.0",
                    PackageSourceType = PackageSourceType.SDK
                }).Where(pair => !nugetPackageNameLookup.Contains(pair.PackageId));

                var allPackages = nugetPackages
                                  .Union(subDependencies)
                                  .Union(sdkPackages)
                                  .ToList();

                Dictionary <PackageVersionPair, Task <PackageDetails> > packageResults;

                if (isIncremental)
                {
                    packageResults = _handler.GetNugetPackages(allPackages, solutionFileName, isIncremental: true, incrementalRefresh: true);
                }
                else
                {
                    packageResults = _handler.GetNugetPackages(allPackages, null, isIncremental: false, incrementalRefresh: false);
                }

                var recommendationResults = _recommendationHandler.GetApiRecommendation(namespaces.ToList());

                var packageAnalysisResults = nugetPackages.Select(package =>
                {
                    var result = PackageCompatibility.IsCompatibleAsync(packageResults.GetValueOrDefault(package, null), package, _logger, targetFramework);
                    var packageAnalysisResult = PackageCompatibility.GetPackageAnalysisResult(result, package, targetFramework);
                    return(new Tuple <PackageVersionPair, Task <PackageAnalysisResult> >(package, packageAnalysisResult));
                }).ToDictionary(t => t.Item1, t => t.Item2);

                var portingActionResults = ProjectActionsToRecommendedActions.Convert(projectActions);

                var SourceFileAnalysisResults = CodeEntityModelToCodeEntities.AnalyzeResults(
                    sourceFileToCodeEntityDetails, packageResults, recommendationResults, portingActionResults, targetFramework);

                var compatibilityResults = GenerateCompatibilityResults(SourceFileAnalysisResults, analyzer.ProjectResult.ProjectFilePath, analyzer.ProjectBuildResult?.PrePortCompilation != null);

                return(new ProjectAnalysisResult
                {
                    ProjectName = analyzer.ProjectResult.ProjectName,
                    ProjectFilePath = analyzer.ProjectResult.ProjectFilePath,
                    TargetFrameworks = targetframeworks,
                    PackageReferences = nugetPackages.ToList(),
                    ProjectReferences = analyzer.ProjectResult.ExternalReferences.ProjectReferences.ConvertAll(p => new ProjectReference {
                        ReferencePath = p.AssemblyLocation
                    }),
                    PackageAnalysisResults = packageAnalysisResults,
                    IsBuildFailed = analyzer.ProjectResult.IsBuildFailed() || analyzer.ProjectBuildResult.IsSyntaxAnalysis,
                    Errors = analyzer.ProjectResult.BuildErrors,
                    ProjectGuid = analyzer.ProjectResult.ProjectGuid,
                    ProjectType = analyzer.ProjectResult.ProjectType,
                    FeatureType = projectFeatureType,
                    SourceFileAnalysisResults = SourceFileAnalysisResults,
                    MetaReferences = analyzer.ProjectBuildResult.Project.MetadataReferences.Select(m => m.Display).ToList(),
                    PreportMetaReferences = analyzer.ProjectBuildResult.PreportReferences,
                    ProjectRules = projectActions.ProjectRules,
                    ExternalReferences = analyzer.ProjectResult.ExternalReferences,
                    ProjectCompatibilityResult = compatibilityResults
                });
            }
            catch (Exception ex)
            {
                _logger.LogError("Error while analyzing {0}, {1}", project, ex);
                return(new ProjectAnalysisResult
                {
                    ProjectName = Path.GetFileNameWithoutExtension(project),
                    ProjectFilePath = project,
                    TargetFrameworks = new List <string>(),
                    PackageReferences = new List <PackageVersionPair>(),
                    ProjectReferences = new List <ProjectReference>(),
                    PackageAnalysisResults = new Dictionary <PackageVersionPair, Task <PackageAnalysisResult> >(),
                    IsBuildFailed = true,
                    Errors = new List <string> {
                        string.Format("Error while analyzing {0}, {1}", project, ex)
                    },
                    ProjectGuid = null,
                    ProjectType = null,
                    SourceFileAnalysisResults = new List <SourceFileAnalysisResult>()
                });
            }
            finally
            {
                CommonUtils.RunGarbageCollection(_logger, "PortingAssistantAnalysisHandler.AnalyzeProject");
            }
        }