Browse Source

Merge NRefactory 'bbcde1ea2e9de8530c1653798215cf6f25f9ea2b' into SharpDevelop newNR branch.

pull/45/merge
Daniel Grunwald 12 years ago
parent
commit
61b4e48940
  1. 36
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ErrorExpression.cs
  2. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  3. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  4. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/InconsistentNamingIssue.cs
  5. 11
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ResultOfAsyncCallShouldNotBeIgnoredIssue.cs
  6. 8
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/TypeParameterNotUsedIssue.cs
  7. 45
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs
  8. 155
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs
  9. 31
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/RenameCallbackArguments.cs
  10. 7
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Analysis/AbiComparerTests.cs
  11. 206
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Analysis/SymbolCollectorTests.cs
  12. 20
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/TestRefactoringContext.cs
  13. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs
  14. 100
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/FindReferencesTest.cs
  15. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
  16. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/AbiComparer.cs
  17. 159
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/SymbolCollector.cs
  18. 82
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/TypeGraph.cs
  19. 51
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/TypeGraphNode.cs
  20. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  21. 79
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/AssemblyQualifiedTypeName.cs
  22. 49
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IkvmLoader.cs

36
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ErrorExpression.cs

@ -27,6 +27,42 @@ using System;
namespace ICSharpCode.NRefactory.CSharp namespace ICSharpCode.NRefactory.CSharp
{ {
[Obsolete("This class is obsolete. Remove all referencing code.")]
public class EmptyExpression : AstNode
{
#region implemented abstract members of AstNode
public override void AcceptVisitor(IAstVisitor visitor)
{
throw new NotImplementedException();
}
public override T AcceptVisitor<T>(IAstVisitor<T> visitor)
{
throw new NotImplementedException();
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
throw new NotImplementedException();
}
protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match)
{
throw new NotImplementedException();
}
public override NodeType NodeType {
get {
throw new NotImplementedException();
}
}
#endregion
}
public class ErrorExpression : Expression public class ErrorExpression : Expression
{ {
TextLocation location; TextLocation location;

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -363,6 +363,7 @@
<Compile Include="Resolver\NodeListResolveVisitorNavigator.cs" /> <Compile Include="Resolver\NodeListResolveVisitorNavigator.cs" />
<Compile Include="Resolver\OverloadResolution.cs" /> <Compile Include="Resolver\OverloadResolution.cs" />
<Compile Include="Resolver\OverloadResolutionErrors.cs" /> <Compile Include="Resolver\OverloadResolutionErrors.cs" />
<Compile Include="Resolver\RenameCallbackArguments.cs" />
<Compile Include="Resolver\ResolveAtLocation.cs" /> <Compile Include="Resolver\ResolveAtLocation.cs" />
<Compile Include="Resolver\ResolveVisitor.cs" /> <Compile Include="Resolver\ResolveVisitor.cs" />
<Compile Include="Resolver\TypeInference.cs" /> <Compile Include="Resolver\TypeInference.cs" />
@ -516,7 +517,6 @@
<Compile Include="Resolver\ReducedExtensionMethod.cs" /> <Compile Include="Resolver\ReducedExtensionMethod.cs" />
<Compile Include="Refactoring\CodeIssues\SimplifyAnonymousMethodToDelegateIssue.cs" /> <Compile Include="Refactoring\CodeIssues\SimplifyAnonymousMethodToDelegateIssue.cs" />
<Compile Include="Refactoring\CodeIssues\CompilerErrors\CS0127ReturnMustNotBeFollowedByAnyExpression.cs" /> <Compile Include="Refactoring\CodeIssues\CompilerErrors\CS0127ReturnMustNotBeFollowedByAnyExpression.cs" />
<Compile Include="Analysis\AbiComparer.cs" />
<Compile Include="Refactoring\CreateChangedEvent.cs" /> <Compile Include="Refactoring\CreateChangedEvent.cs" />
<Compile Include="Refactoring\CodeActions\SimplifyIfFlowAction.cs" /> <Compile Include="Refactoring\CodeActions\SimplifyIfFlowAction.cs" />
<Compile Include="Refactoring\CodeActions\SimplifyIfInLoopsFlowAction.cs" /> <Compile Include="Refactoring\CodeActions\SimplifyIfInLoopsFlowAction.cs" />

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs

@ -2699,7 +2699,7 @@ namespace ICSharpCode.NRefactory.CSharp
direction.AddChild ((Expression)arg.Expr.Accept (this), Roles.Expression); direction.AddChild ((Expression)arg.Expr.Accept (this), Roles.Expression);
newArg.AddChild (direction, Roles.Expression); newArg.AddChild (direction, Roles.Expression);
} else { } else {
newArg.AddChild ((Expression)na.Expr.Accept (this), Roles.Expression); newArg.AddChild (na.Expr != null ? (Expression)na.Expr.Accept (this) : new ErrorExpression ("Named argument expression parse error"), Roles.Expression);
} }
return newArg; return newArg;
} }

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/InconsistentNamingIssue.cs

@ -147,11 +147,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolveResult is MemberResolveResult) { if (resolveResult is MemberResolveResult) {
script.Rename(((MemberResolveResult)resolveResult).Member, n); script.Rename(((MemberResolveResult)resolveResult).Member, n);
} else if (resolveResult is TypeResolveResult) { } else if (resolveResult is TypeResolveResult) {
var def = ((TypeResolveResult)resolveResult).Type.GetDefinition(); var def = resolveResult.Type.GetDefinition();
if (def != null) { if (def != null) {
script.Rename(def, n); script.Rename(def, n);
} else { } else if (resolveResult.Type.Kind == TypeKind.TypeParameter) {
script.RenameTypeParameter(((TypeResolveResult)resolveResult).Type, n); script.Rename((ITypeParameter)resolveResult.Type, n);
} }
} else if (resolveResult is LocalResolveResult) { } else if (resolveResult is LocalResolveResult) {
script.Rename(((LocalResolveResult)resolveResult).Variable, n); script.Rename(((LocalResolveResult)resolveResult).Variable, n);
@ -169,11 +169,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolveResult is MemberResolveResult) { if (resolveResult is MemberResolveResult) {
script.Rename(((MemberResolveResult)resolveResult).Member); script.Rename(((MemberResolveResult)resolveResult).Member);
} else if (resolveResult is TypeResolveResult) { } else if (resolveResult is TypeResolveResult) {
var def = ((TypeResolveResult)resolveResult).Type.GetDefinition(); var def = resolveResult.Type.GetDefinition();
if (def != null) { if (def != null) {
script.Rename(def); script.Rename(def);
} else { } else if (resolveResult.Type.Kind == TypeKind.TypeParameter) {
script.RenameTypeParameter(((TypeResolveResult)resolveResult).Type); script.Rename((ITypeParameter)resolveResult.Type);
} }
} else if (resolveResult is LocalResolveResult) { } else if (resolveResult is LocalResolveResult) {
script.Rename(((LocalResolveResult)resolveResult).Variable); script.Rename(((LocalResolveResult)resolveResult).Variable);

11
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/ResultOfAsyncCallShouldNotBeIgnoredIssue.cs

@ -43,6 +43,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
} }
AstNode GetNodeToUnderline(Expression target)
{
if (target is IdentifierExpression)
return target;
if (target is MemberReferenceExpression)
return ((MemberReferenceExpression)target).MemberNameToken;
return target;
}
public override void VisitExpressionStatement(ExpressionStatement expressionStatement) public override void VisitExpressionStatement(ExpressionStatement expressionStatement)
{ {
base.VisitExpressionStatement(expressionStatement); base.VisitExpressionStatement(expressionStatement);
@ -51,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return; return;
var rr = ctx.Resolve(invocation) as InvocationResolveResult; var rr = ctx.Resolve(invocation) as InvocationResolveResult;
if (rr != null && (rr.Type.IsKnownType(KnownTypeCode.Task) || rr.Type.IsKnownType(KnownTypeCode.TaskOfT))) { if (rr != null && (rr.Type.IsKnownType(KnownTypeCode.Task) || rr.Type.IsKnownType(KnownTypeCode.TaskOfT))) {
AddIssue(invocation, ctx.TranslateString("Exceptions in async call will be silently ignored because the returned task is unused")); AddIssue(GetNodeToUnderline (invocation.Target), ctx.TranslateString("Exceptions in async call will be silently ignored because the returned task is unused"));
} }
} }
} }

