Beispiel #1
0
        /// <summary>
        /// Read issues from issue providers.
        /// </summary>
        /// <param name="format">Preferred format for comments.</param>
        /// <returns>List of issues.</returns>
        public IEnumerable <IIssue> ReadIssues(IssueCommentFormat format)
        {
            // Initialize issue providers and read issues.
            var issues = new List <IIssue>();

            foreach (var issueProvider in this.issueProviders)
            {
                var providerName = issueProvider.GetType().Name;
                this.log.Verbose("Initialize issue provider {0}...", providerName);
                if (issueProvider.Initialize(this.settings))
                {
                    this.log.Verbose("Reading issues from {0}...", providerName);
                    var currentIssues = issueProvider.ReadIssues(format).ToList();

                    this.log.Verbose(
                        "Found {0} issues using issue provider {1}...",
                        currentIssues.Count,
                        providerName);

                    issues.AddRange(currentIssues);
                }
                else
                {
                    this.log.Warning("Error initializing issue provider {0}.", providerName);
                }
            }

            return(issues);
        }
        /// <inheritdoc />
        public override IEnumerable <IIssue> ReadIssues(
            MarkdownlintIssuesProvider issueProvider,
            IssueCommentFormat format,
            RepositorySettings repositorySettings,
            MarkdownlintIssuesSettings markdownlintIssuesSettings)
        {
            issueProvider.NotNull(nameof(issueProvider));
            repositorySettings.NotNull(nameof(repositorySettings));
            markdownlintIssuesSettings.NotNull(nameof(markdownlintIssuesSettings));

            var regex = new Regex(@"(.*): (\d*): (MD\d*)/((?:\w*-*/*)*) (.*)");

            foreach (var line in markdownlintIssuesSettings.LogFileContent.ToStringUsingEncoding().Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None).ToList().Where(s => !string.IsNullOrEmpty(s)))
            {
                var groups = regex.Match(line).Groups;

                // Read affected file from the line.
                if (!this.TryGetFile(groups, repositorySettings, out string fileName))
                {
                    continue;
                }

                var lineNumber      = int.Parse(groups[2].Value);
                var rule            = groups[3].Value;
                var ruleDescription = groups[5].Value;

                yield return
                    (IssueBuilder
                     .NewIssue(ruleDescription, issueProvider)
                     .InFile(fileName, lineNumber)
                     .WithPriority(IssuePriority.Warning)
                     .OfRule(rule, MarkdownlintRuleUrlResolver.Instance.ResolveRuleUrl(rule))
                     .Create());
            }
        }
Beispiel #3
0
        /// <inheritdoc />
        protected override IEnumerable <IIssue> InternalReadIssues(IssueCommentFormat format)
        {
            // Determine path of the doc root.
            var docRootPath = this.IssueProviderSettings.DocRootPath;

            if (docRootPath.IsRelative)
            {
                docRootPath = docRootPath.MakeAbsolute(this.Settings.RepositoryRoot);
            }

            return
                (from logEntry in this.IssueProviderSettings.LogFileContent.ToStringUsingEncoding(true).Split(new[] { '{', '}' }, StringSplitOptions.RemoveEmptyEntries).Select(x => "{" + x + "}")
                 let logEntryObject = JsonConvert.DeserializeObject <JToken>(logEntry)
                                      let severity = (string)logEntryObject.SelectToken("message_severity")
                                                     let file = this.TryGetFile(logEntryObject, docRootPath)
                                                                let line = this.TryGetLine(logEntryObject)
                                                                           let message = (string)logEntryObject.SelectToken("message")
                                                                                         let source = (string)logEntryObject.SelectToken("source") ?? "DocFx"
                                                                                                      where
                                                                                                      severity == "warning" &&
                                                                                                      !string.IsNullOrWhiteSpace(message)
                                                                                                      select
                                                                                                      IssueBuilder
                                                                                                      .NewIssue(message, this)
                                                                                                      .InFile(file, line)
                                                                                                      .OfRule(source)
                                                                                                      .WithPriority(IssuePriority.Warning)
                                                                                                      .Create());
        }
Beispiel #4
0
 /// <inheritdoc/>
 public override IEnumerable <IIssue> ReadIssues(
     FakeMultiFormatIssueProvider issueProvider,
     IssueCommentFormat format,
     RepositorySettings repositorySettings,
     FakeMultiFormatIssueProviderSettings issueProviderSettings)
 {
     return(this.issues);
 }
