Browse Source

FindReferences: API idea for new options

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
2e40a3483b
  1. 42
      ICSharpCode.NRefactory.CSharp/Resolver/FindReferencedEntities.cs
  2. 35
      ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs
  3. 24
      ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs
  4. 19
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs

42
ICSharpCode.NRefactory.CSharp/Resolver/FindReferencedEntities.cs

@ -27,13 +27,39 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary> /// </summary>
public sealed class FindReferencedEntities : IResolveVisitorNavigator public sealed class FindReferencedEntities : IResolveVisitorNavigator
{ {
readonly Action<AstNode, IEntity> referenceFound; readonly Action<AstNode, IMember> memberReferenceFound;
readonly Action<AstNode, IType> typeReferenceFound;
/// <summary>
/// Creates a new FindReferencedEntities instance that
/// looks for entity definitions.
/// The visitor will report type definitions and member definitions (not specialized members).
/// </summary>
public FindReferencedEntities(Action<AstNode, IEntity> referenceFound) public FindReferencedEntities(Action<AstNode, IEntity> referenceFound)
{ {
if (referenceFound == null) if (referenceFound == null)
throw new ArgumentNullException("referenceFound"); throw new ArgumentNullException("referenceFound");
this.referenceFound = referenceFound; this.memberReferenceFound = (node, member) => referenceFound(node, member.MemberDefinition);
this.typeReferenceFound = (node, type) => {
var def = type.GetDefinition();
if (def != null)
referenceFound(node, def);
};
}
/// <summary>
/// Creates a new FindReferencedEntities instance that
/// looks for types and members.
/// The visitor will report parameterized types and potentially specialized members.
/// </summary>
public FindReferencedEntities(Action<AstNode, IType> typeReferenceFound, Action<AstNode, IMember> memberReferenceFound)
{
if (typeReferenceFound == null)
throw new ArgumentNullException("typeReferenceFound");
if (memberReferenceFound == null)
throw new ArgumentNullException("memberReferenceFound");
this.typeReferenceFound = typeReferenceFound;
this.memberReferenceFound = memberReferenceFound;
} }
public ResolveVisitorNavigationMode Scan(AstNode node) public ResolveVisitorNavigationMode Scan(AstNode node)
@ -48,28 +74,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
MemberResolveResult mrr = result as MemberResolveResult; MemberResolveResult mrr = result as MemberResolveResult;
if (mrr != null) { if (mrr != null) {
referenceFound(node, mrr.Member.MemberDefinition); memberReferenceFound(node, mrr.Member);
} }
TypeResolveResult trr = result as TypeResolveResult; TypeResolveResult trr = result as TypeResolveResult;
if (trr != null) { if (trr != null) {
ITypeDefinition typeDef = trr.Type.GetDefinition(); typeReferenceFound(node, trr.Type);
if (typeDef != null)
referenceFound(node, typeDef);
} }
ForEachResolveResult ferr = result as ForEachResolveResult; ForEachResolveResult ferr = result as ForEachResolveResult;
if (ferr != null) { if (ferr != null) {
Resolved(node, ferr.GetEnumeratorCall); Resolved(node, ferr.GetEnumeratorCall);
if (ferr.CurrentProperty != null) if (ferr.CurrentProperty != null)
referenceFound(node, ferr.CurrentProperty.MemberDefinition); memberReferenceFound(node, ferr.CurrentProperty);
if (ferr.MoveNextMethod != null) if (ferr.MoveNextMethod != null)
referenceFound(node, ferr.MoveNextMethod.MemberDefinition); memberReferenceFound(node, ferr.MoveNextMethod);
} }
} }
public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType)
{ {
if (conversion.IsUserDefined || conversion.IsMethodGroupConversion) { if (conversion.IsUserDefined || conversion.IsMethodGroupConversion) {
referenceFound(expression, conversion.Method.MemberDefinition); memberReferenceFound(expression, conversion.Method);
} }
} }
} }

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

