コード例 #1
0
        public override List<OutputEntry> Process(DependencyGraph graph, Library element)
        {
            var proj = element as Project;
            if (proj == null)
                return null;

            var result = new List<OutputEntry>();

            var same = graph.OutEdges(proj)
                .Where(d => filter(d, Matchers.NullReporter))
                .GroupBy(d => d.Target)
                .Where(g => g.Count() > 1);

            same.ForEach(g =>
            {
                var message = new OutputMessage();
                message.Append("The project ")
                    .Append(proj, OutputMessage.ProjInfo.Name)
                    .Append(" has multiple dependencies with ")
                    .Append(g.Key, OutputMessage.ProjInfo.Name);

                result.Add(new UniqueDependencyOutputEntry(Severity, message, this, g));
            });

            return result;
        }
コード例 #2
0
        protected BaseOutputEntry(string type, Severity severity, OutputMessage messsage, IEnumerable<Library> projects = null,
            IEnumerable<Dependency> dependencies = null, IEnumerable<ProcessedField> processedFields = null)
        {
            Type = type;
            Severity = severity;
            Messsage = messsage;

            if (dependencies == null)
                dependencies = messsage.Elements.Select(e => e.Dependendcy)
                    .Where(d => d != null)
                    .Distinct();

            Dependencies = dependencies.ToList();
            Dependencies.Sort(Dependency.NaturalOrdering);

            if (projects == null)
                projects = messsage.Elements.Select(e => e.Project)
                    .Concat(Dependencies.Select(d => d.Source))
                    .Concat(Dependencies.Select(d => d.Target))
                    .Where(p => p != null)
                    .Distinct();

            Projects = projects.ToList();
            Projects.Sort(Library.NaturalOrdering);

            ProcessedFields = processedFields != null ? processedFields.ToList() : new List<ProcessedField>();
        }
コード例 #3
0
        public override List<OutputEntry> Process(DependencyGraph graph)
        {
            var result = new List<OutputEntry>();

            graph.Edges.Where(d => filter(d, Matchers.NullReporter))
                .Where(e => e.Source.Equals(e.Target))
                .GroupBy(e => e.Source)
                .ForEach(deps =>
                {
                    var message = new OutputMessage();
                    message.Append(deps.Key, OutputMessage.ProjInfo.Name)
                        .Append(" depends on itself");
                    result.Add(new SelfDependencyRuleMatch(Severity, message, this, deps));
                });

            return result;
        }
コード例 #4
0
        public override List<OutputEntry> Process(DependencyGraph graph)
        {
            var result = new List<OutputEntry>();

            IDictionary<Library, int> components;
            graph.StronglyConnectedComponents(out components);

            var circularDependencies = components.Select(c => new { Proj = c.Key, Group = c.Value })
                .GroupBy(c => c.Group)
                .Where(g => g.Count() > 1);

            foreach (var g in circularDependencies)
            {
                var projs = g.Select(i => i.Proj)
                    .ToList();
                projs.Sort(Library.NaturalOrdering);

                var projsSet = new HashSet<Library>(projs);

                var deps = graph.Edges.Where(e => projsSet.Contains(e.Source) && projsSet.Contains(e.Target));

                var message = new OutputMessage();
                message.Append("Circular dependency found between projects ");

                var first = true;
                foreach (var proj in projs)
                {
                    if (first)
                        first = false;
                    else
                        message.Append(", ");

                    message.Append(proj, OutputMessage.ProjInfo.Name);
                }

                result.Add(new CircularDependencyRuleMatch(Severity, message, this, deps));
            }

            return result;
        }
コード例 #5
0
        public override List<OutputEntry> Process(DependencyGraph graph)
        {
            var result = new List<OutputEntry>();

            var same = graph.Vertices.OfType<Project>()
                .Where(v => filter(v))
                .GroupBy(v => id(v))
                .Where(g => g.Count() > 1);
            same.ForEach(g =>
            {
                var projs = g.ToList();

                var message = new OutputMessage();
                message.Append(projs.Count())
                    .Append(" projects ")
                    .Append(description(projs.First()))
                    .Append(" found");

                result.Add(new UniqueProjectOutputEntry(Severity, message, this, projs));
            });

            return result;
        }
