/// <summary> /// Returns language for given file name /// </summary> /// <param name="fileName">File name</param> /// <returns>Language</returns> public static bool FromFileName(string fileName, ref LanguageInfo info) { if (fileName == null) { return(false); } bool result = false; string file = Path.GetFileName(fileName).ToLower(CultureInfo.CurrentCulture); string ext = Path.GetExtension(file); // Look for whole filename first foreach (LanguageInfo item in Instance.Languages) { if (item.Name == file) { info = item; result = true; break; } } // Look for extension only ext is defined if (!string.IsNullOrEmpty(ext)) { foreach (LanguageInfo item in Instance.Languages) { if (Array.Exists(item.Extensions, x => x.EndsWith(ext))) { info = item; result = true; break; } } } return(result); }
/// <summary> /// Analyzes given line of code /// </summary> /// <param name="text">Source code</param> /// <param name="languages">List of languages</param> /// <returns>Array of matches</returns> public Issue[] Analyze(string text, LanguageInfo languageInfo) { string[] languages = new string[] { languageInfo.Name }; // Get rules for the given content type IEnumerable <Rule> rules = GetRulesForLanguages(languages); List <Issue> resultsList = new List <Issue>(); TextContainer textContainer = new TextContainer(text, (languages.Length > 0) ? languages[0] : string.Empty, _stopAfterFirstPatternMatch); // Go through each rule foreach (Rule rule in rules) { if (_logger != null) { _logger.Debug("Processing for rule: " + rule.Id); } // Skip pattern matching this rule if uniquetag option and not in exceptions list bool multipleMatchesOk = !_uniqueTagMatchesOnly || UniqueTagsCheck(rule.Tags); if (!multipleMatchesOk) { continue; } List <Issue> matchList = new List <Issue>(); // Skip rules that don't apply based on settings if (rule.Disabled || !SeverityLevel.HasFlag(rule.Severity)) { continue; } // Go through each matching pattern of the rule foreach (SearchPattern pattern in rule.Patterns) { //Skill patterns that don't apply based on settings if (!ConfidenceLevelFilter.HasFlag(pattern.Confidence)) { continue; } // Get all matches for the patttern List <Boundary> matches = textContainer.MatchPattern(pattern); if (matches.Count > 0) { foreach (Boundary match in matches) { bool passedConditions = true; foreach (SearchCondition condition in rule.Conditions) { bool res = textContainer.MatchPattern(condition.Pattern, match, condition); if (res && condition.NegateFinding) { passedConditions = false; break; } if (!res && condition.NegateFinding) { passedConditions = true; break; } if (!res) { passedConditions = false; break; } } //do not accept features from build type files (only metadata) to avoid false positives that are not part of the executable program if (languageInfo.Type == LanguageInfo.LangFileType.Build && rule.Tags.Any(v => !v.Contains("Metadata"))) { passedConditions = false; } if (passedConditions) { Issue issue = new Issue() { Boundary = match, StartLocation = textContainer.GetLocation(match.Index), EndLocation = textContainer.GetLocation(match.Index + match.Length), PatternMatch = pattern, Confidence = pattern.Confidence, Rule = rule }; //check at pattern level to avoid adding duplicates if (_uniqueTagMatchesOnly && !UniqueTagsCheck(rule.Tags)) { break; } AddRuleTagHashes(rule.Tags); matchList.Add(issue); } } } } // We got matching rule and suppression are enabled, // let's see if we have a supression on the line if (EnableSuppressions && matchList.Count > 0) { Suppression supp; foreach (Issue result in matchList) { supp = new Suppression(textContainer.GetLineContent(result.StartLocation.Line)); // If rule is NOT being suppressed then report it SuppressedIssue supissue = supp.GetSuppressedIssue(result.Rule.Id); if (supissue == null) { resultsList.Add(result); } // Otherwise add the suppression info instead else { Boundary bound = textContainer.GetLineBoundary(result.Boundary.Index); bound.Index += supissue.Boundary.Index; bound.Length = supissue.Boundary.Length; //resultsList.Add(); Issue info = new Issue() { IsSuppressionInfo = true, Boundary = bound, StartLocation = textContainer.GetLocation(bound.Index), EndLocation = textContainer.GetLocation(bound.Index + bound.Length), Rule = result.Rule }; // Add info only if it's not exists on the same location if (resultsList.FirstOrDefault(x => x.Rule.Id == info.Rule.Id && x.Boundary.Index == info.Boundary.Index) == null) { resultsList.Add(info); } } } } // Otherwise put matchlist to resultlist else { resultsList.AddRange(matchList); } } // Deal with overrides List <Issue> removes = new List <Issue>(); foreach (Issue m in resultsList) { if (m.Rule.Overrides != null && m.Rule.Overrides.Length > 0) { foreach (string ovrd in m.Rule.Overrides) { // Find all overriden rules and mark them for removal from issues list foreach (Issue om in resultsList.FindAll(x => x.Rule.Id == ovrd)) { if (om.Boundary.Index >= m.Boundary.Index && om.Boundary.Index <= m.Boundary.Index + m.Boundary.Length) { removes.Add(om); } } } } } // Remove overriden rules resultsList.RemoveAll(x => removes.Contains(x)); return(resultsList.ToArray()); }