@ -42,9 +42,42 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{ {
#region Properties #region Properties
/// <summary> /// <summary>
/// Gets/Sets whether to find type references even if an alias is being used. /// Specifies whether to find type references even if an alias is being used.
/// Aliases may be <c>var</c> or <c>using Alias = ...;</c>.
/// </summary> /// </summary>
public bool FindTypeReferencesEvenIfAliased { get; set; } public bool FindTypeReferencesEvenIfAliased { get; set; }
/// <summary>
/// Specifies whether find references should only look for specialized matches
/// with equal type parameter substitution to the member we are searching for.
/// </summary>
public bool FindOnlySpecializedReferences { get; set; }
/// <summary>
/// If this option is enabled, find references on a overridden member
/// will find calls to the base member.
/// </summary>
public bool FindCallsThroughVirtualBaseMethod { get; set; }
/// <summary>
/// If this option is enabled, find references on a member implementing
/// an interface will also find calls to the interface.
/// </summary>
public bool FindCallsThroughInterface { get; set; }
/// <summary>
/// If this option is enabled, find references will look for all references
/// to the virtual method slot.
/// </summary>
public bool WholeVirtualSlot { get; set; }
/// <summary>
/// Specifies whether to look for references in documentation comments.
/// This will find entity references in <c>cref</c> attributes and
/// parameter references in <c>&lt;param&gt;</c> and <c>&lt;paramref&gt;</c> tags.
/// TODO: implement this feature.
/// </summary>
public bool SearchInDocumentationComments { get; set; }
#endregion #endregion
#region GetEffectiveAccessibility #region GetEffectiveAccessibility

24
ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs

@ -629,15 +629,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// Handle array types: // Handle array types:
ArrayType arrU = U as ArrayType; ArrayType arrU = U as ArrayType;
ArrayType arrV = V as ArrayType; ArrayType arrV = V as ArrayType;
ParameterizedType pV = V as ParameterizedType;
if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) { if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) {
MakeLowerBoundInference(arrU.ElementType, arrV.ElementType); MakeLowerBoundInference(arrU.ElementType, arrV.ElementType);
return; return;
} else if (arrU != null && IsIEnumerableCollectionOrList(pV) && arrU.Dimensions == 1) {
MakeLowerBoundInference(arrU.ElementType, pV.GetTypeArgument(0));
return;
} }
// Handle parameterized types: // Handle parameterized types:
ParameterizedType pV = V as ParameterizedType;
if (pV != null) { if (pV != null) {
ParameterizedType uniqueBaseType = null; ParameterizedType uniqueBaseType = null;
foreach (IType baseU in U.GetAllBaseTypes()) { foreach (IType baseU in U.GetAllBaseTypes()) {
@ -677,20 +674,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Log.Unindent(); Log.Unindent();
} }
} }
static bool IsIEnumerableCollectionOrList(ParameterizedType rt)
{
if (rt == null || rt.TypeParameterCount != 1)
return false;
switch (rt.GetDefinition().FullName) {
case "System.Collections.Generic.IList":
case "System.Collections.Generic.ICollection":
case "System.Collections.Generic.IEnumerable":
return true;
default:
return false;
}
}
#endregion #endregion
#region MakeUpperBoundInference (§7.5.2.10) #region MakeUpperBoundInference (§7.5.2.10)
@ -713,15 +696,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// Handle array types: // Handle array types:
ArrayType arrU = U as ArrayType; ArrayType arrU = U as ArrayType;
ArrayType arrV = V as ArrayType; ArrayType arrV = V as ArrayType;
ParameterizedType pU = U as ParameterizedType;
if (arrV != null && arrU != null && arrU.Dimensions == arrV.Dimensions) { if (arrV != null && arrU != null && arrU.Dimensions == arrV.Dimensions) {
MakeUpperBoundInference(arrU.ElementType, arrV.ElementType); MakeUpperBoundInference(arrU.ElementType, arrV.ElementType);
return; return;
} else if (arrV != null && IsIEnumerableCollectionOrList(pU) && arrV.Dimensions == 1) {
MakeUpperBoundInference(pU.GetTypeArgument(0), arrV.ElementType);
return;
} }
// Handle parameterized types: // Handle parameterized types:
ParameterizedType pU = U as ParameterizedType;
if (pU != null) { if (pU != null) {
ParameterizedType uniqueBaseType = null; ParameterizedType uniqueBaseType = null;
foreach (IType baseV in V.GetAllBaseTypes()) { foreach (IType baseV in V.GetAllBaseTypes()) {

19
ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs

@ -70,6 +70,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Assert.IsTrue(success); Assert.IsTrue(success);
} }
[Test]
public void ArrayToReadOnlyList()
{
ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");
IType stringType = compilation.FindType(KnownTypeCode.String);
ITypeDefinition readOnlyListType = compilation.FindType(KnownTypeCode.IReadOnlyListOfT).GetDefinition();
if (readOnlyListType == null)
Assert.Ignore(".NET 4.5 IReadOnlyList not available");
bool success;
Assert.AreEqual(
new [] { stringType },
ti.InferTypeArguments(new [] { tp },
new [] { new ResolveResult(new ArrayType(compilation, stringType)) },
new [] { new ParameterizedType(readOnlyListType, new [] { tp }) },
out success));
Assert.IsTrue(success);
}
[Test] [Test]
public void EnumerableToArrayInContravariantType() public void EnumerableToArrayInContravariantType()
{ {

Loading…
Cancel
Save