コード例 #6
0
        public override OutputEntry Process(Dependency dep)
        {
            var fields = new List<ProcessedField>();

            if (!Dependency(dep, (f, v, m) => fields.Add(new ProcessedField("Dependency " + f, v, m))))
                return null;

            if (!Matches(Source, dep.Source, (f, v, m) => fields.Add(new ProcessedField("Source " + f, v, m))))
                return null;

            if (!Matches(Target, dep.Target, (f, v, m) => fields.Add(new ProcessedField("Target " + f, v, m))))
                return null;

            var messsage = new OutputMessage();
            messsage.Append("Dependency between ")
                .Append(dep.Source, OutputMessage.ProjInfo.Name)
                .Append(" and ")
                .Append(dep.Target, OutputMessage.ProjInfo.Name)
                .Append(Allow ? "" : " not")
                .Append(" allowed");

            return new DependencyRuleMatch(Allow, "Dependency", Severity, messsage, this, dep.AsList(), fields);
        }
コード例 #7
0
 private static string ToConsole(Dependency dep, OutputMessage.DepInfo info)
 {
     switch (info)
     {
         case OutputMessage.DepInfo.Type:
         {
             switch (dep.Type)
             {
                 case Dependency.Types.LibraryReference:
                     return "library reference";
                 case Dependency.Types.ProjectReference:
                     return "project reference";
                 default:
                     throw new InvalidDataException();
             }
         }
         case OutputMessage.DepInfo.Line:
         {
             return "line " + dep.Location.Line;
         }
         case OutputMessage.DepInfo.FullDescription:
         {
             return string.Format("{0} in {1} of {2} pointing to {3}", ToConsole(dep, OutputMessage.DepInfo.Type),
                 ToConsole(dep, OutputMessage.DepInfo.Line), ToConsole(dep.Source, OutputMessage.ProjInfo.NameAndProjectPath),
                 ToConsole(dep.Target, OutputMessage.ProjInfo.NameAndPath));
         }
         default:
             throw new InvalidDataException();
     }
 }
コード例 #8
0
        private static string ToConsole(Library proj, OutputMessage.ProjInfo info)
        {
            switch (info)
            {
                case OutputMessage.ProjInfo.Name:
                {
                    return string.Join(" or ", proj.SortedNames);
                }
                case OutputMessage.ProjInfo.NameAndGroup:
                {
                    var result = ToConsole(proj, OutputMessage.ProjInfo.Name);

                    var group = proj.GroupElement;
                    if (group != null)
                        result = string.Format("{0} (in group {1})", result, group.Name);

                    return result;
                }
                case OutputMessage.ProjInfo.NameAndProjectPath:
                {
                    return string.Format("{0} ({1})", ToConsole(proj, OutputMessage.ProjInfo.Name), ToConsole(proj, OutputMessage.ProjInfo.ProjectPath));
                }
                case OutputMessage.ProjInfo.NameAndPath:
                {
                    if (proj.Paths.Any())
                        return string.Format("{0} ({1})", ToConsole(proj, OutputMessage.ProjInfo.Name), ToConsole(proj, OutputMessage.ProjInfo.Path));
                    else
                        return ToConsole(proj, OutputMessage.ProjInfo.Name);
                }
                case OutputMessage.ProjInfo.Path:
                {
                    if (proj.Paths.Any())
                        return string.Join(" or ", proj.Paths);
                    else
                        return ToConsole(proj, OutputMessage.ProjInfo.Name);
                }
                case OutputMessage.ProjInfo.ProjectPath:
                {
                    if (proj is Project)
                        return ((Project) proj).ProjectPath;
                    else
                        throw new InvalidDataException();
                }
                default:
                    throw new InvalidDataException();
            }
        }
コード例 #9
0
        public static string ToConsole(OutputMessage messsage)
        {
            return string.Join("", messsage.Elements.Select(e =>
            {
                if (e.Text != null)
                    return e.Text;

                else if (e.Project != null)
                    return ToConsole(e.Project, e.ProjInfo);

                else if (e.Dependendcy != null)
                    return ToConsole(e.Dependendcy, e.DepInfo);

                else
                    throw new InvalidDataException();
            }));
        }