8
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/TypeParameterNotUsedIssue.cs

@ -52,13 +52,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
protected static bool FindUsage (BaseRefactoringContext context, SyntaxTree unit, protected static bool FindUsage (BaseRefactoringContext context, SyntaxTree unit,
ITypeParameter typaParameter, AstNode declaration) ITypeParameter typeParameter, AstNode declaration)
{ {
var found = false; var found = false;
refFinder.FindTypeParameterReferences (typaParameter, context.UnresolvedFile, unit, context.Compilation, var searchScopes = refFinder.GetSearchScopes(typeParameter);
refFinder.FindReferencesInFile(searchScopes, context.Resolver,
(node, resolveResult) => (node, resolveResult) =>
{ {
found = found || node != declaration; if (node != declaration)
found = true;
}, context.CancellationToken); }, context.CancellationToken);
return found; return found;
} }

45
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs

@ -346,52 +346,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
/// <summary> /// <summary>
/// Renames the specified entity. /// Renames the specified symbol.
/// </summary> /// </summary>
/// <param name='entity'> /// <param name='symbol'>
/// The Entity to rename /// The symbol to rename
/// </param> /// </param>
/// <param name='name'> /// <param name='name'>
/// The new name, if null the user is prompted for a new name. /// The new name, if null the user is prompted for a new name.
/// </param> /// </param>
public virtual void Rename(IEntity entity, string name = null) public virtual void Rename(ISymbol symbol, string name = null)
{
}
/// <summary>
/// Renames the specified entity.
/// </summary>
/// <param name='type'>
/// The Entity to rename
/// </param>
/// <param name='name'>
/// The new name, if null the user is prompted for a new name.
/// </param>
public virtual void RenameTypeParameter (IType type, string name = null)
{
}
/// <summary>
/// Renames the specified variable.
/// </summary>
/// <param name='variable'>
/// The Variable to rename
/// </param>
/// <param name='name'>
/// The new name, if null the user is prompted for a new name.
/// </param>
public virtual void Rename(IVariable variable, string name = null)
{
}
/// <summary>
/// Renames the specified namespace.
/// </summary>
/// <param name="ns">The namespace</param>
/// <param name='name'>
/// The new name, if null the user is prompted for a new name.
/// </param>
public virtual void Rename(INamespace ns, string name = null)
{ {
} }

155
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs

