Browse Source

Implemented the new options for overridden members in FindReferences.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
d4dd1648e8
  1. 10
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs
  2. 143
      ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs
  3. 12
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  4. 66
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/FindReferencesTest.cs
  5. 2
      ICSharpCode.NRefactory/Documentation/IdStringProvider.cs
  6. 19
      ICSharpCode.NRefactory/Semantics/Conversion.cs
  7. 25
      ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs
  8. 12
      ICSharpCode.NRefactory/Semantics/ThisResolveResult.cs
  9. 32
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedMember.cs

10
ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs

@ -805,10 +805,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -805,10 +805,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
var or = rr.PerformOverloadResolution(compilation, args, allowExpandingParams: false, conversions: this);
if (or.FoundApplicableCandidate)
return Conversion.MethodGroupConversion((IMethod)or.GetBestCandidateWithSubstitutedTypeArguments());
else
if (or.FoundApplicableCandidate) {
IMethod method = (IMethod)or.GetBestCandidateWithSubstitutedTypeArguments();
var thisRR = rr.TargetResult as ThisResolveResult;
bool isVirtual = method.IsOverridable && !(thisRR != null && thisRR.CausesNonVirtualInvocation);
return Conversion.MethodGroupConversion(method, isVirtual);
} else {
return Conversion.None;
}
}
#endregion