コード例 #10
0
 public UniqueProjectOutputEntry(Severity severity, OutputMessage messsage, Rule rule, IEnumerable<Library> projs)
     : base("Non unique project", severity, messsage, rule, projs, null)
 {
 }
コード例 #11
0
        private OutputEntry CreateMultipleReferencesWarning(List<Library> candidates, Project proj, Dependency dep, string refName)
        {
            var message = new OutputMessage().Append("The project ")
                .Append(proj, OutputMessage.ProjInfo.NameAndProjectPath)
                .Append(" references the project ")
                .Append(refName)
                .Append(", but there are ")
                .Append(candidates.Count)
                .Append(" projects that match:");

            candidates.ForEach(c => message.Append("\n  - ")
                .Append(c, OutputMessage.ProjInfo.ProjectPath));
            message.Append("\nMultiple dependencies will be created.");

            return new LoadingOutputEntry("Multiple projects found", message, candidates.Select(dep.WithTarget)
                .ToArray());
        }
コード例 #12
0
 protected BaseOutputEntry(string type, Severity severity, OutputMessage messsage, IEnumerable<Dependency> dependencies)
     : this(type, severity, messsage, null, dependencies)
 {
 }
コード例 #13
0
 public LoadingOutputEntry(string type, OutputMessage messsage, params Dependency[] dependencies)
     : base("Loading/" + type, Severity.Info, messsage, dependencies)
 {
 }
コード例 #14
0
        private void WarnIfSimilarFound(List<Library> result, Project proj, Dependency dep, string filename, string refName)
        {
            if (result == null || !result.Any())
                return;

            var message = new OutputMessage().Append("The project ")
                .Append(proj, OutputMessage.ProjInfo.Name)
                .Append(" references the project ")
                .Append(filename)
                .Append(" but it could not be loaded. Using project")
                .Append(result.Count > 1 ? "s" : "")
                .Append(" ")
                .Append(refName)
                .Append(" instead:");

            if (result.Count == 1)
                result.ForEach(p => message.Append(result.First(), OutputMessage.ProjInfo.ProjectPath));
            else
                result.ForEach(p => message.Append("\n  - ")
                    .Append(p, OutputMessage.ProjInfo.ProjectPath));

            warnings.Add(new LoadingOutputEntry("Only similar project found", message, result.Select(dep.WithTarget)
                .ToArray()));
        }
コード例 #15
0
 protected RuleOutputEntry(string type, Severity severity, OutputMessage messsage, Rule rule, IEnumerable<Library> projects = null,
     IEnumerable<Dependency> dependencies = null, IEnumerable<ProcessedField> processedFields = null)
     : base(type, severity, messsage, projects, dependencies, processedFields)
 {
     Rule = rule;
 }
コード例 #16
0
 protected RuleOutputEntry(string type, Severity severity, OutputMessage messsage, Rule rule, IEnumerable<Dependency> dependencies)
     : base(type, severity, messsage, dependencies)
 {
     Rule = rule;
 }
コード例 #17
0
 public DependencyRuleMatch(bool allowed, string type, Severity severity, OutputMessage messsage, Rule rule, IEnumerable<Dependency> deps,
     IEnumerable<ProcessedField> processedFields)
     : base(type, severity, messsage, rule, null, deps.ToList(), processedFields)
 {
     Allowed = allowed;
 }
コード例 #18
0
 public CircularDependencyRuleMatch(Severity severity, OutputMessage messsage, Rule rule, IEnumerable<Dependency> deps)
     : base("Circular dependency", severity, messsage, rule, deps)
 {
 }
コード例 #19
0
 public UniqueDependencyOutputEntry(Severity severity, OutputMessage messsage, Rule rule, IEnumerable<Dependency> deps)
     : base("Non unique dependency", severity, messsage, rule, deps.ToList())
 {
 }
