public static DependencyGraph LoadGraph(Config config, List<OutputEntry> warnings)
        {
            ProjectLoader[] loaders = { new VsProjectsLoader(), new EclipseProjectsLoader() };

            var builder = new DependencyGraphBuilder(config, warnings);

            loaders.ForEach(l => l.LoadProjects(config.Inputs, builder, warnings));

            var graph = builder.Build();

            return graph;
        }
        protected override void InternalHandle(Output result, Config config, DependencyGraph graph)
        {
            var matches = RulesMatcher.Match(graph, config.Rules);

            if (!matches.Any())
            {
                result.AppendLine("No matches found");
                return;
            }

            foreach (var m in matches)
            {
                ConsoleEntryOutputer.ToConsole(m, false)
                    .Split('\n')
                    .ForEach(l => result.AppendLine(l));
                result.AppendLine();
            }
        }
        public Config ParseLines(string filename, string[] lines)
        {
            basePath = Path.GetDirectoryName(filename);
            config = new Config();

            var lineTypes = new Dictionary<string, Action<string, ConfigLocation>>
            {
                { "input:", ParseInput },
                { "group:", ParseGroup },
                { "output projects:", ParseOutputProjects },
                { "output groups:", ParseOutputGroups },
                { "output dependencies:", (line, loc) => ParseOutputDependencies(line, loc, false) },
                { "output dependencies with errors:", (line, loc) => ParseOutputDependencies(line, loc, true) },
                { "output architecture:", ParseOutputArchitecture },
                { "output results:", ParseOutputResults },
                { "rule:", ParseRule },
                { "ignore:", ParseIgnore },
                { "in output:", ParseInOutput },
            };

            var re = new Regex(@"(?<![a-zA-Z0-9])" + COMMENT, RegexOptions.IgnoreCase);

            foreach (var item in lines.Indexed())
            {
                // Line number starts in 1
                var location = new ConfigLocation(item.Index + 1, item.Item);
                var line = item.Item.Trim();

                var m = re.Match(line);
                if (m.Success)
                    line = line.Substring(0, m.Index)
                        .Trim();

                if (string.IsNullOrWhiteSpace(line))
                    continue;

                ParseLine(lineTypes, line, location);
            }

            return config;
        }
        public static ArchitectureGraph Load(Config config, DependencyGraph graph)
        {
            var rules = config.Rules.OfType<DepenendencyRule>()
                .Where(r => r.Severity == Severity.Error)
                .Cast<Rule>()
                .ToList();

            var libs = graph.Vertices.Where(v => v.GroupElement != null)
                .ToList();

            var allowed = new HashSet<GroupDependency>();
            var notAllowed = new HashSet<GroupDependency>();

            foreach (var p1 in libs)
            {
                foreach (var p2 in libs)
                {
                    if (p1.GroupElement.Name == p2.GroupElement.Name)
                        continue;

                    var dep = new GroupDependency(p1.GroupElement.Name, p2.GroupElement.Name);
                    if (allowed.Contains(dep) && notAllowed.Contains(dep))
                        continue;

                    var match = RulesMatcher.FindMatch(rules, Dependency.WithProject(p1, p2, new Location("a", 1))) as DependencyRuleMatch;
                    if (match != null)
                    {
                        if (match.Allowed)
                            allowed.Add(dep);
                        else
                            notAllowed.Add(dep);
                    }

                    match = RulesMatcher.FindMatch(rules, Dependency.WithLibrary(p1, p2, new Location("a", 1), null)) as DependencyRuleMatch;
                    if (match != null)
                    {
                        if (match.Allowed)
                            allowed.Add(dep);
                        else
                            notAllowed.Add(dep);
                    }
                }
            }

            var groups = libs.Select(p => p.GroupElement.Name)
                .Distinct()
                .ToList();

            var deps = new HashSet<GroupDependency>();
            foreach (var g1 in groups)
            {
                foreach (var g2 in groups)
                {
                    if (g1 == g2)
                        continue;

                    var dep = new GroupDependency(g1, g2);
                    var isAllowed = allowed.Contains(dep);
                    var isNotAllowed = notAllowed.Contains(dep);

                    if (isAllowed && isNotAllowed)
                        dep = new GroupDependency(g1, g2, GroupDependency.Types.Conflicted);
                    else if (!isAllowed && !isNotAllowed)
                        dep = new GroupDependency(g1, g2, GroupDependency.Types.Implicit);
                    else if (isNotAllowed)
                        dep = null;

                    if (dep != null)
                        deps.Add(dep);
                }
            }

            var groupGraph = new ArchitectureGraph();
            groupGraph.AddVertexRange(groups);
            groupGraph.AddEdgeRange(deps);
            return groupGraph;
        }
 public GroupsLoader(Config config, DependencyGraph graph, List<OutputEntry> warnings)
 {
     this.config = config;
     this.graph = graph;
     this.warnings = warnings;
 }
 protected abstract void InternalHandle(Output result, Config config, DependencyGraph graph);
 public DependencyGraphBuilder(Config config, List<OutputEntry> warnings)
 {
     this.config = config;
     this.warnings = warnings;
 }
 private static bool IsLocal(Config config, Library lib)
 {
     if (lib is Project)
         return config.Inputs.Any(input => PathUtils.PathMatches(((Project) lib).ProjectPath, input));
     else
         return config.Inputs.Any(input => lib.Paths.Any(p => PathUtils.PathMatches(p, input)));
 }