143
ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.Refactoring;
@ -143,6 +144,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -143,6 +144,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
internal string searchTerm;
internal FindReferences findReferences;
internal ICompilation declarationCompilation;
internal Accessibility accessibility;
internal ITypeDefinition topLevelTypeDefinition;
@ -152,6 +154,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -152,6 +154,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
FindReferenceNavigator n = factory(compilation);
if (n != null) {
n.callback = callback;
n.findReferences = findReferences;
return n;
} else {
return new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Skip, null);
@ -178,6 +181,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -178,6 +181,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
abstract class FindReferenceNavigator : IResolveVisitorNavigator
{
internal FoundReferenceCallback callback;
internal FindReferences findReferences;
internal abstract bool CanMatch(AstNode node);
internal abstract bool IsMatch(ResolveResult rr);
@ -218,6 +222,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -218,6 +222,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
if (entity == null)
throw new ArgumentNullException("entity");
if (entity is IMember)
entity = NormalizeMember((IMember)entity);
Accessibility effectiveAccessibility = GetEffectiveAccessibility(entity);
ITypeDefinition topLevelTypeDefinition = entity.DeclaringTypeDefinition;
while (topLevelTypeDefinition != null && topLevelTypeDefinition.DeclaringTypeDefinition != null)
@ -252,7 +258,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -252,7 +258,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
scope = GetSearchScopeForOperator((IMethod)entity);
break;
case EntityType.Constructor:
IMethod ctor = (IMethod)((IMethod)entity).MemberDefinition;
IMethod ctor = (IMethod)entity;
scope = FindObjectCreateReferences(ctor);
additionalScope = FindChainedConstructorReferences(ctor);
break;
@ -266,11 +272,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -266,11 +272,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
scope.accessibility = effectiveAccessibility;
scope.declarationCompilation = entity.Compilation;
scope.topLevelTypeDefinition = topLevelTypeDefinition;
scope.findReferences = this;
if (additionalScope != null) {
if (additionalScope.accessibility == Accessibility.None)
additionalScope.accessibility = effectiveAccessibility;
additionalScope.declarationCompilation = entity.Compilation;
additionalScope.topLevelTypeDefinition = topLevelTypeDefinition;
additionalScope.findReferences = this;
return new[] { scope, additionalScope };
} else {
return new[] { scope };
@ -418,17 +426,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -418,17 +426,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (searchTerm.Length > 9 && searchTerm.EndsWith("Attribute", StringComparison.Ordinal)) {
// The type might be an attribute, so we also need to look for the short form:
string shortForm = searchTerm.Substring(0, searchTerm.Length - 9);
additionalScope = new SearchScope(
shortForm,
delegate (ICompilation compilation) {
ITypeDefinition imported = compilation.Import(typeDefinition);
if (imported != null)
return new FindTypeDefinitionReferencesNavigator(imported, shortForm);
else
return null;
});
additionalScope = FindTypeDefinitionReferences(typeDefinition, shortForm);
}
}
return FindTypeDefinitionReferences(typeDefinition, searchTerm);
}
SearchScope FindTypeDefinitionReferences(ITypeDefinition typeDefinition, string searchTerm)
{
return new SearchScope(
searchTerm,
delegate (ICompilation compilation) {
@ -495,11 +500,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -495,11 +500,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
SearchScope FindMemberReferences(IEntity member, Func<IMember, FindMemberReferencesNavigator> factory)
{
string searchTerm = member.Name;
IMember memberDefinition = ((IMember)member).MemberDefinition;
return new SearchScope(
searchTerm,
delegate(ICompilation compilation) {
IMember imported = compilation.Import(memberDefinition);
IMember imported = compilation.Import((IMember)member);
return imported != null ? factory(imported) : null;
});
}
@ -511,7 +515,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -511,7 +515,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public FindMemberReferencesNavigator(IMember member)
{
this.member = member.MemberDefinition;
this.member = member;
this.searchTerm = member.Name;
}
@ -539,10 +543,60 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -539,10 +543,60 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool IsMatch(ResolveResult rr)
{
MemberResolveResult mrr = rr as MemberResolveResult;
return mrr != null && member == mrr.Member.MemberDefinition;
return mrr != null && findReferences.IsMemberMatch(member, mrr.Member, mrr.IsVirtualCall);
}
}
IMember NormalizeMember(IMember member)
{
if (WholeVirtualSlot && member.IsOverride)
member = InheritanceHelper.GetBaseMembers(member, false).FirstOrDefault(m => !m.IsOverride) ?? member;
if (!FindOnlySpecializedReferences)
member = member.MemberDefinition;
return member;
}
bool IsMemberMatch(IMember member, IMember referencedMember, bool isVirtualCall)
{
referencedMember = NormalizeMember(referencedMember);
if (member.Equals(referencedMember))
return true;
if (!isVirtualCall)
return false;
bool isInterfaceCall = referencedMember.DeclaringTypeDefinition != null && referencedMember.DeclaringTypeDefinition.Kind == TypeKind.Interface;
if (FindCallsThroughVirtualBaseMethod && member.IsOverride && !WholeVirtualSlot && !isInterfaceCall) {
// Test if 'member' overrides 'referencedMember':
foreach (var baseMember in InheritanceHelper.GetBaseMembers(member, false)) {
if (FindOnlySpecializedReferences) {
if (baseMember.Equals(referencedMember))
return true;
} else {
if (baseMember.MemberDefinition.Equals(referencedMember))
return true;
}
if (!baseMember.IsOverride)
break;
}
return false;
} else if (FindCallsThroughInterface && isInterfaceCall) {
// Test if 'member' implements 'referencedMember':
if (FindOnlySpecializedReferences) {
return member.ImplementedInterfaceMembers.Contains(referencedMember);
} else {
return member.ImplementedInterfaceMembers.Any(m => m.MemberDefinition.Equals(referencedMember));
}
}
return false;
}
bool PerformVirtualLookup(IMember member, IMember referencedMember)
{
if (FindCallsThroughVirtualBaseMethod && member.IsOverride && !WholeVirtualSlot)
return true;
var typeDef = referencedMember.DeclaringTypeDefinition;
return FindCallsThroughInterface && typeDef != null && typeDef.Kind == TypeKind.Interface;
}
sealed class FindFieldReferences : FindMemberReferencesNavigator
{
public FindFieldReferences(IField field) : base(field)
@ -601,10 +655,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -601,10 +655,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region Find References to IEnumerator.Current
SearchScope FindEnumeratorCurrentReferences(IProperty property)
{
IProperty propertyDefinition = (IProperty)property.MemberDefinition;
return new SearchScope(
delegate(ICompilation compilation) {
IProperty imported = compilation.Import(propertyDefinition);
IProperty imported = compilation.Import(property);
return imported != null ? new FindEnumeratorCurrentReferencesNavigator(imported) : null;
});
}
@ -626,7 +679,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -626,7 +679,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool IsMatch(ResolveResult rr)
{
ForEachResolveResult ferr = rr as ForEachResolveResult;
return ferr != null && ferr.CurrentProperty != null && ferr.CurrentProperty.MemberDefinition == property;
return ferr != null && ferr.CurrentProperty != null && findReferences.IsMemberMatch(property, ferr.CurrentProperty, true);
}
}
#endregion
@ -634,8 +687,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -634,8 +687,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region Find Method References
SearchScope GetSearchScopeForMethod(IMethod method)
{
method = (IMethod)method.MemberDefinition;
Type specialNodeType;
switch (method.Name) {
case "Add":
@ -741,18 +792,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -741,18 +792,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var ferr = rr as ForEachResolveResult;
if (ferr != null) {
return IsMatch(ferr.GetEnumeratorCall)
|| (ferr.MoveNextMethod != null && method == ferr.MoveNextMethod.MemberDefinition);
|| (ferr.MoveNextMethod != null && findReferences.IsMemberMatch(method, ferr.MoveNextMethod, true));
}
}
var mrr = rr as MemberResolveResult;
return mrr != null && method == mrr.Member.MemberDefinition;
return mrr != null && findReferences.IsMemberMatch(method, mrr.Member, mrr.IsVirtualCall);
}
internal override void NavigatorDone(CSharpAstResolver resolver, CancellationToken cancellationToken)
{
foreach (var expr in potentialMethodGroupConversions) {
var conversion = resolver.GetConversion(expr, cancellationToken);
if (conversion.IsMethodGroupConversion && conversion.Method.MemberDefinition == method) {
if (conversion.IsMethodGroupConversion && findReferences.IsMemberMatch(method, conversion.Method, conversion.IsVirtualMethodLookup)) {
IType targetType = resolver.GetExpectedType(expr, cancellationToken);
ResolveResult result = resolver.Resolve(expr, cancellationToken);
ReportMatch(expr, new ConversionResolveResult(targetType, result, conversion));
@ -766,7 +817,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -766,7 +817,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region Find Indexer References
SearchScope FindIndexerReferences(IProperty indexer)
{
indexer = (IProperty)indexer.MemberDefinition;
return new SearchScope(
delegate (ICompilation compilation) {
IProperty imported = compilation.Import(indexer);
@ -794,7 +844,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -794,7 +844,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool IsMatch(ResolveResult rr)
{
MemberResolveResult mrr = rr as MemberResolveResult;
return mrr != null && indexer == mrr.Member.MemberDefinition;
return mrr != null && findReferences.IsMemberMatch(indexer, mrr.Member, mrr.IsVirtualCall);
}
}
#endregion
@ -867,7 +917,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -867,7 +917,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
SearchScope FindOperator(IMethod op, Func<IMethod, FindReferenceNavigator> factory)
{
op = (IMethod)op.MemberDefinition;
return new SearchScope(
delegate (ICompilation compilation) {
IMethod imported = compilation.Import(op);
@ -908,7 +957,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -908,7 +957,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool IsMatch(ResolveResult rr)
{
MemberResolveResult mrr = rr as MemberResolveResult;
return mrr != null && op == mrr.Member.MemberDefinition;
return mrr != null && findReferences.IsMemberMatch(op, mrr.Member, mrr.IsVirtualCall);
}
}
@ -940,7 +989,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -940,7 +989,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool IsMatch(ResolveResult rr)
{
MemberResolveResult mrr = rr as MemberResolveResult;
return mrr != null && op == mrr.Member.MemberDefinition;
return mrr != null && findReferences.IsMemberMatch(op, mrr.Member, mrr.IsVirtualCall);
}
}
@ -961,12 +1010,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -961,12 +1010,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool IsMatch(ResolveResult rr)
{
MemberResolveResult mrr = rr as MemberResolveResult;
return mrr != null && op == mrr.Member.MemberDefinition;
return mrr != null && findReferences.IsMemberMatch(op, mrr.Member, mrr.IsVirtualCall);
}
public override void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType)
{
if (conversion.IsUserDefined && conversion.Method.MemberDefinition == op) {
if (conversion.IsUserDefined && findReferences.IsMemberMatch(op, conversion.Method, conversion.IsVirtualMethodLookup)) {
ReportMatch(expression, result);
}
}
@ -989,7 +1038,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -989,7 +1038,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool IsMatch(ResolveResult rr)
{
ConversionResolveResult crr = rr as ConversionResolveResult;
return crr != null && crr.Conversion.IsUserDefined && crr.Conversion.Method.MemberDefinition == op;
return crr != null && crr.Conversion.IsUserDefined
&& findReferences.IsMemberMatch(op, crr.Conversion.Method, crr.Conversion.IsVirtualMethodLookup);
}
}
#endregion
@ -997,7 +1047,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -997,7 +1047,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region Find Constructor References
SearchScope FindObjectCreateReferences(IMethod ctor)
{
ctor = (IMethod)ctor.MemberDefinition;
string searchTerm = null;
if (KnownTypeReference.GetCSharpNameByTypeCode(ctor.DeclaringTypeDefinition.KnownTypeCode) == null) {
// not a built-in type
@ -1035,13 +1084,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1035,13 +1084,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool IsMatch(ResolveResult rr)
{
MemberResolveResult mrr = rr as MemberResolveResult;
return mrr != null && ctor == mrr.Member.MemberDefinition;
return mrr != null && findReferences.IsMemberMatch(ctor, mrr.Member, mrr.IsVirtualCall);
}
}
SearchScope FindChainedConstructorReferences(IMethod ctor)
{
ctor = (IMethod)ctor.MemberDefinition;
SearchScope searchScope = new SearchScope(
delegate (ICompilation compilation) {
IMethod imported = compilation.Import(ctor);
@ -1075,7 +1123,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1075,7 +1123,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool IsMatch(ResolveResult rr)
{
MemberResolveResult mrr = rr as MemberResolveResult;
return mrr != null && ctor == mrr.Member.MemberDefinition;
return mrr != null && findReferences.IsMemberMatch(ctor, mrr.Member, mrr.IsVirtualCall);
}
}
#endregion
@ -1083,22 +1131,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1083,22 +1131,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region Find Destructor References
SearchScope GetSearchScopeForDestructor(IMethod dtor)
{
dtor = (IMethod)dtor.MemberDefinition;
string searchTerm = null;
if (KnownTypeReference.GetCSharpNameByTypeCode(dtor.DeclaringTypeDefinition.KnownTypeCode) == null) {
// not a built-in type
searchTerm = dtor.DeclaringTypeDefinition.Name;
}
return new SearchScope (
searchTerm,
var scope = new SearchScope (
delegate (ICompilation compilation) {
IMethod imported = compilation.Import(dtor);
if (imported != null) {
return new FindDestructorReferencesNavigator (imported);
} else {
return null;
}
});
IMethod imported = compilation.Import(dtor);
if (imported != null) {
return new FindDestructorReferencesNavigator (imported);
} else {
return null;
}
});
scope.accessibility = Accessibility.Private;
return scope;
}
sealed class FindDestructorReferencesNavigator : FindReferenceNavigator
@ -1118,7 +1161,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1118,7 +1161,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal override bool IsMatch(ResolveResult rr)
{
MemberResolveResult mrr = rr as MemberResolveResult;
return mrr != null && dtor == mrr.Member.MemberDefinition;
return mrr != null && findReferences.IsMemberMatch(dtor, mrr.Member, mrr.IsVirtualCall);
}
}
#endregion

12
ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs

@ -650,7 +650,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -650,7 +650,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolveResult result = errorResult;
if (variableInitializer.Parent is FieldDeclaration || variableInitializer.Parent is EventDeclaration) {
if (resolver.CurrentMember != null) {
result = new MemberResolveResult(null, resolver.CurrentMember);
result = new MemberResolveResult(null, resolver.CurrentMember, false);
}
} else {
string identifier = variableInitializer.Name;
@ -707,7 +707,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -707,7 +707,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (resolverEnabled) {
ResolveResult result = errorResult;
if (resolver.CurrentMember != null) {
result = new MemberResolveResult(null, resolver.CurrentMember);
result = new MemberResolveResult(null, resolver.CurrentMember, false);
}
ResolveAndProcessConversion(fixedVariableInitializer.CountExpression, resolver.Compilation.FindType(KnownTypeCode.Int32));
return result;
@ -726,7 +726,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -726,7 +726,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ScanChildren(member);
if (resolver.CurrentMember != null)
return new MemberResolveResult(null, resolver.CurrentMember);
return new MemberResolveResult(null, resolver.CurrentMember, false);
else
return errorResult;
} finally {
@ -772,7 +772,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -772,7 +772,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
if (resolver.CurrentMember != null)
return new MemberResolveResult(null, resolver.CurrentMember);
return new MemberResolveResult(null, resolver.CurrentMember, false);
else
return errorResult;
} finally {
@ -805,7 +805,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -805,7 +805,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
if (resolver.CurrentMember != null)
return new MemberResolveResult(null, resolver.CurrentMember);
return new MemberResolveResult(null, resolver.CurrentMember, false);
else
return errorResult;
} finally {
@ -885,7 +885,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -885,7 +885,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (resolverEnabled && resolver.CurrentTypeDefinition != null) {
ResolveAndProcessConversion(enumMemberDeclaration.Initializer, resolver.CurrentTypeDefinition.EnumUnderlyingType);
if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(null, resolver.CurrentMember);
return new MemberResolveResult(null, resolver.CurrentMember, false);
else
return errorResult;
} else {

66
ICSharpCode.NRefactory.Tests/CSharp/Resolver/FindReferencesTest.cs

@ -33,24 +33,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -33,24 +33,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
CompilationUnit compilationUnit;
CSharpParsedFile parsedFile;
ICompilation compilation;
FindReferences findReferences;
void Init(string code)
{
compilationUnit = new CSharpParser().Parse(new StringReader(code), "test.cs");
parsedFile = compilationUnit.ToTypeSystem();
compilation = TypeSystemHelper.CreateCompilation(parsedFile);
findReferences = new FindReferences();
}
AstNode[] FindReferences(IEntity entity)
{
var result = new List<AstNode>();
var findReferences = new FindReferences();
var searchScopes = findReferences.GetSearchScopes(entity);
findReferences.FindReferencesInFile(searchScopes, parsedFile, compilationUnit, compilation,
(node, rr) => result.Add(node), CancellationToken.None);
return result.OrderBy(n => n.StartLocation).ToArray();
}
#region Method Group
[Test]
public void FindMethodGroupReference()
{
@ -107,7 +109,9 @@ class Test { @@ -107,7 +109,9 @@ class Test {
Assert.AreEqual(new [] { new TextLocation(4, 49), new TextLocation(7, 2) },
FindReferences(m_string).Select(n => n.StartLocation).ToArray());
}
#endregion
#region GetEnumerator
[Test]
public void FindReferenceToGetEnumeratorUsedImplicitlyInForeach()
{
@ -129,7 +133,9 @@ class Test { @@ -129,7 +133,9 @@ class Test {
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 3 && r is MethodDeclaration));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is ForeachStatement));
}
#endregion
#region Op_Implicit
[Test]
public void FindReferencesForOpImplicitInLocalVariableInitialization()
{
@ -147,5 +153,63 @@ class Test { @@ -147,5 +153,63 @@ class Test {
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 4 && r is ObjectCreateExpression));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 6 && r is OperatorDeclaration));
}
#endregion
#region Inheritance
const string inheritanceTest = @"using System;
class A { public virtual void M() {} }
class B : A { public override void M() {} }
class C : A { public override void M() {} }
class Calls {
void Test(A a, B b, C c) {
a.M();
b.M();
c.M();
}
}";
[Test]
public void InheritanceTest1()
{
Init(inheritanceTest);
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "B");
var BM = test.Methods.Single(m => m.Name == "M");
var actual = FindReferences(BM).ToList();
Assert.AreEqual(2, actual.Count);
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 3 && r is MethodDeclaration));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is InvocationExpression));
}
[Test]
public void InheritanceTest2()
{
Init(inheritanceTest);
findReferences.FindCallsThroughVirtualBaseMethod = true;
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "B");
var BM = test.Methods.Single(m => m.Name == "M");
var actual = FindReferences(BM).ToList();
Assert.AreEqual(3, actual.Count);
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 3 && r is MethodDeclaration));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 7 && r is InvocationExpression));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is InvocationExpression));
}
[Test]
public void InheritanceTest3()
{
Init(inheritanceTest);
findReferences.WholeVirtualSlot = true;
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "B");
var BM = test.Methods.Single(m => m.Name == "M");
var actual = FindReferences(BM).ToList();
Assert.AreEqual(6, actual.Count);
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 2 && r is MethodDeclaration));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 3 && r is MethodDeclaration));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 4 && r is MethodDeclaration));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 7 && r is InvocationExpression));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is InvocationExpression));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 9 && r is InvocationExpression));
}
#endregion
}
}