コード例 #20
0
        private static void LoadProjects(List<string> paths, DependencyGraphBuilder builder, List<OutputEntry> warnings, string filenamePattern,
            params string[] defaultLanguage)
        {
            var csprojsFiles =
                new HashSet<string>(paths.SelectMany(folder => Directory.GetFiles(folder, filenamePattern, SearchOption.AllDirectories))
                    .Select(Path.GetFullPath));

            List<VSProjReader> csprojs = csprojsFiles.Select(f => new VSProjReader(f))
                .OrderBy(n => n.Filename, StringComparer.CurrentCultureIgnoreCase)
                .ToList();
            foreach (VSProjReader csproj in csprojs)
            {
                object proj = builder.AddProject(csproj.Name, csproj.AssemblyName, csproj.ProjectGuid, csproj.Filename, defaultLanguage);

                foreach (VSProjReader.ProjectReference csref in csproj.ProjectReferences)
                    builder.AddProjectReference(proj, csref.Name, null, csref.ProjectGuid, csref.Include, new Location(csproj.Filename, csref.LineNumber),
                        defaultLanguage);

                foreach (VSProjReader.Reference csref in csproj.References)
                {
                    IEnumerable<string> language;
                    if (csref.HintPath == null && csref.Include.GetPublicKey() == null)
                        // A system lib
                        language = defaultLanguage;
                    else
                        language = null;

                    builder.AddLibraryReference(proj, null, csref.Include.Name, null, csref.HintPath, new Location(csproj.Filename, csref.LineNumber),
                        language);
                }

                foreach (VSProjReader.COMReference csref in csproj.COMReferences)
                    builder.AddLibraryReference(proj, null, csref.Include, csref.Guid, null, new Location(csproj.Filename, csref.LineNumber), null);
            }

            var externalCsprojFiles = csprojs.SelectMany(p => p.ProjectReferences)
                .Select(r => r.Include)
                .Distinct()
                .Where(f => !csprojsFiles.Contains(f))
                .OrderBy(n => n, StringComparer.CurrentCultureIgnoreCase);
            foreach (string externalCsprojFile in externalCsprojFiles)
            {
                if (paths.Any(p => externalCsprojFile.StartsWith(p + Path.DirectorySeparatorChar)))
                {
                    OutputMessage msg = new OutputMessage().Append("Failed to load a referenced project: ")
                        .Append(externalCsprojFile);
                    warnings.Add(new LoadingOutputEntry("Referenced project not found", msg));
                    continue;
                }

                try
                {
                    var csproj = new VSProjReader(externalCsprojFile);
                    builder.AddProject(csproj.Name, csproj.AssemblyName, csproj.ProjectGuid, csproj.Filename, defaultLanguage);
                }
                catch (IOException)
                {
                    OutputMessage msg = new OutputMessage().Append("Failed to load a project outside of input folders: ")
                        .Append(externalCsprojFile);
                    warnings.Add(new LoadingOutputEntry("External project not found", msg));
                }
            }
        }
コード例 #21
0
        private Project CreateFakeProject(Project proj, Dependency dep, TempReference reference)
        {
            var result = new Project(reference.ReferenceName ?? reference.ReferenceLibraryName,
                reference.ReferenceLibraryName ?? reference.ReferenceName, reference.ReferenceGuid ?? Guid.NewGuid(), reference.ReferenceFilename, null);

            if (Ignore(result))
                return null;

            if (reference.ReferenceName == null || reference.ReferenceLibraryName == null)
            {
                var guessed = reference.ReferenceName == null ? "project name" : "library name";
                var used = reference.ReferenceName == null ? "library name" : "project name";

                var msg = new OutputMessage().Append("The project ")
                    .Append(proj, OutputMessage.ProjInfo.Name)
                    .Append(" references the project ")
                    .Append(reference.ReferenceFilename ?? reference.ReferenceName ?? reference.ReferenceLibraryName)
                    .Append(" but it could not be loaded. Guessing the ")
                    .Append(guessed)
                    .Append(" to be the same as the ")
                    .Append(used)
                    .Append(".");

                warnings.Add(new LoadingOutputEntry("Project not found", msg, dep.WithTarget(result)));
            }

            AddLibrary(result);

            return result;
        }