Beispiel #5
0
 public override IEnumerable <IIssue> ReadIssues(
     MsBuildIssuesProvider issueProvider,
     IssueCommentFormat format,
     RepositorySettings repositorySettings,
     MsBuildIssuesSettings issueProviderSettings)
 {
     throw new NotImplementedException();
 }
        /// <inheritdoc/>
        public override IEnumerable <IIssue> ReadIssues(
            MsBuildIssuesProvider issueProvider,
            IssueCommentFormat format,
            RepositorySettings repositorySettings,
            MsBuildIssuesSettings issueProviderSettings)
        {
#pragma warning disable SA1123 // Do not place regions within elements
            #region DupFinder Exclusion
#pragma warning restore SA1123 // Do not place regions within elements

            issueProvider.NotNull(nameof(issueProvider));
            repositorySettings.NotNull(nameof(repositorySettings));
            issueProviderSettings.NotNull(nameof(issueProviderSettings));

            #endregion

            var result = new List <IIssue>();

            var binLogReader = new BinLogReader();
            foreach (var record in binLogReader.ReadRecords(issueProviderSettings.LogFileContent))
            {
                var buildEventArgs = record.Args;

                if (buildEventArgs is BuildWarningEventArgs buildWarning)
                {
                    var projectFileRelativePath = this.GetProject(buildWarning, repositorySettings);

                    // Read affected file from the warning.
                    if (!this.TryGetFile(buildWarning, repositorySettings, out string fileName))
                    {
                        continue;
                    }

                    var line = GetLine(buildWarning);
                    var rule = buildWarning.Code;

                    // Determine rule URL.
                    Uri ruleUrl = null;
                    if (!string.IsNullOrWhiteSpace(rule))
                    {
                        ruleUrl = MsBuildRuleUrlResolver.Instance.ResolveRuleUrl(rule);
                    }

                    // Build issue.
                    result.Add(
                        IssueBuilder
                        .NewIssue(buildWarning.Message, issueProvider)
                        .WithPriority(IssuePriority.Warning)
                        .InProject(projectFileRelativePath, System.IO.Path.GetFileNameWithoutExtension(projectFileRelativePath))
                        .InFile(fileName, line)
                        .OfRule(rule, ruleUrl)
                        .Create());
                }
            }

            return(result);
        }
 /// <inheritdoc/>
 protected override IEnumerable <IIssue> InternalReadIssues(IssueCommentFormat format)
 {
     return
         (this.IssueProviderSettings.Format.ReadIssues(
              (TIssueProvider)this,
              format,
              this.Settings,
              this.IssueProviderSettings));
 }