2
ICSharpCode.NRefactory/Documentation/IdStringProvider.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.Documentation
/// </summary>
public static class IdStringProvider
{
#region GetIDString
#region GetIdString
/// <summary>
/// Gets the ID string (C# 4.0 spec, §A.3.1) for the specified entity.
/// </summary>

19
ICSharpCode.NRefactory/Semantics/Conversion.cs

@ -88,11 +88,11 @@ namespace ICSharpCode.NRefactory.Semantics @@ -88,11 +88,11 @@ namespace ICSharpCode.NRefactory.Semantics
return new UserDefinedConversion(false, operatorMethod, isLifted);
}
public static Conversion MethodGroupConversion(IMethod chosenMethod)
public static Conversion MethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup)
{
if (chosenMethod == null)
throw new ArgumentNullException("chosenMethod");
return new MethodGroupConv(chosenMethod);
return new MethodGroupConv(chosenMethod, isVirtualMethodLookup);
}
#endregion
@ -302,10 +302,12 @@ namespace ICSharpCode.NRefactory.Semantics @@ -302,10 +302,12 @@ namespace ICSharpCode.NRefactory.Semantics
sealed class MethodGroupConv : Conversion
{
readonly IMethod method;
readonly bool isVirtualMethodLookup;
public MethodGroupConv(IMethod method)
public MethodGroupConv(IMethod method, bool isVirtualMethodLookup)
{
this.method = method;
this.isVirtualMethodLookup = isVirtualMethodLookup;
}
public override bool IsImplicit {
@ -316,6 +318,10 @@ namespace ICSharpCode.NRefactory.Semantics @@ -316,6 +318,10 @@ namespace ICSharpCode.NRefactory.Semantics
get { return true; }
}
public override bool IsVirtualMethodLookup {
get { return isVirtualMethodLookup; }
}
public override IMethod Method {
get { return method; }
}
@ -434,6 +440,13 @@ namespace ICSharpCode.NRefactory.Semantics @@ -434,6 +440,13 @@ namespace ICSharpCode.NRefactory.Semantics
get { return false; }
}
/// <summary>
/// For method-group conversions, gets whether to perform a virtual method lookup at runtime.
/// </summary>
public virtual bool IsVirtualMethodLookup {
get { return false; }
}
/// <summary>
/// Gets whether this conversion is an anonymous function conversion.
/// </summary>