@ -21,6 +21,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring; using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
@ -72,6 +73,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary> /// </summary>
public bool WholeVirtualSlot { get; set; } public bool WholeVirtualSlot { get; set; }
//public bool FindAllOverloads { get; set; }
/// <summary> /// <summary>
/// Specifies whether to look for references in documentation comments. /// Specifies whether to look for references in documentation comments.
/// This will find entity references in <c>cref</c> attributes and /// This will find entity references in <c>cref</c> attributes and
@ -218,16 +221,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion #endregion
#region GetSearchScopes #region GetSearchScopes
public IList<IFindReferenceSearchScope> GetSearchScopes(IEntity entity) public IList<IFindReferenceSearchScope> GetSearchScopes(ISymbol symbol)
{ {
if (symbol == null)
throw new ArgumentNullException("symbol");
switch (symbol.SymbolKind) {
case SymbolKind.Namespace:
return new[] { GetSearchScopeForNamespace((INamespace)symbol) };
case SymbolKind.TypeParameter:
return new[] { GetSearchScopeForTypeParameter((ITypeParameter)symbol) };
// TODO: IVariable etc.
}
IEntity entity = symbol as IEntity;
if (entity == null) if (entity == null)
throw new ArgumentNullException("entity"); throw new NotSupportedException("Unsupported symbol type");
if (entity is IMember) if (entity is IMember)
entity = NormalizeMember((IMember)entity); entity = NormalizeMember((IMember)entity);
Accessibility effectiveAccessibility = GetEffectiveAccessibility(entity); Accessibility effectiveAccessibility = GetEffectiveAccessibility(entity);
ITypeDefinition topLevelTypeDefinition = entity.DeclaringTypeDefinition; var topLevelTypeDefinition = GetTopLevelTypeDefinition(entity);
while (topLevelTypeDefinition != null && topLevelTypeDefinition.DeclaringTypeDefinition != null)
topLevelTypeDefinition = topLevelTypeDefinition.DeclaringTypeDefinition;
SearchScope scope; SearchScope scope;
SearchScope additionalScope = null; SearchScope additionalScope = null;
switch (entity.SymbolKind) { switch (entity.SymbolKind) {
@ -287,13 +298,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
} }
public IList<IFindReferenceSearchScope> GetSearchScopes(INamespace ns) public IList<IFindReferenceSearchScope> GetSearchScopes(IEnumerable<ISymbol> symbols)
{ {
if (ns == null) if (symbols == null)
throw new ArgumentNullException("ns"); throw new ArgumentNullException("symbols");
return new[] { GetSearchScopeForNamespace(ns) }; return symbols.SelectMany(GetSearchScopes).ToList();
} }
static ITypeDefinition GetTopLevelTypeDefinition(IEntity entity)
{
if (entity == null)
return null;
ITypeDefinition topLevelTypeDefinition = entity.DeclaringTypeDefinition;
while (topLevelTypeDefinition != null && topLevelTypeDefinition.DeclaringTypeDefinition != null)
topLevelTypeDefinition = topLevelTypeDefinition.DeclaringTypeDefinition;
return topLevelTypeDefinition;
}
#endregion #endregion
#region GetInterestingFileNames #region GetInterestingFileNames
@ -358,6 +378,36 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion #endregion
#region FindReferencesInFile #region FindReferencesInFile
/// <summary>
/// Finds all references in the given file.
/// </summary>
/// <param name="searchScope">The search scope for which to look.</param>
/// <param name="resolver">AST resolver for the file to search in.</param>
/// <param name="callback">Callback used to report the references that were found.</param>
/// <param name="cancellationToken">CancellationToken that may be used to cancel the operation.</param>
public void FindReferencesInFile(IFindReferenceSearchScope searchScope, CSharpAstResolver resolver,
FoundReferenceCallback callback, CancellationToken cancellationToken)
{
if (resolver == null)
throw new ArgumentNullException("resolver");
FindReferencesInFile(searchScope, resolver.UnresolvedFile, (SyntaxTree)resolver.RootNode, resolver.Compilation, callback, cancellationToken);
}
/// <summary>
/// Finds all references in the given file.
/// </summary>
/// <param name="searchScopes">The search scopes for which to look.</param>
/// <param name="resolver">AST resolver for the file to search in.</param>
/// <param name="callback">Callback used to report the references that were found.</param>
/// <param name="cancellationToken">CancellationToken that may be used to cancel the operation.</param>
public void FindReferencesInFile(IList<IFindReferenceSearchScope> searchScopes, CSharpAstResolver resolver,
FoundReferenceCallback callback, CancellationToken cancellationToken)
{
if (resolver == null)
throw new ArgumentNullException("resolver");
FindReferencesInFile(searchScopes, resolver.UnresolvedFile, (SyntaxTree)resolver.RootNode, resolver.Compilation, callback, cancellationToken);
}
/// <summary> /// <summary>
/// Finds all references in the given file. /// Finds all references in the given file.
/// </summary> /// </summary>
@ -422,6 +472,79 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
#endregion #endregion
#region RenameReferencesInFile
AstNode GetNodeToReplace(AstNode node)
{
if (node is ConstructorInitializer)
return null;
if (node is ObjectCreateExpression)
node = ((ObjectCreateExpression)node).Type;
if (node is InvocationExpression)
node = ((InvocationExpression)node).Target;
if (node is MemberReferenceExpression)
node = ((MemberReferenceExpression)node).MemberNameToken;
if (node is SimpleType)
node = ((SimpleType)node).IdentifierToken;
if (node is MemberType)
node = ((MemberType)node).MemberNameToken;
if (node is NamespaceDeclaration) {
// var nsd = ((NamespaceDeclaration)node);
// node = nsd.Identifiers.LastOrDefault (n => n.Name == memberName) ?? nsd.Identifiers.FirstOrDefault ();
// if (node == null)
return null;
}
if (node is TypeDeclaration)
node = ((TypeDeclaration)node).NameToken;
if (node is DelegateDeclaration)
node = ((DelegateDeclaration)node).NameToken;
if (node is EntityDeclaration)
node = ((EntityDeclaration)node).NameToken;
if (node is ParameterDeclaration)
node = ((ParameterDeclaration)node).NameToken;
if (node is ConstructorDeclaration)
node = ((ConstructorDeclaration)node).NameToken;
if (node is DestructorDeclaration)
node = ((DestructorDeclaration)node).NameToken;
if (node is NamedArgumentExpression)
node = ((NamedArgumentExpression)node).NameToken;
if (node is NamedExpression)
node = ((NamedExpression)node).NameToken;
if (node is VariableInitializer)
node = ((VariableInitializer)node).NameToken;
if (node is IdentifierExpression) {
node = ((IdentifierExpression)node).IdentifierToken;
}
return node;
}
public void RenameReferencesInFile(IList<IFindReferenceSearchScope> searchScopes, string newName, CSharpAstResolver resolver,
Action<RenameCallbackArguments> callback, Action<Error> errorCallback, CancellationToken cancellationToken = default (CancellationToken))
{
FindReferencesInFile(
searchScopes,
resolver,
delegate(AstNode astNode, ResolveResult result) {
var nodeToReplace = GetNodeToReplace(astNode);
if (nodeToReplace == null) {
errorCallback (new Error (ErrorType.Error, "no node to replace found."));
return;
}
callback (new RenameCallbackArguments(nodeToReplace, Identifier.Create(newName)));
},
cancellationToken);
}
#endregion
#region Find TypeDefinition References #region Find TypeDefinition References
SearchScope FindTypeDefinitionReferences(ITypeDefinition typeDefinition, bool findTypeReferencesEvenIfAliased, out SearchScope additionalScope) SearchScope FindTypeDefinitionReferences(ITypeDefinition typeDefinition, bool findTypeReferencesEvenIfAliased, out SearchScope additionalScope)
{ {
@ -1280,6 +1403,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// <param name="compilation">The compilation.</param> /// <param name="compilation">The compilation.</param>
/// <param name="callback">Callback used to report the references that were found.</param> /// <param name="callback">Callback used to report the references that were found.</param>
/// <param name="cancellationToken">Cancellation token that may be used to cancel the operation.</param> /// <param name="cancellationToken">Cancellation token that may be used to cancel the operation.</param>
[Obsolete("Use GetSearchScopes(typeParameter) instead")]
public void FindTypeParameterReferences(IType typeParameter, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, public void FindTypeParameterReferences(IType typeParameter, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree,
ICompilation compilation, FoundReferenceCallback callback, CancellationToken cancellationToken) ICompilation compilation, FoundReferenceCallback callback, CancellationToken cancellationToken)
{ {
@ -1293,6 +1417,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
FindReferencesInFile(searchScope, unresolvedFile, syntaxTree, compilation, callback, cancellationToken); FindReferencesInFile(searchScope, unresolvedFile, syntaxTree, compilation, callback, cancellationToken);
} }
SearchScope GetSearchScopeForTypeParameter(ITypeParameter tp)
{
var searchScope = new SearchScope(c => new FindTypeParameterReferencesNavigator(tp));
var compilationProvider = tp as ICompilationProvider;
if (compilationProvider != null)
searchScope.declarationCompilation = compilationProvider.Compilation;
searchScope.topLevelTypeDefinition = GetTopLevelTypeDefinition(tp.Owner);
searchScope.accessibility = Accessibility.Private;
return searchScope;
}
class FindTypeParameterReferencesNavigator : FindReferenceNavigator class FindTypeParameterReferencesNavigator : FindReferenceNavigator
{ {
readonly ITypeParameter typeParameter; readonly ITypeParameter typeParameter;

31
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/RenameCallbackArguments.cs

@ -0,0 +1,31 @@
/*
* Created by SharpDevelop.
* User: Daniel
* Date: 6/13/2013
* Time: 17:50
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// Arguments for the callback of <see cref="FindReferences.RenameReferencesInFile"/>.
/// </summary>
public class RenameCallbackArguments
{
public AstNode NodeToReplace { get; private set; }
public AstNode NewNode { get; private set; }
public RenameCallbackArguments(AstNode nodeToReplace, AstNode newNode)
{
if (nodeToReplace == null)
throw new ArgumentNullException("nodeToReplace");
if (newNode == null)
throw new ArgumentNullException("newNode");
this.NodeToReplace = nodeToReplace;
this.NewNode = newNode;
}
}
}

7
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Analysis/AbiComparerTests.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Analysis/AbiComparerTests.cs

@ -25,16 +25,13 @@
// THE SOFTWARE. // THE SOFTWARE.
using System; using System;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework; using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp.CodeCompletion; using ICSharpCode.NRefactory.CSharp.CodeCompletion;
namespace ICSharpCode.NRefactory.CSharp.Analysis namespace ICSharpCode.NRefactory.Analysis
{ {
[TestFixture] [TestFixture]
public class AbiComparerTests public class AbiComparerTests

206
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Analysis/SymbolCollectorTests.cs

@ -0,0 +1,206 @@
//
// SymbolCollectorTests.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
using NUnit.Framework;
using ICSharpCode.NRefactory.CSharp.CodeCompletion;
using System.Text;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.Analysis
{
[TestFixture]
public class SymbolCollectorTests
{
void CollectMembers(string code, string memberName, bool includeOverloads = true)
{
StringBuilder sb = new StringBuilder();
List<int> offsets = new List<int>();
foreach (var ch in code) {
if (ch == '$') {
offsets.Add(sb.Length);
continue;
}
sb.Append(ch);
}
var syntaxTree = SyntaxTree.Parse(sb.ToString (), "test.cs");
var unresolvedFile = syntaxTree.ToTypeSystem();
var compilation = TypeSystemHelper.CreateCompilation(unresolvedFile);
var symbol = FindReferencesTest.GetSymbol(compilation, memberName);
var col = new SymbolCollector();
col.IncludeOverloads = includeOverloads;
col.GroupForRenaming = true;
var result = col.GetRelatedSymbols (new TypeGraph (compilation.Assemblies),
symbol);
if (offsets.Count != result.Count()) {
foreach (var a in result)
Console.WriteLine(a);
}
Assert.AreEqual(offsets.Count, result.Count());
var doc = new ReadOnlyDocument(sb.ToString ());
result
.Select(r => doc.GetOffset ((r as IEntity).Region.Begin))
.SequenceEqual(offsets);
}
[Test]
public void TestSingleInterfaceImpl ()
{
var code = @"
interface IA
{
void $Method();
}
class A : IA
{
public virtual void $Method() { };
}
class B : A
{
public override void Method() { };
}
class C : IA
{
public void $Method() { };
}";
CollectMembers(code, "IA.Method");
}
[Test]
public void TestMultiInterfacesImpl1 ()
{
var code = @"
interface IA
{
void $Method();
}
interface IB
{
void $Method();
}
class A : IA, IB
{
public void $Method() { }
}
class B : IA
{
public void $Method() { }
}
class C : IB
{
public void $Method() { }
}";
CollectMembers(code, "A.Method");
}
[Test]
public void TestOverloads ()
{
var code = @"
class A
{
public void $Method () { }
public void $Method (int i) { }
public void $Method (string i) { }
}
";
CollectMembers(code, "A.Method");
}
[Test]
public void TestConstructor ()
{
var code = @"
class $A
{
public $A() { }
public $A(int i) { }
}
";
CollectMembers(code, "A");
}
[Test]
public void TestDestructor ()
{
var code = @"
class $A
{
$~A() { }
}
";
CollectMembers(code, "A");
}
[Test]
public void TestStaticConstructor ()
{
var code = @"
class $A
{
static $A() { }
public $A(int i) { }
}
";
CollectMembers(code, "A");
}
[Test]
public void TestShadowedMember ()
{
var code = @"
class A
{
public int $Prop
{ get; set; }
}
class B : A
{
public int Prop
{ get; set; }
}
";
CollectMembers(code, "A.Prop");
}
}
}

20
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/TestRefactoringContext.cs

@ -165,30 +165,24 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
Replace (node, new IdentifierExpression (newName)); Replace (node, new IdentifierExpression (newName));
} }
public override void Rename (IEntity entity, string name) public override void Rename (ISymbol symbol, string name)
{ {
FindReferences refFinder = new FindReferences (); if (symbol.SymbolKind == SymbolKind.Variable || symbol.SymbolKind == SymbolKind.Parameter) {
refFinder.FindReferencesInFile (refFinder.GetSearchScopes (entity), Rename(symbol as IVariable, name);
context.UnresolvedFile, return;
context.RootNode as SyntaxTree,
context.Compilation, (n, r) => Rename (n, name),
context.CancellationToken);
} }
public override void Rename (IVariable variable, string name)
{
FindReferences refFinder = new FindReferences (); FindReferences refFinder = new FindReferences ();
refFinder.FindLocalReferences (variable, refFinder.FindReferencesInFile (refFinder.GetSearchScopes (symbol),
context.UnresolvedFile, context.UnresolvedFile,
context.RootNode as SyntaxTree, context.RootNode as SyntaxTree,
context.Compilation, (n, r) => Rename (n, name), context.Compilation, (n, r) => Rename (n, name),
context.CancellationToken); context.CancellationToken);
} }
public override void RenameTypeParameter (IType type, string name = null) void Rename (IVariable variable, string name)
{ {
FindReferences refFinder = new FindReferences (); FindReferences refFinder = new FindReferences ();
refFinder.FindTypeParameterReferences (type, refFinder.FindLocalReferences (variable,
context.UnresolvedFile, context.UnresolvedFile,
context.RootNode as SyntaxTree, context.RootNode as SyntaxTree,
context.Compilation, (n, r) => Rename (n, name), context.Compilation, (n, r) => Rename (n, name),

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs

@ -30,6 +30,7 @@ using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp namespace ICSharpCode.NRefactory.CSharp
{ {
#if !__MonoCS__
[TestFixture] [TestFixture]
public class CodeDomConvertVisitorTests : ResolverTestBase public class CodeDomConvertVisitorTests : ResolverTestBase
{ {
@ -481,4 +482,5 @@ namespace ICSharpCode.NRefactory.CSharp
} }
#endregion #endregion
} }
#endif
} }

100
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/FindReferencesTest.cs

@ -24,6 +24,9 @@ using System.Threading;
using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using NUnit.Framework; using NUnit.Framework;
using ICSharpCode.NRefactory.Analysis;
using System.Text;
using ICSharpCode.NRefactory.Editor;
namespace ICSharpCode.NRefactory.CSharp.Resolver namespace ICSharpCode.NRefactory.CSharp.Resolver
{ {
@ -383,5 +386,102 @@ namespace Foo
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 12 && r is SimpleType)); Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 12 && r is SimpleType));
} }
#endregion #endregion
#region Rename
internal static ISymbol GetSymbol (ICompilation compilation, string reflectionName)
{
Stack<ITypeDefinition> typeStack = new Stack<ITypeDefinition>(compilation.MainAssembly.TopLevelTypeDefinitions);
while (typeStack.Count > 0) {
var cur = typeStack.Pop();
if (cur.ReflectionName == reflectionName)
return cur;
foreach (var member in cur.Members)
if (member.ReflectionName == reflectionName)
return member;
foreach (var nested in cur.NestedTypes) {
typeStack.Push(nested);
}
}
return null;
}
IList<AstNode> Rename(string fullyQualifiedName, string newName, bool includeOverloads)
{
var sym = GetSymbol(compilation, fullyQualifiedName);
Assert.NotNull(sym);
var graph = new TypeGraph(compilation.Assemblies);
var col = new SymbolCollector();
col.IncludeOverloads = includeOverloads;
col.GroupForRenaming = true;
var scopes = findReferences.GetSearchScopes(col.GetRelatedSymbols(graph, sym));
List<AstNode> result = new List<AstNode>();
findReferences.RenameReferencesInFile(
scopes,
newName,
new CSharpAstResolver(compilation, syntaxTree, unresolvedFile),
delegate(RenameCallbackArguments obj) {
result.Add (obj.NodeToReplace);
},
delegate(Error obj) {
});
return result;
}
void TestRename(string code, string symbolName)
{
StringBuilder sb = new StringBuilder();
List<int> offsets = new List<int>();
foreach (var ch in code) {
if (ch == '$') {
offsets.Add(sb.Length);
continue;
}
sb.Append(ch);
}
Init(sb.ToString ());
findReferences.WholeVirtualSlot = true;
var doc = new ReadOnlyDocument(sb.ToString ());
var result = Rename(symbolName, "x", false);
Assert.AreEqual(offsets.Count, result.Count);
result.Select(r => doc.GetOffset (r.StartLocation)).SequenceEqual(offsets);
}
[Test]
public void TestSimpleRename ()
{
TestRename (@"using System;
class $Test {
$Test test;
}", "Test");
}
[Test]
public void TestOverride ()
{
TestRename(@"using System;
class Test {
public virtual int $Foo { get; set; }
}
class Test2 : Test {
public override int $Foo { get; set; }
}
class Test3 : Test {
public override int $Foo { get; set; }
public FindReferencesTest ()
{
$Foo = 4;
}
}
", "Test.Foo");
}
#endregion
} }
} }

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -93,6 +93,7 @@
<Compile Include="..\ICSharpCode.NRefactory\Properties\GlobalAssemblyInfo.cs"> <Compile Include="..\ICSharpCode.NRefactory\Properties\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link> <Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile> </Compile>
<Compile Include="Analysis\AbiComparerTests.cs" />
<Compile Include="CSharp\Analysis\DefiniteAssignmentTests.cs" /> <Compile Include="CSharp\Analysis\DefiniteAssignmentTests.cs" />
<Compile Include="CSharp\AstStructureTests.cs" /> <Compile Include="CSharp\AstStructureTests.cs" />
<Compile Include="CSharp\CodeActions\AddUsing\AddUsingActionAlphabeticalTests.cs" /> <Compile Include="CSharp\CodeActions\AddUsing\AddUsingActionAlphabeticalTests.cs" />
@ -396,7 +397,6 @@
<Compile Include="CSharp\CodeIssues\SimplifyAnonymousMethodToDelegateIssueTests.cs" /> <Compile Include="CSharp\CodeIssues\SimplifyAnonymousMethodToDelegateIssueTests.cs" />
<Compile Include="CSharp\CodeIssues\CS0127ReturnMustNotBeFollowedByAnyExpressionTests.cs" /> <Compile Include="CSharp\CodeIssues\CS0127ReturnMustNotBeFollowedByAnyExpressionTests.cs" />
<Compile Include="CSharp\Analysis\SemanticHighlightingTests.cs" /> <Compile Include="CSharp\Analysis\SemanticHighlightingTests.cs" />
<Compile Include="CSharp\Analysis\AbiComparerTests.cs" />
<Compile Include="CSharp\CodeActions\CreateChangedEventTests.cs" /> <Compile Include="CSharp\CodeActions\CreateChangedEventTests.cs" />
<Compile Include="CSharp\CodeActions\SimplifyIfFlowTests.cs" /> <Compile Include="CSharp\CodeActions\SimplifyIfFlowTests.cs" />
<Compile Include="CSharp\CodeActions\SimplifyIfFlowInLoopsTests.cs" /> <Compile Include="CSharp\CodeActions\SimplifyIfFlowInLoopsTests.cs" />
@ -417,6 +417,7 @@
<Compile Include="CSharp\CodeIssues\DuplicateIfInIfChainIssueTests.cs" /> <Compile Include="CSharp\CodeIssues\DuplicateIfInIfChainIssueTests.cs" />
<Compile Include="CSharp\CodeIssues\UseBlockInsteadColonIssueTests.cs" /> <Compile Include="CSharp\CodeIssues\UseBlockInsteadColonIssueTests.cs" />
<Compile Include="CSharp\AstTests.cs" /> <Compile Include="CSharp\AstTests.cs" />
<Compile Include="Analysis\SymbolCollectorTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\cecil\Mono.Cecil.csproj"> <ProjectReference Include="..\..\cecil\Mono.Cecil.csproj">
@ -439,7 +440,6 @@
<Private>False</Private> <Private>False</Private>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions> <ProjectExtensions>
<MonoDevelop> <MonoDevelop>

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/AbiComparer.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/AbiComparer.cs

@ -28,7 +28,7 @@ using ICSharpCode.NRefactory.TypeSystem;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace ICSharpCode.NRefactory.CSharp namespace ICSharpCode.NRefactory.Analysis
{ {
/// <summary> /// <summary>
/// Used to check the compatibility state of two compilations. /// Used to check the compatibility state of two compilations.

159
src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/SymbolCollector.cs

@ -0,0 +1,159 @@
// Copyright (c) 2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using System.Linq;
namespace ICSharpCode.NRefactory.Analysis
{
/// <summary>
/// The symbol collector collects related symbols that form a group of symbols that should be renamed
/// when a name of one symbol changes. For example if a type definition name should be changed
/// the constructors and destructor names should change as well.
/// </summary>
public class SymbolCollector
{
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ICSharpCode.NRefactory.Analysis.SymbolCollector"/> should include overloads.
/// </summary>
/// <value><c>true</c> if overloads should be included; otherwise, <c>false</c>.</value>
public bool IncludeOverloads {
get;
set;
}
public bool GroupForRenaming {
get;
set;
}
static IEnumerable<ISymbol> CollectTypeRelatedMembers (ITypeDefinition type)
{
yield return type;
foreach (var c in type.GetDefinition ().GetMembers (m => !m.IsSynthetic && (m.SymbolKind == SymbolKind.Constructor || m.SymbolKind == SymbolKind.Destructor), GetMemberOptions.IgnoreInheritedMembers)) {
yield return c;
}
}
static IEnumerable<ISymbol> CollectOverloads (TypeGraph g, IMethod method)
{
return method.DeclaringType
.GetMethods (m => m.Name == method.Name)
.Where (m => m != method);
}
static IMember SearchMember (ITypeDefinition derivedType, IMember method)
{
foreach (var m in derivedType.Members) {
if (m.ImplementedInterfaceMembers.Contains (method))
return m;
}
return null;
}
static IEnumerable<ISymbol> MakeUnique (List<ISymbol> symbols)
{
HashSet<ISymbol> taken = new HashSet<ISymbol> ();
foreach (var sym in symbols) {
if (taken.Contains (sym))
continue;
taken.Add (sym);
yield return sym;
}
}
/// <summary>
/// Gets the related symbols.
/// </summary>
/// <returns>The related symbols.</returns>
/// <param name="g">The type graph.</param>
/// <param name="m">The symbol to search</param>
/// <param name="includeOverloads">If set to <c>true</c> overloads are included in the rename.</param>
public IEnumerable<ISymbol> GetRelatedSymbols(TypeGraph g, ISymbol m)
{
switch (m.SymbolKind) {
case SymbolKind.TypeDefinition:
return CollectTypeRelatedMembers ((ITypeDefinition)m);
case SymbolKind.Field:
case SymbolKind.Operator:
case SymbolKind.Variable:
case SymbolKind.Parameter:
case SymbolKind.TypeParameter:
return new ISymbol[] { m };
case SymbolKind.Constructor:
if (GroupForRenaming)
return GetRelatedSymbols (g, ((IMethod)m).DeclaringTypeDefinition);
List<ISymbol> constructorSymbols = new List<ISymbol> ();
if (IncludeOverloads) {
foreach (var m3 in CollectOverloads (g, (IMethod)m)) {
constructorSymbols.Add (m3);
}
}
return constructorSymbols;
case SymbolKind.Destructor:
if (GroupForRenaming)
return GetRelatedSymbols (g, ((IMethod)m).DeclaringTypeDefinition);
return new ISymbol[] { m };
case SymbolKind.Indexer:
case SymbolKind.Event:
case SymbolKind.Property:
return new ISymbol[] { m };
case SymbolKind.Method:
var method = (IMethod)m;
List<ISymbol> symbols = new List<ISymbol> ();
if (method.ImplementedInterfaceMembers.Count > 0) {
foreach (var m2 in method.ImplementedInterfaceMembers) {
symbols.AddRange (GetRelatedSymbols (g, m2));
}
} else {
symbols.Add (method);
}
if (method.DeclaringType.Kind == TypeKind.Interface) {
foreach (var derivedType in g.GetNode (method.DeclaringTypeDefinition).DerivedTypes) {
var member = SearchMember (derivedType.TypeDefinition, method);
if (member != null)
symbols.Add (member);
}
}
if (IncludeOverloads) {
IncludeOverloads = false;
foreach (var m3 in CollectOverloads (g, method)) {
symbols.AddRange (GetRelatedSymbols (g, m3));
}
}
return MakeUnique (symbols);
case SymbolKind.Namespace:
// TODO?
return new ISymbol[] { m };
default:
throw new ArgumentOutOfRangeException ("symbol:"+m.SymbolKind);
}
}
}
}

82
src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/TypeGraph.cs

@ -0,0 +1,82 @@
// Copyright (c) 2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Analysis
{
/// <summary>
/// A graph where type definitions are nodes; and edges are given by inheritance.
/// </summary>
public class TypeGraph
{
Dictionary<AssemblyQualifiedTypeName, TypeGraphNode> dict;
/// <summary>
/// Builds a graph of all type definitions in the specified set of assemblies.
/// </summary>
/// <param name="assemblies">The input assemblies. The assemblies may belong to multiple compilations.</param>
/// <remarks>The resulting graph may be cyclic if there are cyclic type definitions.</remarks>
public TypeGraph(IEnumerable<IAssembly> assemblies)
{
if (assemblies == null)
throw new ArgumentNullException("assemblies");
dict = new Dictionary<AssemblyQualifiedTypeName, TypeGraphNode>();
foreach (IAssembly assembly in assemblies) {
foreach (ITypeDefinition typeDef in assembly.GetAllTypeDefinitions()) {
// Overwrite previous entry - duplicates can occur if there are multiple versions of the
// same project loaded in the solution (e.g. separate .csprojs for separate target frameworks)
dict[new AssemblyQualifiedTypeName(typeDef)] = new TypeGraphNode(typeDef);
}
}
foreach (IAssembly assembly in assemblies) {
foreach (ITypeDefinition typeDef in assembly.GetAllTypeDefinitions()) {
TypeGraphNode typeNode = dict[new AssemblyQualifiedTypeName(typeDef)];
foreach (IType baseType in typeDef.DirectBaseTypes) {
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null) {
TypeGraphNode baseTypeNode;
if (dict.TryGetValue(new AssemblyQualifiedTypeName(baseTypeDef), out baseTypeNode)) {
typeNode.BaseTypes.Add(baseTypeNode);
baseTypeNode.DerivedTypes.Add(typeNode);
}
}
}
}
}
}
public TypeGraphNode GetNode(ITypeDefinition typeDefinition)
{
if (typeDefinition == null)
return null;
return GetNode(new AssemblyQualifiedTypeName(typeDefinition));
}
public TypeGraphNode GetNode(AssemblyQualifiedTypeName typeName)
{
TypeGraphNode node;
if (dict.TryGetValue(typeName, out node))
return node;
else
return null;
}
}
}

51
src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/TypeGraphNode.cs

@ -0,0 +1,51 @@
// Copyright (c) 2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Analysis
{
public sealed class TypeGraphNode
{
readonly ITypeDefinition typeDef;
readonly List<TypeGraphNode> baseTypes = new List<TypeGraphNode>();
readonly List<TypeGraphNode> derivedTypes = new List<TypeGraphNode>();
/// <summary>
/// Creates a new unconnected type graph node.
/// </summary>
public TypeGraphNode(ITypeDefinition typeDef)
{
this.typeDef = typeDef;
}
public ITypeDefinition TypeDefinition {
get { return typeDef; }
}
public IList<TypeGraphNode> DerivedTypes {
get { return derivedTypes; }
}
public IList<TypeGraphNode> BaseTypes {
get { return baseTypes; }
}
}
}

5
src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -82,6 +82,9 @@
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Analysis\AbiComparer.cs" />
<Compile Include="Analysis\TypeGraph.cs" />
<Compile Include="Analysis\TypeGraphNode.cs" />
<Compile Include="Documentation\DocumentationComment.cs" /> <Compile Include="Documentation\DocumentationComment.cs" />
<Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" /> <Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" />
<Compile Include="Documentation\IDocumentationProvider.cs" /> <Compile Include="Documentation\IDocumentationProvider.cs" />
@ -137,6 +140,7 @@
<Compile Include="TypeSystem\Accessibility.cs" /> <Compile Include="TypeSystem\Accessibility.cs" />
<Compile Include="TypeSystem\AnonymousType.cs" /> <Compile Include="TypeSystem\AnonymousType.cs" />
<Compile Include="TypeSystem\ArrayType.cs" /> <Compile Include="TypeSystem\ArrayType.cs" />
<Compile Include="TypeSystem\AssemblyQualifiedTypeName.cs" />
<Compile Include="TypeSystem\ByReferenceType.cs" /> <Compile Include="TypeSystem\ByReferenceType.cs" />
<Compile Include="TypeSystem\CecilLoader.cs" /> <Compile Include="TypeSystem\CecilLoader.cs" />
<Compile Include="TypeSystem\ComHelper.cs" /> <Compile Include="TypeSystem\ComHelper.cs" />
@ -274,6 +278,7 @@
<Compile Include="Completion\CompletionExtensionMethods.cs" /> <Compile Include="Completion\CompletionExtensionMethods.cs" />
<Compile Include="Refactoring\IssueMarker.cs" /> <Compile Include="Refactoring\IssueMarker.cs" />
<Compile Include="Refactoring\Severity.cs" /> <Compile Include="Refactoring\Severity.cs" />
<Compile Include="Analysis\SymbolCollector.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Completion\" /> <Folder Include="Completion\" />

79
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/AssemblyQualifiedTypeName.cs

@ -0,0 +1,79 @@
// Copyright (c) 2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
public struct AssemblyQualifiedTypeName : IEquatable<AssemblyQualifiedTypeName>
{
public readonly string AssemblyName;
public readonly FullTypeName TypeName;
public AssemblyQualifiedTypeName(FullTypeName typeName, string assemblyName)
{
this.AssemblyName = assemblyName;
this.TypeName = typeName;
}
public AssemblyQualifiedTypeName(ITypeDefinition typeDefinition)
{
this.AssemblyName = typeDefinition.ParentAssembly.AssemblyName;
this.TypeName = typeDefinition.FullTypeName;
}
public override string ToString()
{
if (string.IsNullOrEmpty(AssemblyName))
return TypeName.ToString();
else
return TypeName.ToString() + ", " + AssemblyName;
}
public override bool Equals(object obj)
{
return (obj is AssemblyQualifiedTypeName) && Equals((AssemblyQualifiedTypeName)obj);
}
public bool Equals(AssemblyQualifiedTypeName other)
{
return this.AssemblyName == other.AssemblyName && this.TypeName == other.TypeName;
}
public override int GetHashCode()
{
int hashCode = 0;
unchecked {
if (AssemblyName != null)
hashCode += 1000000007 * AssemblyName.GetHashCode();
hashCode += TypeName.GetHashCode();
}
return hashCode;
}
public static bool operator ==(AssemblyQualifiedTypeName lhs, AssemblyQualifiedTypeName rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(AssemblyQualifiedTypeName lhs, AssemblyQualifiedTypeName rhs)
{
return !lhs.Equals(rhs);
}
}
}

49
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IkvmLoader.cs

@ -113,7 +113,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (fileName == null) if (fileName == null)
throw new ArgumentNullException("fileName"); throw new ArgumentNullException("fileName");
using (var universe = new Universe (UniverseOptions.DisablePseudoCustomAttributeRetrieval)) { using (var universe = new Universe (UniverseOptions.DisablePseudoCustomAttributeRetrieval | UniverseOptions.SupressReferenceTypeIdentityConversion)) {
universe.AssemblyResolve += delegate(object sender, IKVM.Reflection.ResolveEventArgs args) { universe.AssemblyResolve += delegate(object sender, IKVM.Reflection.ResolveEventArgs args) {
return universe.CreateMissingAssembly(args.Name); return universe.CreateMissingAssembly(args.Name);
}; };
@ -254,7 +254,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (type == null) { if (type == null) {
return SpecialType.UnknownType; return SpecialType.UnknownType;
} }
if (type.IsByRef) { if (type.IsByRef) {
typeIndex++; typeIndex++;
return interningProvider.Intern ( return interningProvider.Intern (
@ -1491,7 +1490,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
{ {
// set base classes // set base classes
if (typeDefinition.IsEnum) { if (typeDefinition.IsEnum) {
foreach (var enumField in typeDefinition.GetFields (bindingFlags)) { foreach (var enumField in typeDefinition.__GetDeclaredFields ()) {
if (!enumField.IsStatic) { if (!enumField.IsStatic) {
baseTypes.Add(ReadTypeReference(enumField.FieldType)); baseTypes.Add(ReadTypeReference(enumField.FieldType));
break; break;
@ -1501,7 +1500,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (typeDefinition.BaseType != null) { if (typeDefinition.BaseType != null) {
baseTypes.Add(ReadTypeReference(typeDefinition.BaseType)); baseTypes.Add(ReadTypeReference(typeDefinition.BaseType));
} }
foreach (var iface in typeDefinition.GetInterfaces ()) { foreach (var iface in typeDefinition.__GetDeclaredInterfaces ()) {
baseTypes.Add(ReadTypeReference(iface)); baseTypes.Add(ReadTypeReference(iface));
} }
} }
@ -1509,7 +1508,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
void InitNestedTypes(IKVM.Reflection.Type typeDefinition, IUnresolvedTypeDefinition declaringTypeDefinition, ICollection<IUnresolvedTypeDefinition> nestedTypes) void InitNestedTypes(IKVM.Reflection.Type typeDefinition, IUnresolvedTypeDefinition declaringTypeDefinition, ICollection<IUnresolvedTypeDefinition> nestedTypes)
{ {
foreach (var nestedTypeDef in typeDefinition.GetNestedTypes (bindingFlags)) { foreach (var nestedTypeDef in typeDefinition.__GetDeclaredTypes()) {
if (IncludeInternalMembers if (IncludeInternalMembers
|| nestedTypeDef.IsNestedPublic || nestedTypeDef.IsNestedPublic
|| nestedTypeDef.IsNestedFamily || nestedTypeDef.IsNestedFamily
@ -1595,11 +1594,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
return false; return false;
} }
static readonly BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly;
void InitMembers(IKVM.Reflection.Type typeDefinition, IUnresolvedTypeDefinition td, IList<IUnresolvedMember> members) void InitMembers(IKVM.Reflection.Type typeDefinition, IUnresolvedTypeDefinition td, IList<IUnresolvedMember> members)
{ {
foreach (var method in typeDefinition.GetMethods (bindingFlags)) { foreach (var method in typeDefinition.__GetDeclaredMethods ()) {
if (method.IsConstructor) {
if (IsVisible(method.Attributes)) {
SymbolKind type = SymbolKind.Constructor;
members.Add(ReadConstructor(method, td, type));
}
continue;
}
if (IsVisible(method.Attributes) && !IsAccessor(method)) { if (IsVisible(method.Attributes) && !IsAccessor(method)) {
SymbolKind type = SymbolKind.Method; SymbolKind type = SymbolKind.Method;
if (method.IsSpecialName) { if (method.IsSpecialName) {
@ -1610,15 +1614,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
} }
} }
foreach (var method in typeDefinition.GetConstructors (bindingFlags)) { foreach (var field in typeDefinition.__GetDeclaredFields ()) {
if (IsVisible(method.Attributes)) {
SymbolKind type = SymbolKind.Constructor;
members.Add(ReadConstructor(method, td, type));
}
}
foreach (var field in typeDefinition.GetFields (bindingFlags)) {
if (IsVisible(field.Attributes) && !field.IsSpecialName) { if (IsVisible(field.Attributes) && !field.IsSpecialName) {
members.Add(ReadField(field, td)); members.Add(ReadField(field, td));
} }
@ -1631,7 +1627,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
defaultMemberName = defaultMemberAttribute.ConstructorArguments[0].Value as string; defaultMemberName = defaultMemberAttribute.ConstructorArguments[0].Value as string;
} }
foreach (var property in typeDefinition.GetProperties (bindingFlags)) { foreach (var property in typeDefinition.__GetDeclaredProperties ()) {
bool getterVisible = property.GetMethod != null && IsVisible(property.GetMethod.Attributes); bool getterVisible = property.GetMethod != null && IsVisible(property.GetMethod.Attributes);
bool setterVisible = property.SetMethod != null && IsVisible(property.SetMethod.Attributes); bool setterVisible = property.SetMethod != null && IsVisible(property.SetMethod.Attributes);
if (getterVisible || setterVisible) { if (getterVisible || setterVisible) {
@ -1653,14 +1649,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
} }
} }
foreach (var ev in typeDefinition.GetEvents (bindingFlags)) { foreach (var ev in typeDefinition.__GetDeclaredEvents ()) {
if (ev.AddMethod != null && IsVisible(ev.AddMethod.Attributes)) { if (ev.AddMethod != null && IsVisible(ev.AddMethod.Attributes)) {
members.Add(ReadEvent(ev, td)); members.Add(ReadEvent(ev, td));
} }
} }
} }
static bool IsAccessor(MethodInfo methodInfo) static bool IsAccessor(MethodBase methodInfo)
{ {
if (!methodInfo.IsSpecialName) if (!methodInfo.IsSpecialName)
return false; return false;
@ -1677,9 +1673,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
#region Read Method #region Read Method
[CLSCompliant(false)] [CLSCompliant(false)]
public IUnresolvedMethod ReadMethod(MethodInfo method, IUnresolvedTypeDefinition parentType, SymbolKind methodType = SymbolKind.Method) public IUnresolvedMethod ReadMethod(MethodBase method, IUnresolvedTypeDefinition parentType, SymbolKind methodType = SymbolKind.Method)
{ {
return ReadMethod(method, parentType, methodType, null); return ReadMethod((MethodInfo)method, parentType, methodType, null);
} }
IUnresolvedMethod ReadMethod(MethodInfo method, IUnresolvedTypeDefinition parentType, SymbolKind methodType, IUnresolvedMember accessorOwner) IUnresolvedMethod ReadMethod(MethodInfo method, IUnresolvedTypeDefinition parentType, SymbolKind methodType, IUnresolvedMember accessorOwner)
@ -1689,7 +1685,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
var m = new DefaultUnresolvedMethod(parentType, method.Name); var m = new DefaultUnresolvedMethod(parentType, method.Name);
m.SymbolKind = methodType; m.SymbolKind = methodType;
m.AccessorOwner = accessorOwner; m.AccessorOwner = accessorOwner;
m.HasBody = method.GetMethodBody () != null; m.HasBody = !method.DeclaringType.IsInterface && (method.GetMethodImplementationFlags () & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.IL;
var genericArguments = method.GetGenericArguments (); var genericArguments = method.GetGenericArguments ();
if (genericArguments != null) { if (genericArguments != null) {
for (int i = 0; i < genericArguments.Length; i++) { for (int i = 0; i < genericArguments.Length; i++) {
@ -1803,9 +1799,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
#region Read Constructor #region Read Constructor
[CLSCompliant(false)] [CLSCompliant(false)]
public IUnresolvedMethod ReadConstructor(ConstructorInfo method, IUnresolvedTypeDefinition parentType, SymbolKind methodType = SymbolKind.Method) public IUnresolvedMethod ReadConstructor(MethodBase method, IUnresolvedTypeDefinition parentType, SymbolKind methodType = SymbolKind.Method)
{ {
return ReadConstructor(method, parentType, methodType, null); return ReadConstructor((ConstructorInfo)method, parentType, methodType, null);
} }
IUnresolvedMethod ReadConstructor(ConstructorInfo method, IUnresolvedTypeDefinition parentType, SymbolKind methodType, IUnresolvedMember accessorOwner) IUnresolvedMethod ReadConstructor(ConstructorInfo method, IUnresolvedTypeDefinition parentType, SymbolKind methodType, IUnresolvedMember accessorOwner)
@ -1815,7 +1811,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
var m = new DefaultUnresolvedMethod(parentType, method.Name); var m = new DefaultUnresolvedMethod(parentType, method.Name);
m.SymbolKind = methodType; m.SymbolKind = methodType;
m.AccessorOwner = accessorOwner; m.AccessorOwner = accessorOwner;
m.HasBody = method.GetMethodBody () != null; m.HasBody = !method.DeclaringType.IsInterface && (method.GetMethodImplementationFlags () & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.IL;
var genericArguments = method.GetGenericArguments (); var genericArguments = method.GetGenericArguments ();
if (genericArguments != null) { if (genericArguments != null) {
for (int i = 0; i < genericArguments.Length; i++) { for (int i = 0; i < genericArguments.Length; i++) {
@ -1938,7 +1934,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
f.Accessibility = GetAccessibility(field.Attributes); f.Accessibility = GetAccessibility(field.Attributes);
f.IsReadOnly = field.IsInitOnly; f.IsReadOnly = field.IsInitOnly;
f.IsStatic = field.IsStatic; f.IsStatic = field.IsStatic;
f.ReturnType = ReadTypeReference(field.FieldType, typeAttributes: field.CustomAttributes); f.ReturnType = ReadTypeReference(field.FieldType, typeAttributes: field.CustomAttributes);
if (field.Attributes.HasFlag (FieldAttributes.HasDefault)) { if (field.Attributes.HasFlag (FieldAttributes.HasDefault)) {

Loading…
Cancel
Save