Beispiel #8
0
        /// <summary>
        /// Gets the message of the issue in a specific format.
        /// If the message is not available in the specific format, the message in
        /// text format will be returned.
        /// </summary>
        /// <param name="issue">Issue for which the message should be returned.</param>
        /// <param name="format">Format in which the message should be returned.</param>
        /// <returns>Message in the format specified by <paramref name="format"/> or message in text
        /// format if it is not available in the desired format.</returns>
        public static string Message(this IIssue issue, IssueCommentFormat format)
        {
            issue.NotNull(nameof(issue));

            return(format switch
            {
                IssueCommentFormat.PlainText => issue.MessageText,
                IssueCommentFormat.Html => !string.IsNullOrEmpty(issue.MessageHtml) ? issue.MessageHtml : issue.MessageText,
                IssueCommentFormat.Markdown => !string.IsNullOrEmpty(issue.MessageMarkdown) ? issue.MessageMarkdown : issue.MessageText,
                _ => throw new ArgumentOutOfRangeException(nameof(format)),
            });
        /// <inheritdoc />
        protected override IEnumerable <IIssue> InternalReadIssues(IssueCommentFormat format)
        {
            var result = new List <IIssue>();

            if (this.IssueProviderSettings.CheckBinaryFilesTrackedByLfs)
            {
                result.AddRange(this.CheckForBinaryFilesNotTrackedByLfs(format));
            }

            return(result);
        }
        /// <summary>
        /// Checks for binary files which are not tracked by LFS.
        /// </summary>
        /// <param name="format">Preferred format of the messages.</param>
        /// <returns>List of issues for binary files which are not tracked by LFS.</returns>
        private IEnumerable <IIssue> CheckForBinaryFilesNotTrackedByLfs(IssueCommentFormat format)
        {
            var allFiles = this.GetAllFilesFromRepository();

            if (!allFiles.Any())
            {
                return(new List <IIssue>());
            }

            var textFiles = this.GetTextFilesFromRepository();

            var binaryFiles = this.DetermineBinaryFiles(allFiles, textFiles);

            if (!binaryFiles.Any())
            {
                return(new List <IIssue>());
            }

            var lfsTrackedFiles            = this.GetLfsTrackedFilesFromRepository();
            var binaryFilesNotTrackedByLfs = this.DetermineBinaryFilesNotTrackedWithLfs(binaryFiles, lfsTrackedFiles);

            var result = new List <IIssue>();

            foreach (var file in binaryFilesNotTrackedByLfs)
            {
                string message = null;
                switch (format)
                {
                case IssueCommentFormat.Markdown:
                    message = $"The binary file `{file}` is not tracked by Git LFS";
                    break;

                case IssueCommentFormat.Html:
                    message = $"The binary file <pre>{file}</pre> is not tracked by Git LFS";
                    break;

                default:
                    message = $"The binary file \"{file}\" is not tracked by Git LFS";
                    break;
                }

                var ruleDescription = new BinaryFileNotTrackedByLfsRuleDescription();

                result.Add(
                    IssueBuilder
                    .NewIssue(message, this)
                    .InFile(file)
                    .OfRule(ruleDescription)
                    .Create());
            }

            return(result);
        }
Beispiel #11
0
        /// <summary>
        /// Gets the message of the issue in a specific format.
        /// If the message is not available in the specific format, the message in
        /// text format will be returned.
        /// </summary>
        /// <param name="issue">Issue for which the message should be returned.</param>
        /// <param name="format">Format in which the message should be returned.</param>
        /// <returns>Message in the format specified by <paramref name="format"/> or message in text
        /// format if it is not available in the desired format.</returns>
        public static string Message(this IIssue issue, IssueCommentFormat format)
        {
            issue.NotNull(nameof(issue));

            switch (format)
            {
            case IssueCommentFormat.PlainText:
                return(issue.MessageText);

            case IssueCommentFormat.Html:
                return(!string.IsNullOrEmpty(issue.MessageHtml) ? issue.MessageHtml : issue.MessageText);

            case IssueCommentFormat.Markdown:
                return(!string.IsNullOrEmpty(issue.MessageMarkdown) ? issue.MessageMarkdown : issue.MessageText);

            default:
                throw new ArgumentOutOfRangeException(nameof(format));
            }
        }
        /// <inheritdoc />
        public override IEnumerable <IIssue> ReadIssues(
            MarkdownlintIssuesProvider issueProvider,
            IssueCommentFormat format,
            RepositorySettings repositorySettings,
            MarkdownlintIssuesSettings markdownlintIssuesSettings)
        {
            issueProvider.NotNull(nameof(issueProvider));
            repositorySettings.NotNull(nameof(repositorySettings));
            markdownlintIssuesSettings.NotNull(nameof(markdownlintIssuesSettings));

            Dictionary <string, IEnumerable <Issue> > logFileEntries;

            using (var ms = new MemoryStream(markdownlintIssuesSettings.LogFileContent.RemovePreamble()))
            {
                var jsonSerializer = new DataContractJsonSerializer(
                    typeof(Dictionary <string, IEnumerable <Issue> >),
                    settings: new DataContractJsonSerializerSettings {
                    UseSimpleDictionaryFormat = true
                });

                logFileEntries = jsonSerializer.ReadObject(ms) as Dictionary <string, IEnumerable <Issue> >;
            }

            return
                (from file in logFileEntries
                 from entry in file.Value
                 let
                 rule = entry.ruleName
                        select
                        IssueBuilder
                        .NewIssue(entry.ruleDescription, issueProvider)
                        .InFile(file.Key, entry.lineNumber)
                        .WithPriority(IssuePriority.Warning)
                        .OfRule(rule, MarkdownlintRuleUrlResolver.Instance.ResolveRuleUrl(rule))
                        .Create());
        }
Beispiel #13
0
        /// <inheritdoc/>
        public override IEnumerable <IIssue> ReadIssues(
            MsBuildIssuesProvider issueProvider,
            IssueCommentFormat format,
            RepositorySettings repositorySettings,
            MsBuildIssuesSettings issueProviderSettings)
        {
#pragma warning disable SA1123 // Do not place regions within elements
            #region DupFinder Exclusion
#pragma warning restore SA1123 // Do not place regions within elements

            issueProvider.NotNull(nameof(issueProvider));
            repositorySettings.NotNull(nameof(repositorySettings));
            issueProviderSettings.NotNull(nameof(issueProviderSettings));

            #endregion

            var result = new List <IIssue>();

            // Read log file.
            var logDocument = XDocument.Parse(issueProviderSettings.LogFileContent.ToStringUsingEncoding(true));

            // Loop through all warning tags.
            foreach (var warning in logDocument.Descendants("warning"))
            {
                // Read affected project from the warning.
                if (!this.TryGetProject(warning, repositorySettings, out string projectFileRelativePath))
                {
                    continue;
                }

                // Read affected file from the warning.
                if (!this.TryGetFile(warning, repositorySettings, out string fileName))
                {
                    continue;
                }

                // Read affected line from the warning.
                if (!TryGetLine(warning, out var line))
                {
                    continue;
                }

                // Read rule code from the warning.
                if (!TryGetRule(warning, out string rule))
                {
                    continue;
                }

                // Determine rule URL.
                Uri ruleUrl = null;
                if (!string.IsNullOrWhiteSpace(rule))
                {
                    ruleUrl = MsBuildRuleUrlResolver.Instance.ResolveRuleUrl(rule);
                }

                // Build issue.
                result.Add(
                    IssueBuilder
                    .NewIssue(warning.Value, issueProvider)
                    .WithPriority(IssuePriority.Warning)
                    .InProject(projectFileRelativePath, System.IO.Path.GetFileNameWithoutExtension(projectFileRelativePath))
                    .InFile(fileName, line)
                    .OfRule(rule, ruleUrl)
                    .Create());
            }

            return(result);
        }
Beispiel #14
0
        /// <inheritdoc/>
        public IEnumerable <IIssue> ReadIssues(IssueCommentFormat format)
        {
            this.AssertInitialized();

            return(this.InternalReadIssues(format));
        }
Beispiel #15
0
 /// <inheritdoc/>
 public abstract IEnumerable <IIssue> ReadIssues(
     TIssueProvider issueProvider,
     IssueCommentFormat format,
     RepositorySettings repositorySettings,
     TSettings issueProviderSettings);
Beispiel #16
0
        /// <inheritdoc/>
        public IEnumerable <IIssue> ReadIssues(IssueCommentFormat format)
        {
            this.AssertSettings();

            return(this.InternalReadIssues(format));
        }
Beispiel #17
0
        public IEnumerable <IIssue> ReadIssues(IssueCommentFormat format)
        {
            var issueReader = new IssuesReader(this.Log, this.IssueProviders, this.Settings);

            return(issueReader.ReadIssues(format));
        }
 /// <inheritdoc/>
 protected override IEnumerable <IIssue> InternalReadIssues(IssueCommentFormat format)
 {
     this.Format = format;
     return(this.issues);
 }
        /// <inheritdoc />
        protected override IEnumerable <IIssue> InternalReadIssues(IssueCommentFormat format)
        {
            var result = new List <IIssue>();

            var logDocument = XDocument.Parse(this.IssueProviderSettings.LogFileContent.ToStringUsingEncoding());

            var solutionPath = Path.GetDirectoryName(logDocument.Descendants("Solution").Single().Value);

            // Read all issue types.
            var issueTypes =
                logDocument.Descendants("IssueType").ToDictionary(
                    x => x.Attribute("Id")?.Value,
                    x => new IssueType
            {
                Severity = x.Attribute("Severity").Value,
                WikiUrl  = x.Attribute("WikiUrl")?.Value.ToUri()
            });

            // Loop through all issue tags.
            foreach (var issue in logDocument.Descendants("Issue"))
            {
                // Read affected project from the issue.
                if (!TryGetProject(issue, out string projectName))
                {
                    continue;
                }

                // Read affected file from the issue.
                if (!TryGetFile(issue, solutionPath, out string fileName))
                {
                    continue;
                }

                // Read affected line from the issue.
                if (!TryGetLine(issue, out int line))
                {
                    continue;
                }

                // Read rule code from the issue.
                if (!TryGetRule(issue, out string rule))
                {
                    continue;
                }

                // Read message from the issue.
                if (!TryGetMessage(issue, out string message))
                {
                    continue;
                }

                // Determine issue type properties.
                var issueType = issueTypes[rule];
                var severity  = issueType.Severity.ToLowerInvariant();
                var ruleUrl   = issueType.WikiUrl;

                // Build issue.
                result.Add(
                    IssueBuilder
                    .NewIssue(message, this)
                    .InProjectOfName(projectName)
                    .InFile(fileName, line)
                    .WithPriority(GetPriority(severity))
                    .OfRule(rule, ruleUrl)
                    .Create());
            }

            return(result);
        }
Beispiel #20
0
 /// <summary>
 /// Gets all issues.
 /// Compared to <see cref="ReadIssues"/> it is safe to access Settings from this method.
 /// </summary>
 /// <param name="format">Preferred format of the comments.</param>
 /// <returns>List of issues</returns>
 protected abstract IEnumerable <IIssue> InternalReadIssues(IssueCommentFormat format);
Beispiel #21
0
 /// <inheritdoc />
 protected override IEnumerable <IIssue> InternalReadIssues(IssueCommentFormat format)
 {
     return(this.msBuildIssuesSettings.Format.ReadIssues(this.Settings, this.msBuildIssuesSettings));
 }