25
ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs

@ -34,12 +34,30 @@ namespace ICSharpCode.NRefactory.Semantics @@ -34,12 +34,30 @@ namespace ICSharpCode.NRefactory.Semantics
readonly bool isConstant;
readonly object constantValue;
readonly ResolveResult targetResult;
readonly bool isVirtualCall;
public MemberResolveResult(ResolveResult targetResult, IMember member)
: base(member.EntityType == EntityType.Constructor ? member.DeclaringType : member.ReturnType)
{
this.targetResult = targetResult;
this.member = member;
var thisRR = targetResult as ThisResolveResult;
this.isVirtualCall = member.IsOverridable && !(thisRR != null && thisRR.CausesNonVirtualInvocation);
IField field = member as IField;
if (field != null) {
isConstant = field.IsConst;
if (isConstant)
constantValue = field.ConstantValue;
}
}
public MemberResolveResult(ResolveResult targetResult, IMember member, bool isVirtualCall)
: base(member.EntityType == EntityType.Constructor ? member.DeclaringType : member.ReturnType)
{
this.targetResult = targetResult;
this.member = member;
this.isVirtualCall = isVirtualCall;
IField field = member as IField;
if (field != null) {
isConstant = field.IsConst;
@ -69,6 +87,13 @@ namespace ICSharpCode.NRefactory.Semantics @@ -69,6 +87,13 @@ namespace ICSharpCode.NRefactory.Semantics
get { return member; }
}
/// <summary>
/// Gets whether this MemberResolveResult is a virtual call.
/// </summary>
public bool IsVirtualCall {
get { return isVirtualCall; }
}
public override bool IsCompileTimeConstant {
get { return isConstant; }
}

12
ICSharpCode.NRefactory/Semantics/ThisResolveResult.cs

@ -27,8 +27,18 @@ namespace ICSharpCode.NRefactory.Semantics @@ -27,8 +27,18 @@ namespace ICSharpCode.NRefactory.Semantics
/// </summary>
public class ThisResolveResult : ResolveResult
{
public ThisResolveResult(IType type) : base(type)
bool causesNonVirtualInvocation;
public ThisResolveResult(IType type, bool causesNonVirtualInvocation = false) : base(type)
{
this.causesNonVirtualInvocation = causesNonVirtualInvocation;
}
/// <summary>
/// Gets whether this resolve result causes member invocations to be non-virtual.
/// </summary>
public bool CausesNonVirtualInvocation {
get { return causesNonVirtualInvocation; }
}
}
}

