1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
20
using System.Collections.Generic;
21
using System.Diagnostics;
23
using System.Threading;
24
using ICSharpCode.NRefactory.CSharp;
25
using ICSharpCode.NRefactory.CSharp.Resolver;
26
using ICSharpCode.NRefactory.Semantics;
27
using ICSharpCode.NRefactory.TypeSystem;
29
namespace ICSharpCode.NRefactory.ConsistencyCheck
31
public class FindReferencesConsistencyCheck
33
readonly Solution solution;
34
Dictionary<IEntity, HashSet<AstNode>> referenceDict = new Dictionary<IEntity, HashSet<AstNode>>();
36
public FindReferencesConsistencyCheck(Solution solution)
38
this.solution = solution;
43
using (new Timer("Finding referenced entities... ")) {
44
foreach (var file in solution.AllFiles) {
45
var navigator = new FindReferencedEntities(
46
delegate (AstNode node, IEntity entity) {
48
throw new ArgumentNullException("node");
50
throw new ArgumentNullException("entity");
52
if (!IgnoreEntity(entity)) {
53
HashSet<AstNode> list;
54
if (!referenceDict.TryGetValue(entity, out list)) {
55
list = new HashSet<AstNode>();
56
referenceDict.Add(entity, list);
62
file.CreateResolver().ApplyNavigator(navigator);
65
Console.WriteLine("For each entity, find all references...");
66
Stopwatch w = Stopwatch.StartNew();
67
foreach (var project in solution.Projects) {
68
foreach (var type in project.Compilation.MainAssembly.GetAllTypeDefinitions()) {
69
TestFindReferences(type);
70
foreach (IMember m in type.Members) {
71
TestFindReferences(m);
77
Console.WriteLine("FindReferencesConsistencyCheck is done ({0}).", w.Elapsed);
78
PrintTimingsPerEntityType();
81
bool IgnoreEntity(IEntity entity)
84
//return entity.FullName != "ICSharpCode.NRefactory.TypeSystem.Implementation.DefaultResolvedTypeDefinition.parts";
87
Dictionary<EntityType, TimeSpan> timings = new Dictionary<EntityType, TimeSpan>();
88
Dictionary<EntityType, int> entityCount = new Dictionary<EntityType, int>();
90
void TestFindReferences(IEntity entity)
92
if (IgnoreEntity(entity))
94
FindReferences fr = new FindReferences();
95
fr.FindTypeReferencesEvenIfAliased = true;
97
Stopwatch w = new Stopwatch();
98
var searchScopes = fr.GetSearchScopes(entity);
99
foreach (var project in solution.Projects) {
101
HashSet<AstNode> foundReferences = new HashSet<AstNode>();
102
var interestingFiles = new HashSet<CSharpFile>();
103
foreach (var searchScope in searchScopes) {
104
foreach (var unresolvedFile in fr.GetInterestingFiles(searchScope, project.Compilation)) {
105
var file = project.Files.Single(f => f.FileName == unresolvedFile.FileName);
106
Debug.Assert(file.UnresolvedTypeSystemForFile == unresolvedFile);
108
// Skip file if it doesn't contain the search term
109
if (searchScope.SearchTerm != null && file.OriginalText.IndexOf(searchScope.SearchTerm, StringComparison.Ordinal) < 0)
112
interestingFiles.Add(file);
115
foreach (var file in interestingFiles) {
116
fr.FindReferencesInFile(searchScopes, file.UnresolvedTypeSystemForFile, file.SyntaxTree, project.Compilation,
117
delegate(AstNode node, ResolveResult result) {
118
foundReferences.Add(node);
119
}, CancellationToken.None);
122
if (timings.ContainsKey(entity.EntityType)) {
123
timings[entity.EntityType] += w.Elapsed;
125
timings[entity.EntityType] = w.Elapsed;
129
IEntity importedEntity = project.Compilation.Import(entity);
131
HashSet<AstNode> expectedReferences;
132
if (importedEntity == null || !referenceDict.TryGetValue(importedEntity, out expectedReferences)) {
133
if (foundReferences.Any()) {
134
// There aren't any expected references stored, but we found some references anyways:
136
Console.WriteLine("Entity not in reference dictionary: " + entity);
140
if (foundReferences.Except(expectedReferences).Any()) {
142
Console.WriteLine("Reference mismatch for " + entity + ":");
143
var n = foundReferences.Except(expectedReferences).First();
144
Console.WriteLine("Found unexpected reference " + n + " (" + n.GetRegion() + ")");
146
if (expectedReferences.Except(foundReferences).Any()) {
148
Console.WriteLine("Reference mismatch for " + entity + ":");
149
var n = expectedReferences.Except(foundReferences).First();
150
Console.WriteLine("Did not find expected reference " + n + " (" + n.GetRegion() + ")");
154
if (entityCount.ContainsKey(entity.EntityType)) {
155
entityCount[entity.EntityType]++;
157
entityCount[entity.EntityType] = 1;
161
void PrintTimingsPerEntityType()
163
foreach (var pair in entityCount) {
164
Console.WriteLine("{0} - avg. {1} per entity", pair.Key, TimeSpan.FromSeconds(timings[pair.Key].TotalSeconds / pair.Value));