/// <summary> /// Given a Repo and a Tree find any possible FalsePositives /// </summary> /// <param name="repo">Repo that has the remote changes that need to be checked</param> /// <param name="local">The syntax tree that will be compared with syntax trees from repo</param> public static IEnumerable <DetectedFalsePositive> ForFalsePositive(Repo repo, SyntaxTree local) { var relativePath = GetRelativePath(repo.LocalRepoDirectory, local.FilePath); var pulls = GetPulls(repo, relativePath); foreach (var pull in pulls) { var conflicts = Diff3.Compare(pull.File.BaseTree, local, pull.File.HeadTree); var locs = GetInsertedMethods(conflicts.Local); var rems = GetInsertedMethods(conflicts.Remote); var methodConflicts = conflicts.Conflicts.Where(con => con.Ancestor.Node is MethodDeclarationSyntax); foreach (var c in methodConflicts) { var ancestor = (MethodDeclarationSyntax)c.Ancestor.Node; var conflict = GetInnerMethodConflicts(ancestor, c.Remote, c.Local, locs, InnerMethodConflict.Local.Moved); //If the local was not moved, the local could have still been changed if (conflict == null) { conflict = GetInnerMethodConflicts(ancestor, c.Local, c.Remote, rems, InnerMethodConflict.Local.Changed); if (conflict == null) { continue; } } if (!conflict.DiffResult.Conflicts.Any(con => TriviaCompare.IsSemanticChange(con.Local.Node, con.Remote.Node))) { yield return(new DetectedFalsePositive { Location = Location.Create(local, conflict.GetLocal().Identifier.Span), MethodName = ancestor.Identifier.ToString(), RemoteFile = pull.File, RemoteChange = pull.Change, ConflictType = conflict.LocalLocation == InnerMethodConflict.Local.Changed ? DetectedFalsePositive.ConflictTypes.LocalMethodChanged : DetectedFalsePositive.ConflictTypes.LocalMethodRemoved, }); } } } }
private static InnerMethodConflict GetInnerMethodConflicts(MethodDeclarationSyntax ancestor, SpanDetails changed, SpanDetails removed, IEnumerable <MethodDeclarationSyntax> insertedMethods, InnerMethodConflict.Local type) { if (!TriviaCompare.IsSpanInNodeTrivia(removed.Span, removed.Node)) { return(null); } var change = changed.Node as MethodDeclarationSyntax; if (change == null) { return(null); } var moved = GetMovedMethod(insertedMethods, change); if (moved == null) { return(null); } var diffRes = Diff3.Compare(ancestor, moved, change); return(new InnerMethodConflict(ancestor, change, moved, diffRes, type)); }