32
ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedMember.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.NRefactory.Utils;
@ -65,18 +66,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -65,18 +66,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
}
public override DocumentationComment Documentation {
get {
IUnresolvedDocumentationProvider docProvider = unresolved.ParsedFile as IUnresolvedDocumentationProvider;
if (docProvider != null) {
var doc = docProvider.GetDocumentation(unresolved, this);
if (doc != null)
return doc;
}
return base.Documentation;
}
}
IList<IMember> FindImplementedInterfaceMembers()
{
if (unresolved.IsExplicitInterfaceImplementation) {
@ -87,8 +76,25 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -87,8 +76,25 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
result.Add(member);
}
return result.ToArray();
} else if (unresolved.IsStatic) {
return EmptyList<IMember>.Instance;
} else {
throw new NotImplementedException();
// TODO: implement interface member mappings correctly
return InheritanceHelper.GetBaseMembers(this, true)
.Where(m => m.DeclaringTypeDefinition != null && m.DeclaringTypeDefinition.Kind == TypeKind.Interface)
.ToArray();
}
}
public override DocumentationComment Documentation {
get {
IUnresolvedDocumentationProvider docProvider = unresolved.ParsedFile as IUnresolvedDocumentationProvider;
if (docProvider != null) {
var doc = docProvider.GetDocumentation(unresolved, this);
if (doc != null)
return doc;
}
return base.Documentation;
}
}

Loading…
Cancel
Save