Browse Source

Merge NRefactory 5.2.0-361-g875ee8d into SharpDevelop newNR branch.

newNRvisualizers
Daniel Grunwald 13 years ago
parent
commit
2dbebf213d
  1. 15
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/SyntaxTree.cs
  2. 113
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  3. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs
  4. 46
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs
  5. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs
  6. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs
  7. 1
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingOptionsFactory.cs
  8. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  9. 1
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CheckIfParameterIsNullAction.cs
  10. 85
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/AccessPath.cs
  11. 100
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs
  12. 17
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/AssignmentMadeToSameVariableIssue.cs
  13. 3
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantToStringIssue.cs
  14. 36
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantTypeCastIssue.cs
  15. 57
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/StringIsNullOrEmptyIssue.cs
  16. 36
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableDeclaredInWideScopeIssue.cs
  17. 20
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableNotUsedIssues/ParameterNotUsedIssue.cs
  18. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs
  19. 15
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs
  20. 18
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs
  21. 85
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs
  22. 1
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs
  23. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs
  24. 25
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs
  25. 15
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs
  26. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/ResolvedUsingScope.cs
  27. 13
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs
  28. 14
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs
  29. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/AddCatchTypeTests.cs
  30. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertAnonymousDelegateToLambdaTests.cs
  31. 8
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertConditionalToIfTests.cs
  32. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertLamdaToAnonymousDelegateTests.cs
  33. 21
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertSwitchToIfTests.cs
  34. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/DeclareLocalVariableTests.cs
  35. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtensionMethodInvocationToStaticMethodInvocationTests.cs
  36. 68
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/MoveToOuterScopeTests.cs
  37. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/RemoveRedundantCatchTypeTests.cs
  38. 3
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/SplitDeclarationAndAssignmentTests.cs
  39. 76
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionAccessibleTests.cs
  40. 69
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs
  41. 14
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/NameContextTests.cs
  42. 8
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs
  43. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/TestBase.cs
  44. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/AccessToModifiedClosureTests.cs
  45. 65
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/AssignmentMadeToSameVariableIssueTests.cs
  46. 9
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ConstantConditionIssueTests.cs
  47. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionIsAlwaysOfProvidedTypeIssueTests.cs
  48. 3
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/InspectionActionTestBase.cs
  49. 30
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ParameterNotUsedIssueTests.cs
  50. 29
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantToStringTests.cs
  51. 24
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantTypeCastIssueTests.cs
  52. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ReferenceToStaticMemberViaDerivedTypeTests.cs
  53. 68
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/StringIsNullOrEmptyInspectorTests.cs
  54. 21
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/VariableDeclaredInWideScopeTests.cs
  55. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs
  56. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs
  57. 39
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs
  58. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs
  59. 3
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs
  60. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs
  61. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs
  62. 41
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeParameterTests.cs
  63. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemHelper.cs
  64. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  65. 22
      src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  66. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Documentation/GetPotentiallyNestedClassTypeReference.cs
  67. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  68. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs
  69. 20
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  70. 313
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/FullTypeName.cs
  71. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAssembly.cs
  72. 9
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ICompilation.cs
  73. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs
  74. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/INamespace.cs
  75. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs
  76. 10
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs
  77. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs
  78. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs
  79. 28
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  80. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs
  81. 24
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeDefinition.cs
  82. 69
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/FullNameAndTypeParameterCount.cs
  83. 99
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs
  84. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/KnownTypeCache.cs
  85. 50
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/UnknownType.cs
  86. 6
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs
  87. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs
  88. 144
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TopLevelTypeName.cs
  89. 118
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TypeSystemExtensions.cs

15
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/SyntaxTree.cs

@ -105,22 +105,29 @@ namespace ICSharpCode.NRefactory.CSharp
{ {
} }
public IEnumerable<TypeDeclaration> GetTypes(bool includeInnerTypes = false) /// <summary>
/// Gets all defined types in this syntax tree.
/// </summary>
/// <returns>
/// A list containing <see cref="TypeDeclaration"/> or <see cref="DelegateDeclaration"/> nodes.
/// </returns>
public IEnumerable<EntityDeclaration> GetTypes(bool includeInnerTypes = false)
{ {
Stack<AstNode> nodeStack = new Stack<AstNode> (); Stack<AstNode> nodeStack = new Stack<AstNode> ();
nodeStack.Push(this); nodeStack.Push(this);
while (nodeStack.Count > 0) { while (nodeStack.Count > 0) {
var curNode = nodeStack.Pop(); var curNode = nodeStack.Pop();
if (curNode is TypeDeclaration) { if (curNode is TypeDeclaration || curNode is DelegateDeclaration) {
yield return (TypeDeclaration)curNode; yield return (EntityDeclaration)curNode;
} }
foreach (var child in curNode.Children) { foreach (var child in curNode.Children) {
if (!(child is Statement || child is Expression) && if (!(child is Statement || child is Expression) &&
(child.Role != Roles.TypeMemberRole || (child is TypeDeclaration && includeInnerTypes))) (child.Role != Roles.TypeMemberRole || ((child is TypeDeclaration || child is DelegateDeclaration) && includeInnerTypes)))
nodeStack.Push (child); nodeStack.Push (child);
} }
} }
} }
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{ {

113
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

@ -669,8 +669,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (!(Char.IsWhiteSpace(prevCh) || allowedChars.IndexOf(prevCh) >= 0)) { if (!(Char.IsWhiteSpace(prevCh) || allowedChars.IndexOf(prevCh) >= 0)) {
return null; return null;
} }
// Do not pop up completion on identifier identifier (should be handled by keyword completion).
// Do not pop up completion on identifier identifier (should be handled by keyword completion).
tokenIndex = offset - 1; tokenIndex = offset - 1;
token = GetPreviousToken(ref tokenIndex, false); token = GetPreviousToken(ref tokenIndex, false);
if (token == "class" || token == "interface" || token == "struct" || token == "enum" || token == "namespace") { if (token == "class" || token == "interface" || token == "struct" || token == "enum" || token == "namespace") {
@ -688,7 +687,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
// after these always follows a name // after these always follows a name
return null; return null;
} }
if (identifierStart == null && !string.IsNullOrEmpty(token) && !IsInsideCommentStringOrDirective() && (prevToken2 == ";" || prevToken2 == "{" || prevToken2 == "}")) { if (identifierStart == null && !string.IsNullOrEmpty(token) && !IsInsideCommentStringOrDirective() && (prevToken2 == ";" || prevToken2 == "{" || prevToken2 == "}")) {
char last = token [token.Length - 1]; char last = token [token.Length - 1];
if (char.IsLetterOrDigit(last) || last == '_' || token == ">") { if (char.IsLetterOrDigit(last) || last == '_' || token == ">") {
@ -708,7 +707,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (n != null && n.Parent is AnonymousTypeCreateExpression) { if (n != null && n.Parent is AnonymousTypeCreateExpression) {
AutoSelect = false; AutoSelect = false;
} }
// Handle foreach (type name _ // Handle foreach (type name _
if (n is IdentifierExpression) { if (n is IdentifierExpression) {
var prev = n.GetPrevNode() as ForeachStatement; var prev = n.GetPrevNode() as ForeachStatement;
@ -719,24 +718,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
return null; return null;
} }
// var astResolver = new CSharpAstResolver(
// GetState(),
// identifierStart.Unit,
// CSharpUnresolvedFile
// );
//
// foreach (var type in CreateFieldAction.GetValidTypes(astResolver, (Expression)n)) {
// if (type.Kind == TypeKind.Delegate) {
// AddDelegateHandlers(contextList, type, false, false);
// AutoSelect = false;
// AutoCompleteEmptyMatch = false;
// }
// }
} }
// Handle object/enumerable initialzer expressions: "new O () { P$" // Handle object/enumerable initialzer expressions: "new O () { P$"
if (n is IdentifierExpression && n.Parent is ArrayInitializerExpression) { if (n is IdentifierExpression && n.Parent is ArrayInitializerExpression && !(n.Parent.Parent is ArrayCreateExpression)) {
var result = HandleObjectInitializer(identifierStart.Unit, n); var result = HandleObjectInitializer(identifierStart.Unit, n);
if (result != null) if (result != null)
return result; return result;
@ -777,7 +762,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
} }
} }
if (n != null && n.Parent is ObjectCreateExpression) { if (n != null && n.Parent is ObjectCreateExpression) {
var invokeResult = ResolveExpression(n.Parent); var invokeResult = ResolveExpression(n.Parent);
var mgr = invokeResult != null ? invokeResult.Item1 as ResolveResult : null; var mgr = invokeResult != null ? invokeResult.Item1 as ResolveResult : null;
@ -1147,6 +1132,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return wrapper.Result; return wrapper.Result;
} }
} }
/* if (Unit != null && (node == null || node is TypeDeclaration)) { /* if (Unit != null && (node == null || node is TypeDeclaration)) {
var constructor = Unit.GetNodeAt<ConstructorDeclaration>( var constructor = Unit.GetNodeAt<ConstructorDeclaration>(
location.Line, location.Line,
@ -1192,6 +1178,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
void AddContextCompletion(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node) void AddContextCompletion(CompletionDataWrapper wrapper, CSharpResolver state, AstNode node)
{ {
int i = offset - 1;
var isInGlobalDelegate = node == null && state.CurrentTypeDefinition == null && GetPreviousToken(ref i, true) == "delegate";
if (state != null && !(node is AstType)) { if (state != null && !(node is AstType)) {
foreach (var variable in state.LocalVariables) { foreach (var variable in state.LocalVariables) {
if (variable.Region.IsInside(location.Line, location.Column - 1)) { if (variable.Region.IsInside(location.Line, location.Column - 1)) {
@ -1222,10 +1211,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return t.GetAllBaseTypeDefinitions().Any(bt => bt.Equals(attribute)) ? t : null; return t.GetAllBaseTypeDefinitions().Any(bt => bt.Equals(attribute)) ? t : null;
}; };
} }
AddTypesAndNamespaces(wrapper, state, node, typePred); if (node != null || state.CurrentTypeDefinition != null || isInGlobalDelegate) {
AddTypesAndNamespaces(wrapper, state, node, typePred);
wrapper.Result.Add(factory.CreateLiteralCompletionData("global"));
wrapper.Result.Add(factory.CreateLiteralCompletionData("global"));
}
if (!(node is AstType)) { if (!(node is AstType)) {
if (currentMember != null || node is Expression) { if (currentMember != null || node is Expression) {
AddKeywords(wrapper, statementStartKeywords); AddKeywords(wrapper, statementStartKeywords);
@ -1235,7 +1226,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} else if (currentType != null) { } else if (currentType != null) {
AddKeywords(wrapper, typeLevelKeywords); AddKeywords(wrapper, typeLevelKeywords);
} else { } else {
AddKeywords(wrapper, globalLevelKeywords); if (!isInGlobalDelegate)
AddKeywords(wrapper, globalLevelKeywords);
} }
var prop = currentMember as IUnresolvedProperty; var prop = currentMember as IUnresolvedProperty;
if (prop != null && prop.Setter != null && prop.Setter.Region.IsInside(location)) { if (prop != null && prop.Setter != null && prop.Setter.Region.IsInside(location)) {
@ -1253,7 +1245,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
AddKeywords(wrapper, parameterTypePredecessorKeywords); AddKeywords(wrapper, parameterTypePredecessorKeywords);
} }
} }
AddKeywords(wrapper, primitiveTypesKeywords);
if (node != null || state.CurrentTypeDefinition != null || isInGlobalDelegate)
AddKeywords(wrapper, primitiveTypesKeywords);
if (currentMember != null && (node is IdentifierExpression || node is SimpleType) && (node.Parent is ExpressionStatement || node.Parent is ForeachStatement || node.Parent is UsingStatement)) { if (currentMember != null && (node is IdentifierExpression || node is SimpleType) && (node.Parent is ExpressionStatement || node.Parent is ForeachStatement || node.Parent is UsingStatement)) {
wrapper.AddCustom("var"); wrapper.AddCustom("var");
wrapper.AddCustom("dynamic"); wrapper.AddCustom("dynamic");
@ -1342,7 +1336,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
} }
if (this.currentMember != null && !(node is AstType)) { if (this.currentMember != null && !(node is AstType)) {
var def = ctx.CurrentTypeDefinition ?? Compilation.MainAssembly.GetTypeDefinition(currentType); var def = ctx.CurrentTypeDefinition;
if (def == null && currentType != null)
def = Compilation.MainAssembly.GetTypeDefinition(currentType.FullTypeName);
if (def != null) { if (def != null) {
bool isProtectedAllowed = true; bool isProtectedAllowed = true;
foreach (var member in def.GetMembers ()) { foreach (var member in def.GetMembers ()) {
@ -1791,8 +1787,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
if (hintType is ParameterizedType && hintType.TypeParameterCount == 1 && hintType.FullName == "System.Collections.Generic.IEnumerable") { if (hintType is ParameterizedType && hintType.TypeParameterCount == 1 && hintType.FullName == "System.Collections.Generic.IEnumerable") {
var arg = ((ParameterizedType)hintType).TypeArguments.FirstOrDefault(); var arg = ((ParameterizedType)hintType).TypeArguments.FirstOrDefault();
var array = new ArrayTypeReference(arg.ToTypeReference(), 1).Resolve(ctx); if (arg.Kind != TypeKind.TypeParameter) {
wrapper.AddType(array, amb.ConvertType(array)); var array = new ArrayType (ctx.Compilation, arg, 1);
wrapper.AddType(array, amb.ConvertType(array));
}
} }
} else { } else {
var hint = wrapper.AddType(hintType, DefaultCompletionString); var hint = wrapper.AddType(hintType, DefaultCompletionString);
@ -2014,7 +2012,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
"delegate", "delegate",
"Creates anonymous delegate.", "Creates anonymous delegate.",
"delegate {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString "delegate {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString
); );
} }
var sb = new StringBuilder("("); var sb = new StringBuilder("(");
var sbWithoutTypes = new StringBuilder("("); var sbWithoutTypes = new StringBuilder("(");
@ -2026,10 +2024,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
sb.Append(", "); sb.Append(", ");
sbWithoutTypes.Append(", "); sbWithoutTypes.Append(", ");
} }
var convertedParameter = builder.ConvertParameter (delegateMethod.Parameters [k]); var convertedParameter = builder.ConvertParameter(delegateMethod.Parameters [k]);
if (convertedParameter.ParameterModifier == ParameterModifier.Params) if (convertedParameter.ParameterModifier == ParameterModifier.Params)
convertedParameter.ParameterModifier = ParameterModifier.None; convertedParameter.ParameterModifier = ParameterModifier.None;
sb.Append(convertedParameter.GetText (FormattingPolicy)); sb.Append(convertedParameter.GetText(FormattingPolicy));
sbWithoutTypes.Append(delegateMethod.Parameters [k].Name); sbWithoutTypes.Append(delegateMethod.Parameters [k].Name);
} }
@ -2039,22 +2037,22 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
"delegate" + sb, "delegate" + sb,
"Creates anonymous delegate.", "Creates anonymous delegate.",
"delegate" + sb + " {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString "delegate" + sb + " {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString
); );
if (!completionList.Result.Any(data => data.DisplayText == sb.ToString())) { if (!completionList.Result.Any(data => data.DisplayText == sb.ToString())) {
completionList.AddCustom( completionList.AddCustom(
sb.ToString(), sb.ToString(),
"Creates typed lambda expression.", "Creates typed lambda expression.",
sb + " => |" + (addSemicolon ? ";" : "") sb + " => |" + (addSemicolon ? ";" : "")
); );
} }
if (!delegateMethod.Parameters.Any (p => p.IsOut || p.IsRef) && !completionList.Result.Any(data => data.DisplayText == sbWithoutTypes.ToString())) { if (!delegateMethod.Parameters.Any(p => p.IsOut || p.IsRef) && !completionList.Result.Any(data => data.DisplayText == sbWithoutTypes.ToString())) {
completionList.AddCustom( completionList.AddCustom(
sbWithoutTypes.ToString(), sbWithoutTypes.ToString(),
"Creates lambda expression.", "Creates lambda expression.",
sbWithoutTypes + " => |" + (addSemicolon ? ";" : "") sbWithoutTypes + " => |" + (addSemicolon ? ";" : "")
); );
} }
/* TODO:Make factory method out of it. /* TODO:Make factory method out of it.
// It's needed to temporarly disable inserting auto matching bracket because the anonymous delegates are selectable with '(' // It's needed to temporarly disable inserting auto matching bracket because the anonymous delegates are selectable with '('
@ -2298,7 +2296,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var lookup = new MemberLookup( var lookup = new MemberLookup(
ctx.CurrentTypeDefinition, ctx.CurrentTypeDefinition,
Compilation.MainAssembly Compilation.MainAssembly
); );
if (resolveResult is NamespaceResolveResult) { if (resolveResult is NamespaceResolveResult) {
var nr = (NamespaceResolveResult)resolveResult; var nr = (NamespaceResolveResult)resolveResult;
@ -2317,10 +2315,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
return namespaceContents.Result; return namespaceContents.Result;
} }
IType type = resolveResult.Type; IType type = resolveResult.Type;
if (resolvedNode.Parent is PointerReferenceExpression && (type is PointerType)) { if (resolvedNode.Parent is PointerReferenceExpression && (type is PointerType)) {
type = ((PointerType)type).ElementType; resolveResult = new OperatorResolveResult (((PointerType)type).ElementType, System.Linq.Expressions.ExpressionType.Extension, resolveResult);
} }
//var typeDef = resolveResult.Type.GetDefinition(); //var typeDef = resolveResult.Type.GetDefinition();
@ -2354,7 +2351,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
resolveResult, resolveResult,
((IdentifierExpression)resolvedNode).Identifier, ((IdentifierExpression)resolvedNode).Identifier,
out trr out trr
)) { )) {
if (currentMember != null && mrr.Member.IsStatic ^ currentMember.IsStatic) { if (currentMember != null && mrr.Member.IsStatic ^ currentMember.IsStatic) {
skipNonStaticMembers = true; skipNonStaticMembers = true;
@ -2398,20 +2395,21 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (resolvedNode.Annotation<ObjectCreateExpression>() == null) { if (resolvedNode.Annotation<ObjectCreateExpression>() == null) {
//tags the created expression as part of an object create expression. //tags the created expression as part of an object create expression.
/*
var filteredList = new List<IMember>(); var filteredList = new List<IMember>();
foreach (var member in type.GetMembers ()) { foreach (var member in type.GetMembers ()) {
filteredList.Add(member);
}
foreach (var member in filteredList) {
// Console.WriteLine ("add:" + member + "/" + member.IsStatic);
result.AddMember(member);
}*/
foreach (var member in lookup.GetAccessibleMembers (resolveResult)) {
if (member.EntityType == EntityType.Indexer || member.EntityType == EntityType.Operator || member.EntityType == EntityType.Constructor || member.EntityType == EntityType.Destructor) { if (member.EntityType == EntityType.Indexer || member.EntityType == EntityType.Operator || member.EntityType == EntityType.Constructor || member.EntityType == EntityType.Destructor) {
continue; continue;
} }
if (member.IsExplicitInterfaceImplementation) {
continue;
}
// Console.WriteLine ("member:" + member + member.IsShadowing);
if (!lookup.IsAccessible(member, isProtectedAllowed)) {
// Console.WriteLine ("skip access: " + member.FullName);
continue;
}
if (resolvedNode is BaseReferenceExpression && member.IsAbstract) { if (resolvedNode is BaseReferenceExpression && member.IsAbstract) {
continue; continue;
} }
@ -2435,18 +2433,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (member.EntityType == EntityType.Operator) { if (member.EntityType == EntityType.Operator) {
continue; continue;
} }
if (member.IsExplicitInterfaceImplementation) {
continue; if (member is IMember) {
} result.AddMember ((IMember)member);
if (member.IsShadowing) { } else {
filteredList.RemoveAll(m => m.Name == member.Name); if (resolveResult is TypeResolveResult || includeStaticMembers)
result.AddType ((IType)member, member.Name);
} }
filteredList.Add(member);
}
foreach (var member in filteredList) {
// Console.WriteLine ("add:" + member + "/" + member.IsStatic);
result.AddMember(member);
} }
} }
@ -2492,7 +2485,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return result.Result; return result.Result;
} }
IEnumerable<ICompletionData> CreateCaseCompletionData(TextLocation location) IEnumerable<ICompletionData> CreateCaseCompletionData(TextLocation location)
{ {
var unit = ParseStub("a: break;"); var unit = ParseStub("a: break;");

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs

@ -99,7 +99,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
// current member, instead of the beginning of the file. // current member, instead of the beginning of the file.
cpos = offset - 1; cpos = offset - 1;
var mem = currentMember; var mem = currentMember;
if (mem == null || (mem is IType)) { if (mem == null || (mem is IType) || IsInsideCommentStringOrDirective ()) {
return false; return false;
} }
int startPos = document.GetOffset (mem.Region.BeginLine, mem.Region.BeginColumn); int startPos = document.GetOffset (mem.Region.BeginLine, mem.Region.BeginColumn);

46
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs

@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
yield return method; yield return method;
} }
foreach (var extMethods in resolveResult.GetEligibleExtensionMethods (true)) { foreach (var extMethods in resolveResult.GetEligibleExtensionMethods (true)) {
foreach (var method in extMethods) { foreach (var method in extMethods) {
yield return method; yield return method;
@ -152,7 +152,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (invoke.Node is ConstructorInitializer) { if (invoke.Node is ConstructorInitializer) {
var init = (ConstructorInitializer)invoke.Node; var init = (ConstructorInitializer)invoke.Node;
if (init.ConstructorInitializerType == ConstructorInitializerType.This) { if (init.ConstructorInitializerType == ConstructorInitializerType.This) {
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), ctx.CurrentTypeDefinition); return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), ctx.CurrentTypeDefinition, init);
} else { } else {
var baseType = ctx.CurrentTypeDefinition.DirectBaseTypes.FirstOrDefault(bt => bt.Kind != TypeKind.Interface); var baseType = ctx.CurrentTypeDefinition.DirectBaseTypes.FirstOrDefault(bt => bt.Kind != TypeKind.Interface);
if (baseType == null) { if (baseType == null) {
@ -167,7 +167,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return null; return null;
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type); return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type);
} }
if (invoke.Node is ICSharpCode.NRefactory.CSharp.Attribute) { if (invoke.Node is ICSharpCode.NRefactory.CSharp.Attribute) {
var attribute = ResolveExpression(invoke); var attribute = ResolveExpression(invoke);
if (attribute == null || attribute.Item1 == null) { if (attribute == null || attribute.Item1 == null) {
@ -189,22 +189,22 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), new [] { (IMethod)mr.Member }); return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), new [] { (IMethod)mr.Member });
} }
} }
if (resolveResult.Type.Kind == TypeKind.Delegate) { if (resolveResult.Type.Kind == TypeKind.Delegate) {
return factory.CreateDelegateDataProvider(document.GetOffset(invoke.Node.StartLocation), resolveResult.Type); return factory.CreateDelegateDataProvider(document.GetOffset(invoke.Node.StartLocation), resolveResult.Type);
} }
// //
// if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) { // if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) {
// if (resolveResult is ThisResolveResult) // if (resolveResult is ThisResolveResult)
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult); // return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult);
// if (resolveResult is BaseResolveResult) // if (resolveResult is BaseResolveResult)
// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult); // return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult);
// } // }
// IType resolvedType = resolver.SearchType (resolveResult.ResolvedType); // IType resolvedType = resolver.SearchType (resolveResult.ResolvedType);
// if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) { // if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) {
// return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType); // return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType);
// } // }
break; break;
case ',': case ',':
invoke = GetInvocationBeforeCursor(true) ?? GetIndexerBeforeCursor(); invoke = GetInvocationBeforeCursor(true) ?? GetIndexerBeforeCursor();
@ -217,7 +217,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (typeExpression == null || typeExpression.Item1 == null || typeExpression.Item1.IsError) { if (typeExpression == null || typeExpression.Item1 == null || typeExpression.Item1.IsError) {
return null; return null;
} }
return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(typeExpression.Item1.Type)); return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(typeExpression.Item1.Type));
} }
return null; return null;
@ -228,7 +228,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type); var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type);
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type); return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type);
} }
if (invoke.Node is ICSharpCode.NRefactory.CSharp.Attribute) { if (invoke.Node is ICSharpCode.NRefactory.CSharp.Attribute) {
var attribute = ResolveExpression(invoke); var attribute = ResolveExpression(invoke);
if (attribute == null || attribute.Item1 == null) { if (attribute == null || attribute.Item1 == null) {
@ -236,13 +236,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} }
return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), attribute.Item1.Type); return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), attribute.Item1.Type);
} }
invocationExpression = ResolveExpression(invoke); invocationExpression = ResolveExpression(invoke);
if (invocationExpression == null || invocationExpression.Item1 == null || invocationExpression.Item1.IsError) { if (invocationExpression == null || invocationExpression.Item1 == null || invocationExpression.Item1.IsError) {
return null; return null;
} }
resolveResult = invocationExpression.Item1; resolveResult = invocationExpression.Item1;
if (resolveResult is MethodGroupResolveResult) { if (resolveResult is MethodGroupResolveResult) {
return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectMethods(invoke.Node, resolveResult as MethodGroupResolveResult)); return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectMethods(invoke.Node, resolveResult as MethodGroupResolveResult));
@ -269,7 +269,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (tExpr == null || tExpr.Item1 == null || tExpr.Item1.IsError) { if (tExpr == null || tExpr.Item1 == null || tExpr.Item1.IsError) {
return null; return null;
} }
return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(tExpr.Item1.Type)); return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(tExpr.Item1.Type));
case '[': case '[':
invoke = GetIndexerBeforeCursor(); invoke = GetIndexerBeforeCursor();
@ -320,7 +320,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return result; return result;
} }
} }
} }

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs

@ -35,6 +35,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
{ {
IParameterDataProvider CreateConstructorProvider (int startOffset, IType type); IParameterDataProvider CreateConstructorProvider (int startOffset, IType type);
/// <summary>
/// Creates a constructor provider skipping the parent of thisInitializer.
/// </summary>
IParameterDataProvider CreateConstructorProvider (int startOffset, IType type, AstNode thisInitializer);
IParameterDataProvider CreateMethodDataProvider (int startOffset, IEnumerable<IMethod> methods); IParameterDataProvider CreateMethodDataProvider (int startOffset, IEnumerable<IMethod> methods);
IParameterDataProvider CreateDelegateDataProvider (int startOffset, IType type); IParameterDataProvider CreateDelegateDataProvider (int startOffset, IType type);

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs

@ -739,15 +739,15 @@ namespace ICSharpCode.NRefactory.CSharp
} }
var lastLoc = fieldDeclaration.StartLocation; var lastLoc = fieldDeclaration.StartLocation;
curIndent.Push(IndentType.Block);
foreach (var initializer in fieldDeclaration.Variables) { foreach (var initializer in fieldDeclaration.Variables) {
if (lastLoc.Line != initializer.StartLocation.Line) { if (lastLoc.Line != initializer.StartLocation.Line) {
curIndent.Push(IndentType.Block);
FixStatementIndentation(initializer.StartLocation); FixStatementIndentation(initializer.StartLocation);
curIndent.Pop ();
lastLoc = initializer.StartLocation; lastLoc = initializer.StartLocation;
} }
initializer.AcceptVisitor(this); initializer.AcceptVisitor(this);
} }
curIndent.Pop ();
} }
public override void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration) public override void VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
@ -1179,8 +1179,10 @@ namespace ICSharpCode.NRefactory.CSharp
nextStatementIndent = " "; nextStatementIndent = " ";
} }
} }
bool pushed = false;
if (policy.IndentBlocks && !(policy.AlignEmbeddedIfStatements && node is IfElseStatement && node.Parent is IfElseStatement || policy.AlignEmbeddedUsingStatements && node is UsingStatement && node.Parent is UsingStatement)) { if (policy.IndentBlocks && !(policy.AlignEmbeddedIfStatements && node is IfElseStatement && node.Parent is IfElseStatement || policy.AlignEmbeddedUsingStatements && node is UsingStatement && node.Parent is UsingStatement)) {
curIndent.Push(IndentType.Block); curIndent.Push(IndentType.Block);
pushed = true;
} }
if (isBlock) { if (isBlock) {
VisitBlockWithoutFixingBraces((BlockStatement)node, false); VisitBlockWithoutFixingBraces((BlockStatement)node, false);
@ -1190,7 +1192,7 @@ namespace ICSharpCode.NRefactory.CSharp
} }
node.AcceptVisitor(this); node.AcceptVisitor(this);
} }
if (policy.IndentBlocks && !(policy.AlignEmbeddedIfStatements && node is IfElseStatement && node.Parent is IfElseStatement || policy.AlignEmbeddedUsingStatements && node is UsingStatement && node.Parent is UsingStatement)) { if (pushed) {
curIndent.Pop(); curIndent.Pop();
} }
switch (braceForcement) { switch (braceForcement) {
@ -2105,6 +2107,10 @@ namespace ICSharpCode.NRefactory.CSharp
void FixStatementIndentation(TextLocation location) void FixStatementIndentation(TextLocation location)
{ {
if (location.Line < 1 || location.Column < 1) {
Console.WriteLine("invalid location!");
return;
}
int offset = document.GetOffset(location); int offset = document.GetOffset(location);
if (offset <= 0) { if (offset <= 0) {
Console.WriteLine("possible wrong offset"); Console.WriteLine("possible wrong offset");

1
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/FormattingOptionsFactory.cs

@ -82,6 +82,7 @@ namespace ICSharpCode.NRefactory.CSharp
StatementBraceStyle = BraceStyle.EndOfLine, StatementBraceStyle = BraceStyle.EndOfLine,
ElseNewLinePlacement = NewLinePlacement.SameLine, ElseNewLinePlacement = NewLinePlacement.SameLine,
ElseIfNewLinePlacement = NewLinePlacement.SameLine,
CatchNewLinePlacement = NewLinePlacement.SameLine, CatchNewLinePlacement = NewLinePlacement.SameLine,
FinallyNewLinePlacement = NewLinePlacement.SameLine, FinallyNewLinePlacement = NewLinePlacement.SameLine,
WhileNewLinePlacement = NewLinePlacement.SameLine, WhileNewLinePlacement = NewLinePlacement.SameLine,

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

@ -476,7 +476,6 @@
<Compile Include="Refactoring\NamingHelper.cs" /> <Compile Include="Refactoring\NamingHelper.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\ConvertToInitializerAction.cs" /> <Compile Include="Refactoring\CodeActions\ConvertToInitializer\ConvertToInitializerAction.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\StatementsToInitializerConverter.cs" /> <Compile Include="Refactoring\CodeActions\ConvertToInitializer\StatementsToInitializerConverter.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\InitializerPath.cs" />
<Compile Include="Refactoring\CodeActions\MoveToOuterScopeAction.cs" /> <Compile Include="Refactoring\CodeActions\MoveToOuterScopeAction.cs" />
<Compile Include="Refactoring\CodeIssues\VariableDeclaredInWideScopeIssue.cs" /> <Compile Include="Refactoring\CodeIssues\VariableDeclaredInWideScopeIssue.cs" />
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\ParameterCanBeDemotedIssue.cs" /> <Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\ParameterCanBeDemotedIssue.cs" />
@ -503,6 +502,7 @@
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\IsArrayTypeCriterion.cs" /> <Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\IsArrayTypeCriterion.cs" />
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\SupportsIndexingCriterion.cs" /> <Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\SupportsIndexingCriterion.cs" />
<Compile Include="Refactoring\CodeIssues\RedundantWhereWithPredicateIssue.cs" /> <Compile Include="Refactoring\CodeIssues\RedundantWhereWithPredicateIssue.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\AccessPath.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> <ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">

1
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CheckIfParameterIsNullAction.cs

@ -54,7 +54,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Condition = new BinaryOperatorExpression (new IdentifierExpression (parameter.Name), BinaryOperatorType.Equality, new NullReferenceExpression ()), Condition = new BinaryOperatorExpression (new IdentifierExpression (parameter.Name), BinaryOperatorType.Equality, new NullReferenceExpression ()),
TrueStatement = new ThrowStatement (new ObjectCreateExpression (context.CreateShortType("System", "ArgumentNullException"), new PrimitiveExpression (parameter.Name))) TrueStatement = new ThrowStatement (new ObjectCreateExpression (context.CreateShortType("System", "ArgumentNullException"), new PrimitiveExpression (parameter.Name)))
}; };
System.Console.WriteLine(bodyStatement.StartLocation +"/" + bodyStatement.EndLocation);
script.AddTo(bodyStatement, statement); script.AddTo(bodyStatement, statement);
}); });
} }

85
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/InitializerPath.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/AccessPath.cs

@ -32,25 +32,16 @@ using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
class InitializerPath class AccessPath
{ {
InitializerPath(object anchor) public AccessPath(IVariable target)
{ {
this.anchor = anchor; VariableRoot = target;
MemberPath = new List<IMember>(); MemberPath = new List<IMember>();
} }
public InitializerPath(IVariable target) : this((object)target) public static AccessPath FromResolveResult(ResolveResult resolveResult)
{ {
}
public InitializerPath(IMember target) : this((object)target)
{
}
public static InitializerPath FromResolveResult(ResolveResult resolveResult)
{
InitializerPath initializerPath = null;
var memberPath = new List<IMember>(); var memberPath = new List<IMember>();
var currentResolveResult = resolveResult; var currentResolveResult = resolveResult;
do { do {
@ -59,42 +50,38 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
memberPath.Add(memberResolveResult.Member); memberPath.Add(memberResolveResult.Member);
currentResolveResult = memberResolveResult.TargetResult; currentResolveResult = memberResolveResult.TargetResult;
} else if (currentResolveResult is LocalResolveResult) { } else if (currentResolveResult is LocalResolveResult) {
// This is the root variable
var localResolveResult = (LocalResolveResult)currentResolveResult; var localResolveResult = (LocalResolveResult)currentResolveResult;
memberPath.Reverse(); memberPath.Reverse();
initializerPath = new InitializerPath(localResolveResult.Variable) { return new AccessPath(localResolveResult.Variable) {
MemberPath = memberPath MemberPath = memberPath
}; };
break;
} else if (currentResolveResult is ThisResolveResult) { } else if (currentResolveResult is ThisResolveResult) {
break; break;
} else { } else {
// Unsupported path
return null; return null;
} }
} while (currentResolveResult != null); } while (currentResolveResult != null);
if (initializerPath == null) { memberPath.Reverse();
// This path is rooted at a member return new AccessPath(null) {
memberPath.Reverse(); MemberPath = memberPath
initializerPath = new InitializerPath(memberPath [0]) { };
MemberPath = memberPath.Skip(1).ToList()
};
}
return initializerPath;
} }
public InitializerPath GetParentPath() public AccessPath GetParentPath()
{ {
if (MemberPath.Count < 1) if (MemberPath.Count < 1)
throw new InvalidOperationException("Cannot get the parent path of a path that does not contain any members."); throw new InvalidOperationException("Cannot get the parent path of a path that does not contain any members.");
return new InitializerPath(anchor) { return new AccessPath(VariableRoot) {
MemberPath = MemberPath.Take(MemberPath.Count - 1).ToList() MemberPath = MemberPath.Take(MemberPath.Count - 1).ToList()
}; };
} }
public bool IsSubPath(InitializerPath other) public bool IsSubPath(AccessPath other)
{ {
if (!other.anchor.Equals(anchor)) if (!object.Equals(other.VariableRoot, VariableRoot))
return false; return false;
if (MemberPath.Count <= other.MemberPath.Count) if (MemberPath.Count <= other.MemberPath.Count)
return false; return false;
@ -105,22 +92,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return true; return true;
} }
object anchor; public IVariable VariableRoot { get; set; }
public IVariable VariableRoot { public int PartCount {
get { return anchor as IVariable; } get {
} return MemberPath.Count + (VariableRoot == null ? 0 : 1);
}
public IMember MemberRoot {
get { return anchor as IMember; }
} }
public string RootName { public string RootName {
get { get {
if (anchor is IMember) if (VariableRoot != null)
return (anchor as IMember).Name; return VariableRoot.Name;
else return MemberPath.First().Name;
return (anchor as IVariable).Name;
} }
} }
@ -128,12 +112,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj.GetType() != typeof(InitializerPath)) if (obj.GetType() != typeof(AccessPath))
return false; return false;
var other = (InitializerPath)obj; var other = (AccessPath)obj;
if (!object.Equals(anchor, other.anchor)) if (!object.Equals(VariableRoot, other.VariableRoot))
return false; return false;
if (MemberPath.Count != other.MemberPath.Count) if (MemberPath.Count != other.MemberPath.Count)
@ -148,29 +132,28 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override int GetHashCode() public override int GetHashCode()
{ {
int hash = anchor.GetHashCode(); int hash = VariableRoot != null ? VariableRoot.GetHashCode() : 37;
foreach (var member in MemberPath) foreach (var member in MemberPath)
hash ^= member.GetHashCode(); hash ^= 31 * member.GetHashCode();
return hash; return hash;
} }
public static bool operator==(InitializerPath left, InitializerPath right) public static bool operator==(AccessPath left, AccessPath right)
{ {
return object.Equals(left, right); return object.Equals(left, right);
} }
public static bool operator!=(InitializerPath left, InitializerPath right) public static bool operator!=(AccessPath left, AccessPath right)
{ {
return !object.Equals(left, right); return !object.Equals(left, right);
} }
public override string ToString() public override string ToString()
{ {
if (MemberPath.Count > 0) string memberPathString = string.Join(".", MemberPath.Select<IMember, string>(member => member.Name));
return string.Format("[InitializerPath: {0}.{1}]", RootName, if (VariableRoot == null)
string.Join(".", MemberPath.Select<IMember, string>(member => member.Name))); return string.Format("[AccessPath: {0}]", memberPathString);
else return string.Format("[AccessPath: {0}.{1}]", VariableRoot.Name, memberPathString);
return string.Format("[InitializerPath: {0}]", RootName);
} }
} }

100
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs

@ -37,9 +37,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
public class StatementsToInitializerConverter public class StatementsToInitializerConverter
{ {
IDictionary<InitializerPath, Expression> initializers = new Dictionary<InitializerPath, Expression>(); IDictionary<AccessPath, Expression> accessPaths = new Dictionary<AccessPath, Expression>();
IList<Comment> comments = new List<Comment>(); IList<Comment> comments = new List<Comment>();
InitializerPath mainInitializerPath; AccessPath mainAccessPath;
RefactoringContext context; RefactoringContext context;
public StatementsToInitializerConverter(RefactoringContext context) public StatementsToInitializerConverter(RefactoringContext context)
@ -50,13 +50,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
void Initialize(AstNode targetNode) void Initialize(AstNode targetNode)
{ {
var target = context.Resolve(targetNode); var target = context.Resolve(targetNode);
if (target is LocalResolveResult) { var targetInitializerPath = AccessPath.FromResolveResult(target);
mainInitializerPath = new InitializerPath(((LocalResolveResult)target).Variable); if (targetInitializerPath == null)
} else if (target is MemberResolveResult) { throw new ArgumentException(string.Format("Could not create the main initializer path from resolve result ({0})", target));
mainInitializerPath = new InitializerPath(((MemberResolveResult)target).Member);
} else { mainAccessPath = targetInitializerPath;
throw new ArgumentException("variableInitializer must target a variable or a member.");
}
} }
public VariableInitializer ConvertToInitializer(VariableInitializer variableInitializer, ref IList<AstNode> statements) public VariableInitializer ConvertToInitializer(VariableInitializer variableInitializer, ref IList<AstNode> statements)
@ -67,11 +65,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
throw new ArgumentNullException("statements"); throw new ArgumentNullException("statements");
Initialize(variableInitializer); Initialize(variableInitializer);
initializers [mainInitializerPath] = variableInitializer.Initializer.Clone(); accessPaths [mainAccessPath] = variableInitializer.Initializer.Clone();
Convert(statements); Convert(statements);
statements = ReplacementNodeHelper.GetReplacedNodes(initializers [mainInitializerPath]); statements = ReplacementNodeHelper.GetReplacedNodes(accessPaths [mainAccessPath]);
return new VariableInitializer(mainInitializerPath.RootName, initializers [mainInitializerPath]); return new VariableInitializer(mainAccessPath.RootName, accessPaths [mainAccessPath]);
} }
public AssignmentExpression ConvertToInitializer(AssignmentExpression assignmentExpression, ref IList<AstNode> statements) public AssignmentExpression ConvertToInitializer(AssignmentExpression assignmentExpression, ref IList<AstNode> statements)
@ -84,11 +82,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
throw new ArgumentException("assignmentExpression.Right must be an ObjectCreateExpression", "assignmentExpression"); throw new ArgumentException("assignmentExpression.Right must be an ObjectCreateExpression", "assignmentExpression");
Initialize(assignmentExpression.Left); Initialize(assignmentExpression.Left);
initializers [mainInitializerPath] = assignmentExpression.Right.Clone(); accessPaths [mainAccessPath] = assignmentExpression.Right.Clone();
Convert(statements); Convert(statements);
statements = ReplacementNodeHelper.GetReplacedNodes(initializers [mainInitializerPath]); statements = ReplacementNodeHelper.GetReplacedNodes(accessPaths [mainAccessPath]);
return new AssignmentExpression(new IdentifierExpression(mainInitializerPath.RootName), initializers [mainInitializerPath]); return new AssignmentExpression(new IdentifierExpression(mainAccessPath.RootName), accessPaths [mainAccessPath]);
} }
void Convert(IList<AstNode> originalStatements) void Convert(IList<AstNode> originalStatements)
@ -123,7 +121,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
VariableInitializer variableInitializer; VariableInitializer variableInitializer;
var variableDeclarationStatement = node as VariableDeclarationStatement; var variableDeclarationStatement = node as VariableDeclarationStatement;
if (variableDeclarationStatement == null) { if (variableDeclarationStatement == null) {
variableInitializer = VariableInitializer.Null;
return false; return false;
} }
variableInitializer = variableDeclarationStatement.Variables.FirstOrNullObject(); variableInitializer = variableDeclarationStatement.Variables.FirstOrNullObject();
@ -142,7 +139,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var invocationExpression = expressionStatement.Expression as InvocationExpression; var invocationExpression = expressionStatement.Expression as InvocationExpression;
if (invocationExpression == null) if (invocationExpression == null)
return false; return false;
var target = invocationExpression.Target;
var invocationResolveResult = context.Resolve(invocationExpression) as InvocationResolveResult; var invocationResolveResult = context.Resolve(invocationExpression) as InvocationResolveResult;
if (invocationResolveResult == null) if (invocationResolveResult == null)
return false; return false;
@ -152,15 +148,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (targetResult is MemberResolveResult) if (targetResult is MemberResolveResult)
return false; return false;
ArrayInitializerExpression tuple = new ArrayInitializerExpression(); var tuple = new ArrayInitializerExpression();
foreach (var argument in invocationExpression.Arguments) { foreach (var argument in invocationExpression.Arguments) {
var argumentLocalResolveResult = context.Resolve(argument) as LocalResolveResult; var argumentLocalResolveResult = context.Resolve(argument) as LocalResolveResult;
if (argumentLocalResolveResult != null) { if (argumentLocalResolveResult != null) {
var initializerPath = InitializerPath.FromResolveResult(argumentLocalResolveResult); var initializerPath = AccessPath.FromResolveResult(argumentLocalResolveResult);
if (initializerPath == null || !initializers.ContainsKey(initializerPath)) if (initializerPath == null || !accessPaths.ContainsKey(initializerPath))
return false; return false;
// Add a clone, since we do not yet know if this is where the initializer will be used // Add a clone, since we do not yet know if this is where the initializer will be used
var initializerClone = initializers[initializerPath].Clone(); var initializerClone = accessPaths[initializerPath].Clone();
tuple.Elements.Add(initializerClone); tuple.Elements.Add(initializerClone);
} else { } else {
tuple.Elements.Add(argument.Clone()); tuple.Elements.Add(argument.Clone());
@ -168,11 +164,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
ReplacementNodeHelper.AddReplacementAnnotation(tuple, expressionStatement); ReplacementNodeHelper.AddReplacementAnnotation(tuple, expressionStatement);
var targetPath = InitializerPath.FromResolveResult(targetResult); var targetPath = AccessPath.FromResolveResult(targetResult);
if (targetPath == null || !initializers.ContainsKey(targetPath)) if (targetPath == null || !accessPaths.ContainsKey(targetPath))
return false; return false;
InsertImplicitInitializersForPath(targetPath); InsertImplicitInitializersForPath(targetPath);
var targetInitializer = initializers [targetPath]; var targetInitializer = accessPaths [targetPath];
AddToInitializer(targetInitializer, tuple); AddToInitializer(targetInitializer, tuple);
return true; return true;
} }
@ -196,29 +192,29 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
void AddNewVariable(IVariable variable, Expression initializer, AstNode node) void AddNewVariable(IVariable variable, Expression initializer, AstNode node)
{ {
var variablePath = new InitializerPath(variable); var variablePath = new AccessPath(variable);
var rightResolveResult = context.Resolve(initializer) as LocalResolveResult; var rightResolveResult = context.Resolve(initializer) as LocalResolveResult;
if (rightResolveResult != null) { if (rightResolveResult != null) {
var rightPath = InitializerPath.FromResolveResult(rightResolveResult); var rightPath = AccessPath.FromResolveResult(rightResolveResult);
if (rightPath != null && initializers.ContainsKey(rightPath)) { if (rightPath != null && accessPaths.ContainsKey(rightPath)) {
var rightInitializer = initializers [rightPath]; var rightInitializer = accessPaths [rightPath];
ReplacementNodeHelper.AddReplacementAnnotation(rightInitializer, node); ReplacementNodeHelper.AddReplacementAnnotation(rightInitializer, node);
initializers.Remove(rightPath); accessPaths.Remove(rightPath);
initializers [variablePath] = rightInitializer; accessPaths [variablePath] = rightInitializer;
if (rightPath == mainInitializerPath) { if (rightPath == mainAccessPath) {
mainInitializerPath = variablePath; mainAccessPath = variablePath;
} }
} }
} else { } else {
initializers [variablePath] = ReplacementNodeHelper.CloneWithReplacementAnnotation(initializer, node); accessPaths [variablePath] = ReplacementNodeHelper.CloneWithReplacementAnnotation(initializer, node);
} }
} }
void AddOldAnnotationsToInitializer(InitializerPath targetPath, Expression initializer) void AddOldAnnotationsToInitializer(AccessPath targetPath, IAnnotatable initializer)
{ {
if (targetPath != null) { if (targetPath != null) {
if (initializers.ContainsKey(targetPath)) { if (accessPaths.ContainsKey(targetPath)) {
foreach (var astNode in ReplacementNodeHelper.GetAllReplacementAnnotations(initializers[targetPath])) { foreach (var astNode in ReplacementNodeHelper.GetAllReplacementAnnotations(accessPaths[targetPath])) {
initializer.AddAnnotation(astNode); initializer.AddAnnotation(astNode);
} }
} }
@ -231,16 +227,16 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var leftResolveResult = context.Resolve(left); var leftResolveResult = context.Resolve(left);
Expression initializer; Expression initializer;
if (rightResolveResult != null) { if (rightResolveResult != null) {
var rightPath = InitializerPath.FromResolveResult(rightResolveResult); var rightPath = AccessPath.FromResolveResult(rightResolveResult);
if (initializers.ContainsKey(rightPath)) { if (accessPaths.ContainsKey(rightPath)) {
initializer = initializers [rightPath]; initializer = accessPaths [rightPath];
} else { } else {
initializer = right.Clone(); initializer = right.Clone();
} }
} else { } else {
initializer = right.Clone(); initializer = right.Clone();
} }
var leftPath = InitializerPath.FromResolveResult(leftResolveResult); var leftPath = AccessPath.FromResolveResult(leftResolveResult);
if (leftPath == null) { if (leftPath == null) {
return false; return false;
} }
@ -249,15 +245,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
// to the same variable/member. // to the same variable/member.
AddOldAnnotationsToInitializer(leftPath, initializer); AddOldAnnotationsToInitializer(leftPath, initializer);
if (leftPath.MemberPath.Count == 0) { if (leftPath.PartCount == 1) {
ReplacementNodeHelper.AddReplacementAnnotation(initializer, node); ReplacementNodeHelper.AddReplacementAnnotation(initializer, node);
initializers [leftPath] = initializer; accessPaths [leftPath] = initializer;
return true; return true;
} }
if (!(leftResolveResult is MemberResolveResult)) if (!(leftResolveResult is MemberResolveResult))
return false; return false;
Debug.Assert(leftPath.MemberPath.Count > 0, "No top level assignment should get here."); Debug.Assert(leftPath.PartCount > 1, "No top level assignment should get here.");
var parentKey = leftPath.GetParentPath(); var parentKey = leftPath.GetParentPath();
var member = leftPath.MemberPath.Last(); var member = leftPath.MemberPath.Last();
@ -266,13 +262,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (!success) if (!success)
return false; return false;
var parentInitializer = initializers [parentKey]; var parentInitializer = accessPaths [parentKey];
AddToInitializer(parentInitializer, comments.ToArray()); AddToInitializer(parentInitializer, comments.ToArray());
comments.Clear(); comments.Clear();
AddToInitializer(parentInitializer, new NamedExpression(member.Name, initializer)); AddToInitializer(parentInitializer, new NamedExpression(member.Name, initializer));
ReplacementNodeHelper.AddReplacementAnnotation(initializer, node); ReplacementNodeHelper.AddReplacementAnnotation(initializer, node);
initializers [leftPath] = initializer; accessPaths [leftPath] = initializer;
return true; return true;
} }
@ -347,8 +343,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var resolveResult = context.Resolve(memberReference) as MemberResolveResult; var resolveResult = context.Resolve(memberReference) as MemberResolveResult;
if (resolveResult == null) if (resolveResult == null)
continue; continue;
var initializerPath = InitializerPath.FromResolveResult(resolveResult); var initializerPath = AccessPath.FromResolveResult(resolveResult);
if (initializerPath != null && initializers.ContainsKey(initializerPath)) if (initializerPath != null && accessPaths.ContainsKey(initializerPath))
return true; return true;
} }
return false; return false;
@ -356,12 +352,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
bool VariableHasBeenConverted(IVariable variable) bool VariableHasBeenConverted(IVariable variable)
{ {
return initializers.Any(item => item.Key.VariableRoot.Equals(variable)); return accessPaths.Any(item => item.Key.VariableRoot.Equals(variable));
} }
bool InsertImplicitInitializersForPath(InitializerPath path) bool InsertImplicitInitializersForPath(AccessPath path)
{ {
if (initializers.ContainsKey(path)) if (accessPaths.ContainsKey(path))
return true; return true;
if (path.MemberPath.Count == 0) if (path.MemberPath.Count == 0)
@ -371,11 +367,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (!success) if (!success)
return false; return false;
var parentInitializer = initializers [parentPath]; var parentInitializer = accessPaths [parentPath];
var initializer = new ArrayInitializerExpression(); var initializer = new ArrayInitializerExpression();
var namedExpression = new NamedExpression(path.MemberPath [path.MemberPath.Count - 1].Name, initializer); var namedExpression = new NamedExpression(path.MemberPath [path.MemberPath.Count - 1].Name, initializer);
AddToInitializer(parentInitializer, namedExpression); AddToInitializer(parentInitializer, namedExpression);
initializers [path] = initializer; accessPaths [path] = initializer;
return true; return true;
} }

17
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/AssignmentMadeToSameVariableIssue.cs

@ -29,6 +29,7 @@ using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.PatternMatching; using ICSharpCode.NRefactory.PatternMatching;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
@ -62,14 +63,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var resolveResult = ctx.Resolve (assignmentExpression.Left); var resolveResult = ctx.Resolve (assignmentExpression.Left);
var memberResolveResult = resolveResult as MemberResolveResult; var memberResolveResult = resolveResult as MemberResolveResult;
if (memberResolveResult != null) { if (memberResolveResult != null) {
if (!(memberResolveResult.Member is IField)) var memberResolveResult2 = ctx.Resolve (assignmentExpression.Right) as MemberResolveResult;
if (memberResolveResult2 == null || !AreEquivalent(memberResolveResult, memberResolveResult2))
return; return;
if (!assignmentExpression.Left.Match (assignmentExpression.Right).Success) {
// in case: this.field = field
var memberResolveResult2 = ctx.Resolve (assignmentExpression.Right) as MemberResolveResult;
if (memberResolveResult2 == null || memberResolveResult.Member != memberResolveResult2.Member)
return;
}
} else if (resolveResult is LocalResolveResult) { } else if (resolveResult is LocalResolveResult) {
if (!assignmentExpression.Left.Match (assignmentExpression.Right).Success) if (!assignmentExpression.Left.Match (assignmentExpression.Right).Success)
return; return;
@ -89,6 +85,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
AddIssue (node, ctx.TranslateString ("CS1717:Assignment made to same variable"), AddIssue (node, ctx.TranslateString ("CS1717:Assignment made to same variable"),
new [] { new CodeAction (ctx.TranslateString ("Remove assignment"), action) }); new [] { new CodeAction (ctx.TranslateString ("Remove assignment"), action) });
} }
static bool AreEquivalent(ResolveResult first, ResolveResult second)
{
var firstPath = AccessPath.FromResolveResult(first);
var secondPath = AccessPath.FromResolveResult(second);
return firstPath != null && firstPath.Equals(secondPath) && !firstPath.MemberPath.Any(m => !(m is IField));
}
} }
} }
} }

3
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantToStringIssue.cs

@ -79,7 +79,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolveResult == null) { if (resolveResult == null) {
return; return;
} }
if (resolveResult.Member.Name != "ToString") { var member = resolveResult.Member;
if (member.Name != "ToString" || member.Parameters.Count != 0) {
return; return;
} }
AddRedundantToStringIssue(memberExpression, invocationExpression); AddRedundantToStringIssue(memberExpression, invocationExpression);

36
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/RedundantTypeCastIssue.cs

@ -28,6 +28,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
@ -73,17 +74,45 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var invocationExpr = memberRefExpr.Parent as InvocationExpression; var invocationExpr = memberRefExpr.Parent as InvocationExpression;
if (invocationExpr != null && invocationExpr.Target == memberRefExpr) { if (invocationExpr != null && invocationExpr.Target == memberRefExpr) {
var invocationResolveResult = ctx.Resolve (invocationExpr) as InvocationResolveResult; var invocationResolveResult = ctx.Resolve (invocationExpr) as InvocationResolveResult;
if (invocationResolveResult != null) if (invocationResolveResult != null) {
return invocationResolveResult.Member.DeclaringType; return invocationResolveResult.Member.DeclaringType;
}
} else { } else {
var memberResolveResult = ctx.Resolve (memberRefExpr) as MemberResolveResult; var memberResolveResult = ctx.Resolve (memberRefExpr) as MemberResolveResult;
if (memberResolveResult != null) if (memberResolveResult != null) {
return memberResolveResult.Member.DeclaringType; return memberResolveResult.Member.DeclaringType;
}
} }
} }
return ctx.GetExpectedType (typeCastNode); return ctx.GetExpectedType (typeCastNode);
} }
bool IsExplicitImplementation(IType exprType, IType interfaceType, Expression typeCastNode)
{
var memberRefExpr = typeCastNode.Parent as MemberReferenceExpression;
if (memberRefExpr != null) {
var rr = ctx.Resolve(memberRefExpr);
var memberResolveResult = rr as MemberResolveResult;
if (memberResolveResult != null) {
foreach (var member in exprType.GetMembers (m => m.EntityType == memberResolveResult.Member.EntityType)) {
if (member.IsExplicitInterfaceImplementation && member.ImplementedInterfaceMembers.Contains (memberResolveResult.Member)) {
return true;
}
}
}
var methodGroupResolveResult = rr as MethodGroupResolveResult;
if (methodGroupResolveResult != null) {
foreach (var member in exprType.GetMethods ()) {
if (member.IsExplicitInterfaceImplementation && member.ImplementedInterfaceMembers.Any (m => methodGroupResolveResult.Methods.Contains ((IMethod)m))) {
return true;
}
}
}
}
return false;
}
void AddIssue (Expression typeCastNode, Expression expr, TextLocation start, TextLocation end) void AddIssue (Expression typeCastNode, Expression expr, TextLocation start, TextLocation end)
{ {
AddIssue (start, end, ctx.TranslateString ("Remove redundant type cast"), AddIssue (start, end, ctx.TranslateString ("Remove redundant type cast"),
@ -94,9 +123,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
while (typeCastNode.Parent != null && typeCastNode.Parent is ParenthesizedExpression) while (typeCastNode.Parent != null && typeCastNode.Parent is ParenthesizedExpression)
typeCastNode = (Expression)typeCastNode.Parent; typeCastNode = (Expression)typeCastNode.Parent;
var expectedType = GetExpectedType (typeCastNode); var expectedType = GetExpectedType (typeCastNode);
var exprType = ctx.Resolve (expr).Type; var exprType = ctx.Resolve (expr).Type;
if (expectedType.Kind == TypeKind.Interface && IsExplicitImplementation (exprType, expectedType, typeCastNode))
return;
if (exprType.GetAllBaseTypes ().Any (t => t.Equals(expectedType))) if (exprType.GetAllBaseTypes ().Any (t => t.Equals(expectedType)))
AddIssue (typeCastNode, expr, castStart, castEnd); AddIssue (typeCastNode, expr, castStart, castEnd);
} }

57
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/StringIsNullOrEmptyIssue.cs

@ -41,47 +41,76 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public class StringIsNullOrEmptyIssue : ICodeIssueProvider public class StringIsNullOrEmptyIssue : ICodeIssueProvider
{ {
static readonly Pattern pattern = new Choice { static readonly Pattern pattern = new Choice {
// str == null || str == "" // str == null || str == ""
// str == null || str.Length == 0
new BinaryOperatorExpression ( new BinaryOperatorExpression (
PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ()), PatternHelper.CommutativeOperator (new AnyNode ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ()),
BinaryOperatorType.ConditionalOr, BinaryOperatorType.ConditionalOr,
PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.Equality, new PrimitiveExpression ("")) new Choice {
PatternHelper.CommutativeOperator (new Backreference ("str"), BinaryOperatorType.Equality, new PrimitiveExpression ("")),
PatternHelper.CommutativeOperator (
new MemberReferenceExpression (new Backreference ("str"), "Length"),
BinaryOperatorType.Equality,
new PrimitiveExpression (0)
)
}
), ),
// str == "" || str == null // str == "" || str == null
// str.Length == 0 || str == null
new BinaryOperatorExpression ( new BinaryOperatorExpression (
PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.Equality, new PrimitiveExpression ("")), new Choice {
PatternHelper.CommutativeOperator (new AnyNode ("str"), BinaryOperatorType.Equality, new PrimitiveExpression ("")),
PatternHelper.CommutativeOperator (
new MemberReferenceExpression (new AnyNode ("str"), "Length"),
BinaryOperatorType.Equality,
new PrimitiveExpression (0)
)
},
BinaryOperatorType.ConditionalOr, BinaryOperatorType.ConditionalOr,
PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ()) PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ())
), )
}; };
static readonly Pattern negPattern = new Choice { static readonly Pattern negPattern = new Choice {
// str != null && str != "" // str != null && str != ""
// str != null && str.Length != 0
new BinaryOperatorExpression ( new BinaryOperatorExpression (
PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.InEquality, new NullReferenceExpression ()), PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.InEquality, new NullReferenceExpression ()),
BinaryOperatorType.ConditionalAnd, BinaryOperatorType.ConditionalAnd,
PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.InEquality, new PrimitiveExpression ("")) new Choice {
PatternHelper.CommutativeOperator (new Backreference ("str"), BinaryOperatorType.InEquality, new PrimitiveExpression ("")),
PatternHelper.CommutativeOperator (
new MemberReferenceExpression (new Backreference ("str"), "Length"),
BinaryOperatorType.InEquality,
new PrimitiveExpression (0)
)
}
), ),
// str != "" && str != null // str != "" && str != null
// str.Length != 0 && str != null
new BinaryOperatorExpression ( new BinaryOperatorExpression (
PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.InEquality, new PrimitiveExpression ("")), new Choice {
PatternHelper.CommutativeOperator (new AnyNode ("str"), BinaryOperatorType.InEquality, new PrimitiveExpression ("")),
PatternHelper.CommutativeOperator (
new MemberReferenceExpression (new AnyNode ("str"), "Length"),
BinaryOperatorType.InEquality,
new PrimitiveExpression (0)
)
},
BinaryOperatorType.ConditionalAnd, BinaryOperatorType.ConditionalAnd,
PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.InEquality, new NullReferenceExpression ()) PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.InEquality, new NullReferenceExpression ())
), )
}; };
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context) public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{ {
return new GatherVisitor(context, this).GetIssues(); return new GatherVisitor(context).GetIssues();
} }
class GatherVisitor : GatherVisitorBase class GatherVisitor : GatherVisitorBase
{ {
readonly StringIsNullOrEmptyIssue inspector; public GatherVisitor (BaseRefactoringContext ctx) : base (ctx)
public GatherVisitor (BaseRefactoringContext ctx, StringIsNullOrEmptyIssue inspector) : base (ctx)
{ {
this.inspector = inspector;
} }
public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) public override void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)

36
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableDeclaredInWideScopeIssue.cs

@ -88,14 +88,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var path = GetPath(rootNode, deepestCommonAncestor); var path = GetPath(rootNode, deepestCommonAncestor);
// The node that will follow the moved declaration statement // The node that will follow the moved declaration statement
AstNode anchorNode = GetInitialAnchorNode (rootNode, identifiers, path); AstNode anchorNode = GetInitialAnchorNode(rootNode, identifiers, path);
// Restrict path to only those where the initializer has not changed // Restrict path to only those where the initializer has not changed
var pathToCheck = path.Skip(1).ToList(); var pathToCheck = path.Skip(1).ToList();
var firstInitializerChangeNode = GetFirstInitializerChange(variableDeclarationStatement, pathToCheck, variableInitializer.Initializer); var firstInitializerChangeNode = GetFirstInitializerChange(variableDeclarationStatement, pathToCheck, variableInitializer.Initializer);
if (firstInitializerChangeNode != null) { if (firstInitializerChangeNode != null) {
// The initializer and usage nodes may not be in the same path, so merge them // The node changing the initializer expression may not be on the path
// instead of just making a path to firstInitializerChange // to the actual usages of the variable, so we need to merge the paths
// so we get the part of the paths that are common between them
var pathToChange = GetPath(rootNode, firstInitializerChangeNode); var pathToChange = GetPath(rootNode, firstInitializerChangeNode);
var deepestCommonIndex = GetLowestCommonAncestorIndex(path, pathToChange); var deepestCommonIndex = GetLowestCommonAncestorIndex(path, pathToChange);
anchorNode = pathToChange [deepestCommonIndex + 1]; anchorNode = pathToChange [deepestCommonIndex + 1];
@ -109,9 +110,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
anchorNode = firstBlackListedNode; anchorNode = firstBlackListedNode;
} }
// Get the parent statement anchorNode = GetInsertionPoint(anchorNode);
while (anchorNode != null && !(anchorNode is Statement))
anchorNode = anchorNode.Parent;
if (anchorNode != null && anchorNode != rootNode && anchorNode.Parent != rootNode) { if (anchorNode != null && anchorNode != rootNode && anchorNode.Parent != rootNode) {
AddIssue(variableDeclarationStatement, context.TranslateString("Variable could be moved to a nested scope"), AddIssue(variableDeclarationStatement, context.TranslateString("Variable could be moved to a nested scope"),
@ -119,6 +118,31 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
} }
} }
static bool IsBannedInsertionPoint(AstNode anchorNode)
{
var parent = anchorNode.Parent;
// Don't split 'else if ...' into else { if ... }
if (parent is IfElseStatement && anchorNode is IfElseStatement)
return true;
// Don't allow moving the declaration into the resource aquisition of a using statement
if (parent is UsingStatement)
return true;
return false;
}
static AstNode GetInsertionPoint(AstNode node)
{
while (true) {
if (node == null)
break;
if (node is Statement && !IsBannedInsertionPoint(node))
break;
node = node.Parent;
}
return node;
}
AstNode GetInitialAnchorNode (BlockStatement rootNode, List<IdentifierExpression> identifiers, IList<AstNode> path) AstNode GetInitialAnchorNode (BlockStatement rootNode, List<IdentifierExpression> identifiers, IList<AstNode> path)
{ {
if (identifiers.Count > 1) { if (identifiers.Count > 1) {

20
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/VariableNotUsedIssues/ParameterNotUsedIssue.cs

@ -25,6 +25,8 @@
// THE SOFTWARE. // THE SOFTWARE.
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
@ -51,6 +53,24 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
this.unit = unit; this.unit = unit;
} }
public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
{
// Only some methods are candidates for the warning
if (methodDeclaration.Body.IsNull)
return;
var methodResolveResult = ctx.Resolve(methodDeclaration) as MemberResolveResult;
if (methodResolveResult == null)
return;
var member = methodResolveResult.Member;
if (member.IsOverride)
return;
if (member.ImplementedInterfaceMembers.Any ())
return;
base.VisitMethodDeclaration(methodDeclaration);
}
public override void VisitParameterDeclaration (ParameterDeclaration parameterDeclaration) public override void VisitParameterDeclaration (ParameterDeclaration parameterDeclaration)
{ {
base.VisitParameterDeclaration (parameterDeclaration); base.VisitParameterDeclaration (parameterDeclaration);

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs

@ -60,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public virtual AstType CreateShortType(string ns, string name, int typeParameterCount = 0) public virtual AstType CreateShortType(string ns, string name, int typeParameterCount = 0)
{ {
var builder = CreateTypeSytemAstBuilder(); var builder = CreateTypeSytemAstBuilder();
return builder.ConvertType(ns, name, typeParameterCount); return builder.ConvertType(new TopLevelTypeName(ns, name, typeParameterCount));
} }
public virtual IEnumerable<AstNode> GetSelectedNodes() public virtual IEnumerable<AstNode> GetSelectedNodes()

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

@ -152,6 +152,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
text += Options.EolMarker; text += Options.EolMarker;
InsertText(startOffset, text); InsertText(startOffset, text);
output.RegisterTrackedSegments(this, startOffset); output.RegisterTrackedSegments(this, startOffset);
CorrectFormatting (node, insertNode);
} }
public void InsertAfter(AstNode node, AstNode insertNode) public void InsertAfter(AstNode node, AstNode insertNode)
@ -164,6 +165,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var insertOffset = GetCurrentOffset(node.EndLocation); var insertOffset = GetCurrentOffset(node.EndLocation);
InsertText(insertOffset, text); InsertText(insertOffset, text);
output.RegisterTrackedSegments(this, insertOffset); output.RegisterTrackedSegments(this, insertOffset);
CorrectFormatting (node, insertNode);
} }
public void AddTo(BlockStatement bodyStatement, AstNode insertNode) public void AddTo(BlockStatement bodyStatement, AstNode insertNode)
@ -172,6 +174,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var output = OutputNode(1 + GetIndentLevelAt(startOffset), insertNode, true); var output = OutputNode(1 + GetIndentLevelAt(startOffset), insertNode, true);
InsertText(startOffset, output.Text); InsertText(startOffset, output.Text);
output.RegisterTrackedSegments(this, startOffset); output.RegisterTrackedSegments(this, startOffset);
CorrectFormatting (null, insertNode);
} }
public virtual Task Link (params AstNode[] nodes) public virtual Task Link (params AstNode[] nodes)
@ -196,6 +199,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
output.TrimStart (); output.TrimStart ();
Replace (startOffset, segment.Length, output.Text); Replace (startOffset, segment.Length, output.Text);
output.RegisterTrackedSegments(this, startOffset); output.RegisterTrackedSegments(this, startOffset);
CorrectFormatting (node, node);
}
void CorrectFormatting(AstNode node, AstNode newNode)
{
if (node is Identifier || node is IdentifierExpression || node is CSharpTokenNode || node is AstType)
return;
if (node == null || node.Parent is BlockStatement) {
FormatText(newNode);
} else {
FormatText((node.Parent != null && (node.Parent is Statement || node.Parent is Expression || node.Parent is VariableInitializer)) ? node.Parent : newNode);
}
} }
public abstract void Remove (AstNode node, bool removeEmptyLine = true); public abstract void Remove (AstNode node, bool removeEmptyLine = true);

18
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs

@ -142,17 +142,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return astType; return astType;
} }
public AstType ConvertType(string ns, string name, int typeParameterCount = 0) public AstType ConvertType(FullTypeName fullTypeName)
{ {
if (resolver != null) { if (resolver != null) {
foreach (var asm in resolver.Compilation.Assemblies) { foreach (var asm in resolver.Compilation.Assemblies) {
var def = asm.GetTypeDefinition(ns, name, typeParameterCount); var def = asm.GetTypeDefinition(fullTypeName);
if (def != null) { if (def != null) {
return ConvertType(def); return ConvertType(def);
} }
} }
} }
return new MemberType(new SimpleType(ns), name); TopLevelTypeName top = fullTypeName.TopLevelTypeName;
AstType type;
if (string.IsNullOrEmpty(top.Namespace)) {
type = new SimpleType(top.Name);
} else {
type = new SimpleType(top.Namespace).MemberType(top.Name);
}
for (int i = 0; i < fullTypeName.NestingLevel; i++) {
type = type.MemberType(fullTypeName.GetNestedTypeName(i));
}
return type;
} }
AstType ConvertTypeHelper(IType type) AstType ConvertTypeHelper(IType type)
@ -601,7 +611,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
if (GenerateBody) { if (GenerateBody) {
return new BlockStatement { return new BlockStatement {
new ThrowStatement(new ObjectCreateExpression(ConvertType("System", "NotImplementedException"))) new ThrowStatement(new ObjectCreateExpression(ConvertType(new TopLevelTypeName("System", "NotImplementedException", 0))))
}; };
} else { } else {
return BlockStatement.Null; return BlockStatement.Null;

85
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs

@ -17,7 +17,6 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
@ -141,6 +140,90 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
#endregion #endregion
#region GetAccessibleMembers
/// <summary>
/// Retrieves all members that are accessible and not hidden (by being overridden or shadowed).
/// Returns both members and nested type definitions. Does not include extension methods.
/// </summary>
public IEnumerable<IEntity> GetAccessibleMembers(ResolveResult targetResolveResult)
{
if (targetResolveResult == null)
throw new ArgumentNullException("targetResolveResult");
bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter;
bool allowProtectedAccess = (targetResolveResult is ThisResolveResult || IsProtectedAccessAllowed(targetResolveResult.Type));
// maps the member name to the list of lookup groups
var lookupGroupDict = new Dictionary<string, List<LookupGroup>>();
// This loop will handle base types before derived types.
// The loop performs three jobs:
// 1) It marks entries in lookup groups from base classes as removed when those members
// are hidden by a derived class.
// 2) It adds a new lookup group with the members from a declaring type.
// 3) It replaces virtual members with the overridden version, placing the override in the
// lookup group belonging to the base class.
foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes()) {
List<IEntity> entities = new List<IEntity>();
entities.AddRange(type.GetMembers(options: GetMemberOptions.IgnoreInheritedMembers));
if (!targetIsTypeParameter) {
var nestedTypes = type.GetNestedTypes(options: GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions);
// GetDefinition() might return null if some IType has a strange implementation of GetNestedTypes.
entities.AddRange(nestedTypes.Select(t => t.GetDefinition()).Where(td => td != null));
}
foreach (var entityGroup in entities.GroupBy(e => e.Name)) {
List<LookupGroup> lookupGroups = new List<LookupGroup>();
if (!lookupGroupDict.TryGetValue(entityGroup.Key, out lookupGroups))
lookupGroupDict.Add(entityGroup.Key, lookupGroups = new List<LookupGroup>());
List<IType> newNestedTypes = null;
List<IParameterizedMember> newMethods = null;
IMember newNonMethod = null;
IEnumerable<IType> typeBaseTypes = null;
if (!targetIsTypeParameter) {
AddNestedTypes(type, entityGroup.OfType<IType>(), 0, lookupGroups, ref typeBaseTypes, ref newNestedTypes);
}
AddMembers(type, entityGroup.OfType<IMember>(), allowProtectedAccess, lookupGroups, false, ref typeBaseTypes, ref newMethods, ref newNonMethod);
if (newNestedTypes != null || newMethods != null || newNonMethod != null)
lookupGroups.Add(new LookupGroup(type, newNestedTypes, newMethods, newNonMethod));
}
}
foreach (List<LookupGroup> lookupGroups in lookupGroupDict.Values) {
// Remove interface members hidden by class members.
if (targetIsTypeParameter) {
// This can happen only with type parameters.
RemoveInterfaceMembersHiddenByClassMembers(lookupGroups);
}
// Now report the results:
foreach (LookupGroup lookupGroup in lookupGroups) {
if (!lookupGroup.MethodsAreHidden) {
foreach (IMethod method in lookupGroup.Methods) {
yield return method;
}
}
if (!lookupGroup.NonMethodIsHidden) {
yield return lookupGroup.NonMethod;
}
if (lookupGroup.NestedTypes != null) {
foreach (IType type in lookupGroup.NestedTypes) {
ITypeDefinition typeDef = type.GetDefinition();
if (typeDef != null)
yield return typeDef;
}
}
}
}
}
#endregion
#region class LookupGroup #region class LookupGroup
sealed class LookupGroup sealed class LookupGroup
{ {

1
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs

@ -58,7 +58,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
node = node.Parent; node = node.Parent;
} else if (node.NodeType == NodeType.Token) { } else if (node.NodeType == NodeType.Token) {
if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer) { if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer) {
Console.WriteLine (2);
// There's no other place where one could hover to see the indexer's tooltip, // There's no other place where one could hover to see the indexer's tooltip,
// so we need to resolve it when hovering over the '[' or ']'. // so we need to resolve it when hovering over the '[' or ']'.
// For constructor initializer, the same applies to the 'base'/'this' token. // For constructor initializer, the same applies to the 'base'/'this' token.

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/AliasNamespaceReference.cs

@ -51,6 +51,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return resolver.ResolveAlias(identifier); return resolver.ResolveAlias(identifier);
} }
public override IType ResolveType(CSharpResolver resolver)
{
// alias cannot refer to types
return SpecialType.UnknownType;
}
public override string ToString() public override string ToString()
{ {
return identifier + "::"; return identifier + "::";

25
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs

@ -181,9 +181,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return fullAssemblyName.Substring(0, pos); return fullAssemblyName.Substring(0, pos);
} }
Dictionary<FullNameAndTypeParameterCount, ITypeDefinition> typeDict; Dictionary<TopLevelTypeName, ITypeDefinition> typeDict;
Dictionary<FullNameAndTypeParameterCount, ITypeDefinition> GetTypes() Dictionary<TopLevelTypeName, ITypeDefinition> GetTypes()
{ {
var dict = LazyInit.VolatileRead(ref this.typeDict); var dict = LazyInit.VolatileRead(ref this.typeDict);
if (dict != null) { if (dict != null) {
@ -192,9 +192,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
// Always use the ordinal comparer for the main dictionary so that partial classes // Always use the ordinal comparer for the main dictionary so that partial classes
// get merged correctly. // get merged correctly.
// The compilation's comparer will be used for the per-namespace dictionaries. // The compilation's comparer will be used for the per-namespace dictionaries.
var comparer = FullNameAndTypeParameterCountComparer.Ordinal; var comparer = TopLevelTypeNameComparer.Ordinal;
dict = projectContent.TopLevelTypeDefinitions dict = projectContent.TopLevelTypeDefinitions
.GroupBy(t => new FullNameAndTypeParameterCount(t.Namespace, t.Name, t.TypeParameters.Count), comparer) .GroupBy(t => new TopLevelTypeName(t.Namespace, t.Name, t.TypeParameters.Count), comparer)
.ToDictionary(g => g.Key, g => CreateResolvedTypeDefinition(g.ToArray()), comparer); .ToDictionary(g => g.Key, g => CreateResolvedTypeDefinition(g.ToArray()), comparer);
return LazyInit.GetOrSet(ref this.typeDict, dict); return LazyInit.GetOrSet(ref this.typeDict, dict);
} }
@ -205,11 +205,10 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return new DefaultResolvedTypeDefinition(context, parts); return new DefaultResolvedTypeDefinition(context, parts);
} }
public ITypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount) public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
{ {
var key = new FullNameAndTypeParameterCount(ns ?? string.Empty, name, typeParameterCount);
ITypeDefinition def; ITypeDefinition def;
if (GetTypes().TryGetValue(key, out def)) if (GetTypes().TryGetValue(topLevelTypeName, out def))
return def; return def;
else else
return null; return null;
@ -233,7 +232,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
readonly string fullName; readonly string fullName;
readonly string name; readonly string name;
internal readonly List<NS> childNamespaces = new List<NS>(); internal readonly List<NS> childNamespaces = new List<NS>();
internal readonly Dictionary<FullNameAndTypeParameterCount, ITypeDefinition> types; internal readonly Dictionary<TopLevelTypeName, ITypeDefinition> types;
public NS(CSharpAssembly assembly) public NS(CSharpAssembly assembly)
{ {
@ -243,7 +242,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
// Our main dictionary for the CSharpAssembly is using an ordinal comparer. // Our main dictionary for the CSharpAssembly is using an ordinal comparer.
// If the compilation's comparer isn't ordinal, we need to create a new dictionary with the compilation's comparer. // If the compilation's comparer isn't ordinal, we need to create a new dictionary with the compilation's comparer.
if (assembly.compilation.NameComparer != StringComparer.Ordinal) { if (assembly.compilation.NameComparer != StringComparer.Ordinal) {
this.types = new Dictionary<FullNameAndTypeParameterCount, ITypeDefinition>(new FullNameAndTypeParameterCountComparer(assembly.compilation.NameComparer)); this.types = new Dictionary<TopLevelTypeName, ITypeDefinition>(new TopLevelTypeNameComparer(assembly.compilation.NameComparer));
} }
} }
@ -254,7 +253,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
this.fullName = fullName; this.fullName = fullName;
this.name = name; this.name = name;
if (parentNamespace.types != null) if (parentNamespace.types != null)
this.types = new Dictionary<FullNameAndTypeParameterCount, ITypeDefinition>(parentNamespace.types.Comparer); this.types = new Dictionary<TopLevelTypeName, ITypeDefinition>(parentNamespace.types.Comparer);
} }
string INamespace.ExternAlias { string INamespace.ExternAlias {
@ -290,7 +289,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
} }
} }
ICompilation IResolved.Compilation { ICompilation ICompilationProvider.Compilation {
get { return assembly.Compilation; } get { return assembly.Compilation; }
} }
@ -310,15 +309,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount) ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount)
{ {
var key = new TopLevelTypeName(fullName, name, typeParameterCount);
if (types != null) { if (types != null) {
var key = new FullNameAndTypeParameterCount(fullName, name, typeParameterCount);
ITypeDefinition typeDef; ITypeDefinition typeDef;
if (types.TryGetValue(key, out typeDef)) if (types.TryGetValue(key, out typeDef))
return typeDef; return typeDef;
else else
return null; return null;
} else { } else {
return assembly.GetTypeDefinition(fullName, name, typeParameterCount); return assembly.GetTypeDefinition(key);
} }
} }
} }

15
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/MemberTypeOrNamespaceReference.cs

@ -22,6 +22,7 @@ using System.Collections.ObjectModel;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils; using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.TypeSystem namespace ICSharpCode.NRefactory.CSharp.TypeSystem
@ -58,7 +59,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
} }
public IList<ITypeReference> TypeArguments { public IList<ITypeReference> TypeArguments {
get { return new ReadOnlyCollection<ITypeReference>(typeArguments); } get { return typeArguments; }
}
public NameLookupMode LookupMode {
get { return lookupMode; }
} }
/// <summary> /// <summary>
@ -67,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
/// </summary> /// </summary>
public MemberTypeOrNamespaceReference AddSuffix(string suffix) public MemberTypeOrNamespaceReference AddSuffix(string suffix)
{ {
return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments); return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments, lookupMode);
} }
public override ResolveResult Resolve(CSharpResolver resolver) public override ResolveResult Resolve(CSharpResolver resolver)
@ -86,6 +91,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
} }
} }
public override IType ResolveType(CSharpResolver resolver)
{
TypeResolveResult trr = Resolve(resolver) as TypeResolveResult;
return trr != null ? trr.Type : new UnknownType(null, identifier, typeArguments.Count);
}
public override string ToString() public override string ToString()
{ {
if (typeArguments.Count == 0) if (typeArguments.Count == 0)

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/ResolvedUsingScope.cs

@ -176,7 +176,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
get { return EmptyList<IAssembly>.Instance; } get { return EmptyList<IAssembly>.Instance; }
} }
ICompilation IResolved.Compilation { ICompilation ICompilationProvider.Compilation {
get { return parentNamespace.Compilation; } get { return parentNamespace.Compilation; }
} }

13
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/SimpleTypeOrNamespaceReference.cs

@ -23,6 +23,7 @@ using System.Collections.ObjectModel;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils; using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.TypeSystem namespace ICSharpCode.NRefactory.CSharp.TypeSystem
@ -51,7 +52,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
} }
public IList<ITypeReference> TypeArguments { public IList<ITypeReference> TypeArguments {
get { return new ReadOnlyCollection<ITypeReference>(typeArguments); } get { return typeArguments; }
}
public NameLookupMode LookupMode {
get { return lookupMode; }
} }
/// <summary> /// <summary>
@ -69,6 +74,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return resolver.LookupSimpleNameOrTypeName(identifier, typeArgs, lookupMode); return resolver.LookupSimpleNameOrTypeName(identifier, typeArgs, lookupMode);
} }
public override IType ResolveType(CSharpResolver resolver)
{
TypeResolveResult trr = Resolve(resolver) as TypeResolveResult;
return trr != null ? trr.Type : new UnknownType(null, identifier, typeArguments.Count);
}
public override string ToString() public override string ToString()
{ {
if (typeArguments.Count == 0) if (typeArguments.Count == 0)

14
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs

@ -34,6 +34,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
/// </summary> /// </summary>
public abstract ResolveResult Resolve(CSharpResolver resolver); public abstract ResolveResult Resolve(CSharpResolver resolver);
/// <summary>
/// Returns the type that is referenced; or an <c>UnknownType</c> if the type isn't found.
/// </summary>
public abstract IType ResolveType(CSharpResolver resolver);
/// <summary> /// <summary>
/// Returns the namespace that is referenced; or null if no such namespace is found. /// Returns the namespace that is referenced; or null if no such namespace is found.
/// </summary> /// </summary>
@ -43,15 +48,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return nrr != null ? nrr.Namespace : null; return nrr != null ? nrr.Namespace : null;
} }
/// <summary>
/// Returns the type that is referenced; or <see cref="SpecialType.UnknownType"/> if the type isn't found.
/// </summary>
public IType ResolveType(CSharpResolver resolver)
{
TypeResolveResult trr = Resolve(resolver) as TypeResolveResult;
return trr != null ? trr.Type : SpecialType.UnknownType;
}
IType ITypeReference.Resolve(ITypeResolveContext context) IType ITypeReference.Resolve(ITypeResolveContext context)
{ {
// Strictly speaking, we might have to resolve the type in a nested compilation, similar // Strictly speaking, we might have to resolve the type in a nested compilation, similar

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/AddCatchTypeTests.cs

@ -50,8 +50,7 @@ class TestClass
public void F() public void F()
{ {
try { try {
} } catch (System.Exception e) {
catch (System.Exception e) {
} }
} }
}"); }");
@ -107,8 +106,7 @@ class TestClass
public void F() public void F()
{ {
try { try {
} } catch (Exception e) {
catch (Exception e) {
} }
} }
}"); }");

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertAnonymousDelegateToLambdaTests.cs

@ -47,9 +47,9 @@ class A
{ {
void F () void F ()
{ {
System.Action<int, int> action = (i1, i2) => { System.Action<int, int> action = (i1, i2) => {
System.Console.WriteLine (i1); System.Console.WriteLine (i1);
}; };
} }
}"); }");
} }
@ -69,9 +69,9 @@ class A
{ {
void F () void F ()
{ {
var action = (int i1, int i2) => { var action = (int i1, int i2) => {
System.Console.WriteLine (i1); System.Console.WriteLine (i1);
}; };
} }
}"); }");
} }

8
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertConditionalToIfTests.cs

@ -239,10 +239,10 @@ class TestClass
{ {
int a; int a;
if (i < 10) if (i < 10)
if (i > 0) if (i > 0)
a = 0; a = 0;
else else
a = 1; a = 1;
} }
}"); }");
} }

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertLamdaToAnonymousDelegateTests.cs

@ -47,8 +47,8 @@ class A
void F () void F ()
{ {
System.Action<int, int> = delegate (int i1, int i2) { System.Action<int, int> = delegate (int i1, int i2) {
System.Console.WriteLine (i1); System.Console.WriteLine (i1);
}; };
} }
}"); }");
} }
@ -69,8 +69,8 @@ class A
void F () void F ()
{ {
System.Action<int, int> = delegate (int i1, int i2) { System.Action<int, int> = delegate (int i1, int i2) {
System.Console.WriteLine (i1); System.Console.WriteLine (i1);
}; };
} }
}"); }");
} }
@ -91,8 +91,8 @@ class A
void F () void F ()
{ {
System.Action = delegate { System.Action = delegate {
System.Console.WriteLine (); System.Console.WriteLine ();
}; };
} }
}"); }");
} }

21
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ConvertSwitchToIfTests.cs

@ -61,11 +61,9 @@ class TestClass
{ {
if (a == 0) { if (a == 0) {
return 0; return 0;
} else } else if (a == 1 || a == 2) {
if (a == 1 || a == 2) {
return 1; return 1;
} else } else if (a == 3 || a == 4 || a == 5) {
if (a == 3 || a == 4 || a == 5) {
return 1; return 1;
} else { } else {
return 2; return 2;
@ -101,11 +99,9 @@ class TestClass
{ {
if (a == 0) { if (a == 0) {
return 0; return 0;
} else } else if (a == 1 || a == 2) {
if (a == 1 || a == 2) {
return 1; return 1;
} else } else if (a == 3 || a == 4 || a == 5) {
if (a == 3 || a == 4 || a == 5) {
return 1; return 1;
} }
} }
@ -142,10 +138,8 @@ class TestClass
{ {
if (a == 0) { if (a == 0) {
int b = 1; int b = 1;
} else } else if (a == 1 || a == 2) {
if (a == 1 || a == 2) { } else if (a == 3 || a == 4 || a == 5) {
} else
if (a == 3 || a == 4 || a == 5) {
} else { } else {
} }
} }
@ -176,8 +170,7 @@ class TestClass
{ {
if (a == 0) { if (a == 0) {
return 0; return 0;
} else } else if (a == (1 == 1 ? 1 : 2)) {
if (a == (1 == 1 ? 1 : 2)) {
return 1; return 1;
} else { } else {
return 2; return 2;

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/DeclareLocalVariableTests.cs

@ -1,4 +1,4 @@
// //
// DeclareLocalVariableTests.cs // DeclareLocalVariableTests.cs
// //
// Author: // Author:

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/ExtensionMethodInvocationToStaticMethodInvocationTests.cs

@ -82,7 +82,7 @@ class C
void F() void F()
{ {
A a = new A(); A a = new A();
if(a.$Ext (1)) if (a.$Ext (1))
return; return;
} }
}", @" }", @"
@ -99,7 +99,7 @@ class C
void F() void F()
{ {
A a = new A(); A a = new A();
if(B.Ext (a, 1)) if (B.Ext (a, 1))
return; return;
} }
}"); }");

68
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/MoveToOuterScopeTests.cs

@ -54,13 +54,13 @@ class A
public void SimpleCase() public void SimpleCase()
{ {
TestStatements(@" TestStatements(@"
while (true) { while (true) {
int $i = 2; int $i = 2;
} }
", @" ", @"
int i = 2; int i = 2;
while (true) { while (true) {
} }
"); ");
} }
@ -81,14 +81,14 @@ class A
public void MovesOnlyTheCurrentVariableInitialization() public void MovesOnlyTheCurrentVariableInitialization()
{ {
TestStatements(@" TestStatements(@"
while (true) { while (true) {
int $i = 2, j = 3; int $i = 2, j = 3;
} }
", @" ", @"
int i = 2; int i = 2;
while (true) { while (true) {
int j = 3; int j = 3;
} }
"); ");
} }
@ -96,13 +96,13 @@ while (true) {
public void MovesAllInitializersWhenOnType() public void MovesAllInitializersWhenOnType()
{ {
TestStatements(@" TestStatements(@"
while (true) { while (true) {
i$nt i = 2, j = 3; i$nt i = 2, j = 3;
} }
", @" ", @"
int i = 2, j = 3; int i = 2, j = 3;
while (true) { while (true) {
} }
"); ");
} }
@ -110,16 +110,16 @@ while (true) {
public void OnlyMovesDeclarationWhenInitializerDependsOnOtherStatements() public void OnlyMovesDeclarationWhenInitializerDependsOnOtherStatements()
{ {
TestStatements(@" TestStatements(@"
while (true) { while (true) {
int i = 2; int i = 2;
int j$ = i; int j$ = i;
} }
", @" ", @"
int j; int j;
while (true) { while (true) {
int i = 2; int i = 2;
j = i; j = i;
} }
"); ");
} }
@ -127,13 +127,13 @@ while (true) {
public void HandlesLambdaDelegate() public void HandlesLambdaDelegate()
{ {
TestStatements(@" TestStatements(@"
var action = new Action<int>(i => { var action = new Action<int>(i => {
int j$ = 2; int j$ = 2;
}); });
", @" ", @"
int j = 2; int j = 2;
var action = new Action<int>(i => { var action = new Action<int>(i => {
}); });
"); ");
} }
} }

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/RemoveRedundantCatchTypeTests.cs

@ -52,8 +52,7 @@ class TestClass
public void F() public void F()
{ {
try { try {
} } catch {
catch {
} }
} }
}"); }");
@ -79,8 +78,7 @@ class TestClass
public void F() public void F()
{ {
try { try {
} } catch {
catch {
System.Console.WriteLine (""Hi""); System.Console.WriteLine (""Hi"");
} }
} }

3
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/SplitDeclarationAndAssignmentTests.cs

@ -100,7 +100,8 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
" void Test ()" + Environment.NewLine + " void Test ()" + Environment.NewLine +
" {" + Environment.NewLine + " {" + Environment.NewLine +
" int i;" + Environment.NewLine + " int i;" + Environment.NewLine +
" for (i = 1; i < 10; i++) {}" + Environment.NewLine + " for (i = 1; i < 10; i++) {" + Environment.NewLine +
" }" + Environment.NewLine +
" }" + Environment.NewLine + " }" + Environment.NewLine +
"}", result); "}", result);
} }

76
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionAccessibleTests.cs

@ -29,6 +29,7 @@
using System; using System;
using NUnit.Framework; using NUnit.Framework;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.CodeCompletion namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
{ {
@ -1345,5 +1346,80 @@ public class Foo
Assert.IsNotNull (provider.Find ("Bar"), "'Bar' not found."); Assert.IsNotNull (provider.Find ("Bar"), "'Bar' not found.");
}); });
} }
[Test()]
public void TestImplicitShadowing ()
{
CodeCompletionBugTests.CombinedProviderTest (@"
using System;
namespace ConsoleApplication2
{
class A
{
public int Foo;
}
class B : A
{
public string Foo;
}
class Program
{
static void Main (string[] args)
{
var b = new B ();
$b.$
}
}
}", provider => {
int count = 0;
foreach (var data in provider.Data)
if (data.DisplayText == "Foo")
count += data.HasOverloads ? data.OverloadedData.Count () : 1;
Assert.AreEqual (1, count);
});
}
[Test()]
public void TestOverrideFiltering ()
{
CodeCompletionBugTests.CombinedProviderTest (@"
using System;
namespace ConsoleApplication2
{
class A
{
public virtual int Foo { set {} }
}
class B : A
{
public override int Foo {
set {
base.Foo = value;
}
}
}
class Program
{
static void Main (string[] args)
{
var b = new B ();
$b.$
}
}
}
", provider => {
int count = 0;
foreach (var data in provider.Data)
if (data.DisplayText == "Foo")
count += data.HasOverloads ? data.OverloadedData.Count () : 1;
Assert.AreEqual (1, count);
});
}
} }
} }

69
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs

@ -74,6 +74,9 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
#region ICompletionData implementation #region ICompletionData implementation
public void AddOverload (ICompletionData data) public void AddOverload (ICompletionData data)
{ {
if (overloadedData.Count == 0)
overloadedData.Add (this);
overloadedData.Add (data);
} }
public CompletionCategory CompletionCategory { public CompletionCategory CompletionCategory {
@ -103,13 +106,17 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
public bool HasOverloads { public bool HasOverloads {
get { get {
throw new NotImplementedException (); return overloadedData.Count > 0;
} }
} }
List<ICompletionData> overloadedData = new List<ICompletionData> ();
public System.Collections.Generic.IEnumerable<ICompletionData> OverloadedData { public System.Collections.Generic.IEnumerable<ICompletionData> OverloadedData {
get; get {
set; return overloadedData;
}
set {
throw new NotImplementedException ();
}
} }
#endregion #endregion
@ -5415,5 +5422,59 @@ public class FooBar
}); });
} }
/// <summary>
/// Bug 7041 - No completion inside new[]
/// </summary>
[Test()]
public void TestBug7041()
{
CombinedProviderTest(
@"using System;
namespace ConsoleApplication2
{
class Test
{
public string[] Foo { get; set; }
}
class Program
{
static void Main(string[] args)
{
var a = new Test ()
{
$Foo = new [] { S$
}
}
}
}
", provider => {
Assert.IsNotNull(provider.Find("System"));
});
}
[Test()]
public void TestGlobalPrimitiveTypes()
{
CombinedProviderTest(
@"$u$", provider => {
Assert.IsNotNull(provider.Find("using"));
Assert.IsNull(provider.Find("ushort"));
});
}
[Test()]
public void TestGlobalPrimitiveTypesCase2()
{
CombinedProviderTest(
@"$delegate u$", provider => {
Assert.IsNotNull(provider.Find("ushort"));
Assert.IsNotNull(provider.Find("System"));
Assert.IsNull(provider.Find("using"));
});
}
} }
} }

14
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/NameContextTests.cs

@ -187,6 +187,20 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
Assert.AreEqual (0, provider.Count, "provider needs to be empty"); Assert.AreEqual (0, provider.Count, "provider needs to be empty");
}); });
} }
[Ignore("TODO")]
[Test()]
public void TestIndexerParameterName ()
{
var provider = CodeCompletionBugTests.CreateProvider (@"class MyClass {
$public int this [int f$
}");
Assert.IsTrue (provider == null || provider.Count == 0, "provider should be empty.");
provider = CodeCompletionBugTests.CreateProvider (@"class MyClass {
$public int this [int f, string x$
}");
Assert.IsTrue (provider == null || provider.Count == 0, "provider should be empty.");
}
} }
} }

8
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs

@ -220,6 +220,14 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
}; };
} }
public IParameterDataProvider CreateConstructorProvider(int startOffset, ICSharpCode.NRefactory.TypeSystem.IType type, AstNode skipNode)
{
Assert.IsTrue(type.Kind != TypeKind.Unknown);
return new Provider () {
Data = type.GetConstructors (m => m.Accessibility == Accessibility.Public)
};
}
public IParameterDataProvider CreateMethodDataProvider (int startOffset, IEnumerable<IMethod> methods) public IParameterDataProvider CreateMethodDataProvider (int startOffset, IEnumerable<IMethod> methods)
{ {
return new Provider () { return new Provider () {

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/TestBase.cs

@ -1,4 +1,4 @@
// //
// TestBase.cs // TestBase.cs
// //
// Author: // Author:
@ -38,7 +38,7 @@ using System.Diagnostics;
namespace ICSharpCode.NRefactory.CSharp.CodeCompletion namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
{ {
[TestFixture] [TestFixture]
public class TestBase public abstract class TestBase
{ {
class TestListener : TraceListener class TestListener : TraceListener
{ {

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/AccessToModifiedClosureTests.cs

@ -403,7 +403,7 @@ class TestClass
foreach (var i in a) { foreach (var i in a) {
var f = new System.Func<int, int> (x => { var f = new System.Func<int, int> (x => {
var f2 = new System.Func<int, int> (y => y - i); var f2 = new System.Func<int, int> (y => y - i);
return f2(x) + i; return f2 (x) + i;
}); });
} }
} }
@ -417,7 +417,7 @@ class TestClass
var i1 = i; var i1 = i;
var f = new System.Func<int, int> (x => { var f = new System.Func<int, int> (x => {
var f2 = new System.Func<int, int> (y => y - i1); var f2 = new System.Func<int, int> (y => y - i1);
return f2(x) + i1; return f2 (x) + i1;
}); });
} }
} }
@ -432,7 +432,7 @@ class TestClass
var f = new System.Func<int, int> (x => { var f = new System.Func<int, int> (x => {
var i1 = i; var i1 = i;
var f2 = new System.Func<int, int> (y => y - i1); var f2 = new System.Func<int, int> (y => y - i1);
return f2(x) + i; return f2 (x) + i;
}); });
} }
} }
@ -579,7 +579,7 @@ class TestClass
{ {
void TestMethod2 (int b, System.Func<int, int> a) void TestMethod2 (int b, System.Func<int, int> a)
{ {
TestMethod2 (b++, c => c + b); TestMethod2 (b++, c => c + b);
} }
}"; }";
var input2 = @" var input2 = @"
@ -587,7 +587,7 @@ class TestClass
{ {
void TestMethod3 (System.Func<int, int> a, int b) void TestMethod3 (System.Func<int, int> a, int b)
{ {
TestMethod3 (c => c + b, b++); TestMethod3 (c => c + b, b++);
} }
}"; }";
var output2 = @" var output2 = @"
@ -596,7 +596,7 @@ class TestClass
void TestMethod3 (System.Func<int, int> a, int b) void TestMethod3 (System.Func<int, int> a, int b)
{ {
var b1 = b; var b1 = b;
TestMethod3 (c => c + b1, b++); TestMethod3 (c => c + b1, b++);
} }
}"; }";
Test (input1, 0); Test (input1, 0);

65
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/AssignmentMadeToSameVariableIssueTests.cs

@ -127,7 +127,7 @@ class TestClass
}"; }";
Test<AssignmentMadeToSameVariableIssue> (input, 2, output); Test<AssignmentMadeToSameVariableIssue> (input, 2, output);
} }
[Test] [Test]
public void TestNoIssue () public void TestNoIssue ()
{ {
@ -146,6 +146,69 @@ class TestClass
this.a = a; this.a = a;
Prop = Prop; Prop = Prop;
} }
}";
Test<AssignmentMadeToSameVariableIssue> (input, 0);
}
[Test]
public void IgnoresAssignmentWithDifferentRootObjects ()
{
var input = @"
class TestClass
{
int a;
void TestMethod (TestClass tc)
{
a = tc.a;
}
}";
Test<AssignmentMadeToSameVariableIssue> (input, 0);
}
[Test]
public void NestedFieldAccess ()
{
var input = @"
class TestClass
{
int a;
TestClass nested;
void TestMethod ()
{
nested.nested.a = nested.nested.a;
}
}";
var output = @"
class TestClass
{
int a;
TestClass nested;
void TestMethod ()
{
}
}";
Test<AssignmentMadeToSameVariableIssue> (input, 1, output);
}
[Test]
public void NestedPropertyAccess ()
{
var input = @"
class TestClass
{
int a;
TestClass nested { get; set; }
void TestMethod ()
{
nested.nested.a = nested.nested.a;
}
}"; }";
Test<AssignmentMadeToSameVariableIssue> (input, 0); Test<AssignmentMadeToSameVariableIssue> (input, 0);
} }

9
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ConstantConditionIssueTests.cs

@ -114,7 +114,8 @@ class TestClass
{ {
void TestMethod () void TestMethod ()
{ {
for (int i = 0; true; i++) ; for (int i = 0; true; i++)
;
} }
}"; }";
Test<ConstantConditionIssue> (input, 1, output); Test<ConstantConditionIssue> (input, 1, output);
@ -128,7 +129,8 @@ class TestClass
{ {
void TestMethod () void TestMethod ()
{ {
while (1 > 0) ; while (1 > 0)
;
} }
}"; }";
var output = @" var output = @"
@ -136,7 +138,8 @@ class TestClass
{ {
void TestMethod () void TestMethod ()
{ {
while (true) ; while (true)
;
} }
}"; }";
Test<ConstantConditionIssue> (input, 1, output); Test<ConstantConditionIssue> (input, 1, output);

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ExpressionIsAlwaysOfProvidedTypeIssueTests.cs

@ -39,7 +39,8 @@ class TestClass
{ {
void TestMethod (" + variableType + @" x) void TestMethod (" + variableType + @" x)
{ {
if (x is " + providedType + @") ; if (x is " + providedType + @")
;
} }
}"; }";
var output = @" var output = @"
@ -47,7 +48,8 @@ class TestClass
{ {
void TestMethod (" + variableType + @" x) void TestMethod (" + variableType + @" x)
{ {
if (x != null) ; if (x != null)
;
} }
}"; }";
Test<ExpressionIsAlwaysOfProvidedTypeIssue> (input, 1, output); Test<ExpressionIsAlwaysOfProvidedTypeIssue> (input, 1, output);
@ -73,7 +75,8 @@ class TestClass
{ {
void TestMethod<T> (T x) where T : TestClass void TestMethod<T> (T x) where T : TestClass
{ {
if (x is TestClass) ; if (x is TestClass)
;
} }
}"; }";
var output = @" var output = @"
@ -81,7 +84,8 @@ class TestClass
{ {
void TestMethod<T> (T x) where T : TestClass void TestMethod<T> (T x) where T : TestClass
{ {
if (x != null) ; if (x != null)
;
} }
}"; }";
Test<ExpressionIsAlwaysOfProvidedTypeIssue> (input, 1, output); Test<ExpressionIsAlwaysOfProvidedTypeIssue> (input, 1, output);

3
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/InspectionActionTestBase.cs

@ -59,6 +59,9 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
} }
bool pass = expectedOutput == ctx.Text; bool pass = expectedOutput == ctx.Text;
if (!pass) { if (!pass) {
Console.WriteLine ("expected:");
Console.WriteLine (expectedOutput);
Console.WriteLine ("got:");
Console.WriteLine (ctx.Text); Console.WriteLine (ctx.Text);
} }
Assert.AreEqual (expectedOutput, ctx.Text); Assert.AreEqual (expectedOutput, ctx.Text);

30
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ParameterNotUsedIssueTests.cs

@ -43,6 +43,36 @@ class TestClass {
}"; }";
Test<ParameterNotUsedIssue> (input, 1); Test<ParameterNotUsedIssue> (input, 1);
} }
[Test]
public void TestInterfaceImplementation ()
{
var input = @"
interface ITestClass {
void TestMethod (int i);
}
class TestClass : ITestClass {
public void TestMethod (int i)
{
}
}";
Test<ParameterNotUsedIssue> (input, 0);
}
[Test]
public void TestAbstractMethodImplementation ()
{
var input = @"
abstract class TestBase {
public abstract void TestMethod (int i);
}
class TestClass : TestBase {
public override void TestMethod (int i)
{
}
}";
Test<ParameterNotUsedIssue> (input, 0);
}
[Test] [Test]
public void TestUsedParameter () public void TestUsedParameter ()

29
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantToStringTests.cs

@ -76,6 +76,23 @@ class Foo
Assert.AreEqual (0, issues.Count); Assert.AreEqual (0, issues.Count);
} }
[Test]
public void IgnoresCallsToIFormattableToString ()
{
var input = @"
class Foo
{
void Bar (System.DateTime dt)
{
string s = dt.ToString("""", CultureInfo.InvariantCulture) + string.Empty;
}
}";
TestRefactoringContext context;
var issues = GetIssues (new RedundantToStringIssue (), input, out context);
Assert.AreEqual (0, issues.Count);
}
[Test] [Test]
public void StringTarget () public void StringTarget ()
{ {
@ -123,7 +140,7 @@ class Foo
{ {
void Bar (int i) void Bar (int i)
{ {
string s = string.Format(""{0}"", i); string s = string.Format (""{0}"", i);
} }
}"); }");
} }
@ -150,7 +167,7 @@ class Foo
void Bar (int i) void Bar (int i)
{ {
string format = ""{0}""; string format = ""{0}"";
string s = string.Format(format, i); string s = string.Format (format, i);
} }
}"); }");
} }
@ -179,7 +196,7 @@ class Foo
{ {
void Bar (int i) void Bar (int i)
{ {
string s = FakeFormat(""{0} {1}"", i.ToString(), i); string s = FakeFormat (""{0} {1}"", i.ToString (), i);
} }
void FakeFormat(string format, string arg0, object arg1) void FakeFormat(string format, string arg0, object arg1)
@ -212,7 +229,7 @@ class Foo
{ {
void Bar (int i) void Bar (int i)
{ {
string s = FakeFormat(""{0} {1}"", i, i); string s = FakeFormat (""{0} {1}"", i, i);
} }
void FakeFormat(string format, params object[] args) void FakeFormat(string format, params object[] args)
@ -244,8 +261,8 @@ class Foo
void Bar (int i) void Bar (int i)
{ {
var w = new System.IO.StringWriter(); var w = new System.IO.StringWriter();
w.Write(i); w.Write (i);
w.WriteLine(i); w.WriteLine (i);
} }
}"); }");
} }

24
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/RedundantTypeCastIssueTests.cs

@ -146,5 +146,29 @@ class TestClass
}"; }";
Test<RedundantTypeCastIssue> (input, 0); Test<RedundantTypeCastIssue> (input, 0);
} }
/// <summary>
/// Bug 7065 - "remove redundant type cast" false positive for explicit interface implementation
/// </summary>
[Test]
public void TestBug7065 ()
{
var input = @"
using System;
public class TestClass : IDisposable
{
void IDisposable.Dispose()
{
}
void Foo()
{
((IDisposable)this).Dispose();
}
}
";
Test<RedundantTypeCastIssue> (input, 0);
}
} }
} }

10
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/ReferenceToStaticMemberViaDerivedTypeTests.cs

@ -46,7 +46,7 @@ class C
{ {
void Main() void Main()
{ {
B.F(); B.F ();
} }
}"; }";
TestRefactoringContext context; TestRefactoringContext context;
@ -64,7 +64,7 @@ class C
{ {
void Main() void Main()
{ {
A.F(); A.F ();
} }
}" }"
); );
@ -181,7 +181,7 @@ class D
{ {
void Main() void Main()
{ {
A.B.F(); A.B.F ();
} }
}" }"
); );
@ -205,7 +205,7 @@ namespace Second
{ {
void Main() void Main()
{ {
B.F(); B.F ();
} }
} }
}"; }";
@ -229,7 +229,7 @@ namespace Second
{ {
void Main() void Main()
{ {
First.A.F(); First.A.F ();
} }
} }
}" }"

68
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/StringIsNullOrEmptyInspectorTests.cs

@ -410,7 +410,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
} }
}"); }");
} }
[Test] [Test]
public void TestInspectorCaseSN8 () public void TestInspectorCaseSN8 ()
{ {
@ -422,7 +422,39 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
; ;
} }
}"; }";
TestRefactoringContext context;
var issues = GetIssues (new StringIsNullOrEmptyIssue (), input, out context);
Assert.AreEqual (1, issues.Count);
CheckFix (context, issues, @"class Foo
{
void Bar (string str)
{
if (string.IsNullOrEmpty (str))
;
}
}");
}
[TestCase("str == null || str.Length == 0")]
[TestCase("str == null || 0 == str.Length")]
[TestCase("str.Length == 0 || str == null")]
[TestCase("0 == str.Length || str == null")]
[TestCase("null == str || str.Length == 0")]
[TestCase("null == str || 0 == str.Length")]
[TestCase("str.Length == 0 || null == str")]
[TestCase("0 == str.Length || null == str")]
public void TestInspectorCaseNL (string expression)
{
var input = @"class Foo
{
void Bar (string str)
{
if (" + expression + @")
;
}
}";
TestRefactoringContext context; TestRefactoringContext context;
var issues = GetIssues (new StringIsNullOrEmptyIssue (), input, out context); var issues = GetIssues (new StringIsNullOrEmptyIssue (), input, out context);
Assert.AreEqual (1, issues.Count); Assert.AreEqual (1, issues.Count);
@ -433,6 +465,38 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
if (string.IsNullOrEmpty (str)) if (string.IsNullOrEmpty (str))
; ;
} }
}");
}
[TestCase("str != null && str.Length != 0")]
[TestCase("str != null && 0 != str.Length")]
[TestCase("str.Length != 0 && str != null")]
[TestCase("0 != str.Length && str != null")]
[TestCase("null != str && str.Length != 0")]
[TestCase("null != str && 0 != str.Length")]
[TestCase("str.Length != 0 && null != str")]
[TestCase("0 != str.Length && null != str")]
public void TestInspectorCaseLN (string expression)
{
var input = @"class Foo
{
void Bar (string str)
{
if (" + expression + @")
;
}
}";
TestRefactoringContext context;
var issues = GetIssues (new StringIsNullOrEmptyIssue (), input, out context);
Assert.AreEqual (1, issues.Count);
CheckFix (context, issues, @"class Foo
{
void Bar (string str)
{
if (!string.IsNullOrEmpty (str))
;
}
}"); }");
} }
} }

21
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/VariableDeclaredInWideScopeTests.cs

@ -379,6 +379,27 @@ class A
} }
"); ");
} }
[Test]
public void DoesNotExpandElseClause ()
{
TestStatements(@"
string o = ""Hello World !"";
if (false) {
} else if (!o.Contains (""Foo"")) {
}
", 0);
}
[Test]
public void DoesNotInsertBlockStatementInResourceAquisition ()
{
TestStatements(@"
string o = ""Hello World !"";
using (var file = File.Open(o, FileMode.Open))
return;
", 0);
}
} }
} }

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs

@ -217,7 +217,7 @@ namespace OtherNS {
public void AmbiguousType() public void AmbiguousType()
{ {
Assert.AreEqual("System.Array", TypeToString(compilation.FindType(typeof(Array)))); Assert.AreEqual("System.Array", TypeToString(compilation.FindType(typeof(Array))));
Assert.AreEqual("OtherNS.Array", TypeToString(compilation.MainAssembly.GetTypeDefinition("OtherNS", "Array", 0))); Assert.AreEqual("OtherNS.Array", TypeToString(compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName("OtherNS", "Array"))));
} }
} }
} }

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs

@ -397,6 +397,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public void ImplicitLongConstantExpressionConversion() public void ImplicitLongConstantExpressionConversion()
{ {
Assert.IsFalse(IntegerLiteralConversion(0L, typeof(int))); Assert.IsFalse(IntegerLiteralConversion(0L, typeof(int)));
Assert.IsFalse(IntegerLiteralConversion(0L, typeof(short)));
Assert.IsTrue(IntegerLiteralConversion(0L, typeof(long))); Assert.IsTrue(IntegerLiteralConversion(0L, typeof(long)));
Assert.IsTrue(IntegerLiteralConversion(0L, typeof(ulong))); Assert.IsTrue(IntegerLiteralConversion(0L, typeof(ulong)));
@ -508,8 +509,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
) } ) })); ) } ) }));
ICompilation compilation = TypeSystemHelper.CreateCompilation(a, b); ICompilation compilation = TypeSystemHelper.CreateCompilation(a, b);
ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a); ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a.FullTypeName);
ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b); ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b.FullTypeName);
IType type1 = new ParameterizedType(resolvedB, new [] { compilation.FindType(KnownTypeCode.Double) }); IType type1 = new ParameterizedType(resolvedB, new [] { compilation.FindType(KnownTypeCode.Double) });
IType type2 = new ParameterizedType(resolvedA, new [] { new ParameterizedType(resolvedB, new[] { compilation.FindType(KnownTypeCode.String) }) }); IType type2 = new ParameterizedType(resolvedA, new [] { new ParameterizedType(resolvedB, new[] { compilation.FindType(KnownTypeCode.String) }) });

39
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs

@ -44,6 +44,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
CSharpUnresolvedFile unresolvedFile = syntaxTree.ToTypeSystem(); CSharpUnresolvedFile unresolvedFile = syntaxTree.ToTypeSystem();
project = project.AddOrUpdateFiles(unresolvedFile); project = project.AddOrUpdateFiles(unresolvedFile);
compilation = project.CreateCompilation(); compilation = project.CreateCompilation();
lookup = new MemberLookup(null, compilation.MainAssembly);
return unresolvedFile; return unresolvedFile;
} }
@ -61,7 +62,7 @@ class Derived : Middle {
public override void Method() {} public override void Method() {}
}"; }";
var unresolvedFile = Parse(program); var unresolvedFile = Parse(program);
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(unresolvedFile.TopLevelTypeDefinitions[2]); ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName("Derived"));
var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult; var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count()); Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count());
@ -88,7 +89,7 @@ class Derived : Base<int> {
public override void Method(string a) {} public override void Method(string a) {}
}"; }";
var unresolvedFile = Parse(program); var unresolvedFile = Parse(program);
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(unresolvedFile.TopLevelTypeDefinitions[1]); ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName("Derived"));
var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult; var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count()); Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count());
@ -116,7 +117,7 @@ class Derived : Base {
public override void Method<S>(S a) {} public override void Method<S>(S a) {}
}"; }";
var unresolvedFile = Parse(program); var unresolvedFile = Parse(program);
ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(unresolvedFile.TopLevelTypeDefinitions[1]); ITypeDefinition derived = compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName("Derived"));
var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult; var rr = lookup.Lookup(new ResolveResult(derived), "Method", EmptyList<IType>.Instance, true) as MethodGroupResolveResult;
Assert.AreEqual(1, rr.MethodsGroupedByDeclaringType.Count()); Assert.AreEqual(1, rr.MethodsGroupedByDeclaringType.Count());
@ -456,5 +457,37 @@ class TestClass {
var mrr = Resolve<MemberResolveResult>(program); var mrr = Resolve<MemberResolveResult>(program);
Assert.AreEqual("TestClass.B", mrr.Member.FullName); Assert.AreEqual("TestClass.B", mrr.Member.FullName);
} }
[Test]
public void GenericClassDoesNotHideField()
{
string program = @"using System;
class A { public int F; }
class B : A { public class F<T> {} }
class C : B {
public void M()
{
$F$ = 1;
}
}";
var mrr = Resolve<MemberResolveResult>(program);
Assert.AreEqual("A.F", mrr.Member.FullName);
}
[Test]
public void NonGenericClassHidesField_WithExplicitThisAccess()
{
string program = @"using System;
class A { public int F; }
class B : A { public class F {} }
class C : B {
public void M()
{
$this.F$ = 1;
}
}";
var trr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("B+F", trr.Type.ReflectionName);
}
} }
} }

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs

@ -59,7 +59,7 @@ namespace ICSharpCode.NRefactory.Documentation
ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount = 0) ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount = 0)
{ {
return compilation.MainAssembly.GetTypeDefinition(nameSpace, name, typeParameterCount); return compilation.MainAssembly.GetTypeDefinition(new TopLevelTypeName(nameSpace, name, typeParameterCount));
} }
[Test] [Test]

3
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs

@ -48,6 +48,9 @@ namespace ICSharpCode.NRefactory.CSharp.FormattingTests
expectedOutput = NormalizeNewlines(expectedOutput); expectedOutput = NormalizeNewlines(expectedOutput);
IDocument doc = GetResult(policy, input, mode); IDocument doc = GetResult(policy, input, mode);
if (expectedOutput != doc.Text) { if (expectedOutput != doc.Text) {
Console.WriteLine ("expected:");
Console.WriteLine (expectedOutput);
Console.WriteLine ("got:");
Console.WriteLine (doc.Text); Console.WriteLine (doc.Text);
} }
Assert.AreEqual (expectedOutput, doc.Text); Assert.AreEqual (expectedOutput, doc.Text);

5
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs

@ -83,7 +83,7 @@ namespace System.Collections.Generic {
ITypeDefinition Resolve(IUnresolvedTypeDefinition typeDef) ITypeDefinition Resolve(IUnresolvedTypeDefinition typeDef)
{ {
return compilation.MainAssembly.GetTypeDefinition(typeDef); return typeDef.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition();
} }
[Test] [Test]
@ -135,8 +135,7 @@ namespace System.Collections.Generic {
// class C : C {} // class C : C {}
var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C");
c.BaseTypes.Add(c); c.BaseTypes.Add(c);
compilation = TypeSystemHelper.CreateCompilation(c); ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
ITypeDefinition resolvedC = Resolve(c);
Assert.AreEqual(new [] { resolvedC }, resolvedC.GetAllBaseTypes().ToArray()); Assert.AreEqual(new [] { resolvedC }, resolvedC.GetAllBaseTypes().ToArray());
} }

10
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs

@ -31,8 +31,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
public void EmptyClassHasToString() public void EmptyClassHasToString()
{ {
DefaultUnresolvedTypeDefinition c = new DefaultUnresolvedTypeDefinition(string.Empty, "C"); DefaultUnresolvedTypeDefinition c = new DefaultUnresolvedTypeDefinition(string.Empty, "C");
var compilation = TypeSystemHelper.CreateCompilation(c); var resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
Assert.AreEqual("System.Object.ToString", compilation.MainAssembly.GetTypeDefinition(c).GetMethods(m => m.Name == "ToString").Single().FullName); Assert.AreEqual("System.Object.ToString", resolvedC.GetMethods(m => m.Name == "ToString").Single().FullName);
} }
[Test] [Test]
@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
c.BaseTypes.Add(b2); c.BaseTypes.Add(b2);
var compilation = TypeSystemHelper.CreateCompilation(b1, b2, c); var compilation = TypeSystemHelper.CreateCompilation(b1, b2, c);
ITypeDefinition resolvedC = compilation.MainAssembly.GetTypeDefinition(c); ITypeDefinition resolvedC = compilation.MainAssembly.GetTypeDefinition(c.FullTypeName);
Assert.AreEqual(new[] { "P1", "P2" }, resolvedC.GetProperties().Select(p => p.Name).ToArray()); Assert.AreEqual(new[] { "P1", "P2" }, resolvedC.GetProperties().Select(p => p.Name).ToArray());
// Test that there's only one copy of ToString(): // Test that there's only one copy of ToString():
Assert.AreEqual(1, resolvedC.GetMethods(m => m.Name == "ToString").Count()); Assert.AreEqual(1, resolvedC.GetMethods(m => m.Name == "ToString").Count());
@ -91,8 +91,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
a.NestedTypes.Add(b); a.NestedTypes.Add(b);
var compilation = TypeSystemHelper.CreateCompilation(a, b); var compilation = TypeSystemHelper.CreateCompilation(a, b);
ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a); ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a.FullTypeName);
ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b); ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b.FullTypeName);
// A<> gets self-parameterized, B<> stays unbound // A<> gets self-parameterized, B<> stays unbound
Assert.AreEqual("A`1+B`1[[`0],[]]", resolvedA.GetNestedTypes().Single().ReflectionName); Assert.AreEqual("A`1+B`1[[`0],[]]", resolvedA.GetNestedTypes().Single().ReflectionName);

41
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeParameterTests.cs

@ -18,6 +18,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework; using NUnit.Framework;
@ -36,7 +37,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) } Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) }
}); });
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilation(c).MainAssembly.GetTypeDefinition(c); ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
// At runtime, we might have T=System.ValueType and U=int, so C# can't inherit the 'class' constraint // At runtime, we might have T=System.ValueType and U=int, so C# can't inherit the 'class' constraint
// from one type parameter to another. // from one type parameter to another.
Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType); Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType);
@ -54,7 +55,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) } Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) }
}); });
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilation(c).MainAssembly.GetTypeDefinition(c); ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
// At runtime, we might have T=System.ValueType and U=int, so C# can't inherit the 'class' constraint // At runtime, we might have T=System.ValueType and U=int, so C# can't inherit the 'class' constraint
// from one type parameter to another. // from one type parameter to another.
Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType); Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType);
@ -73,11 +74,45 @@ namespace ICSharpCode.NRefactory.TypeSystem
Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) } Constraints = { new TypeParameterReference(EntityType.TypeDefinition, 0) }
}); });
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilation(c).MainAssembly.GetTypeDefinition(c); ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType); Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType);
Assert.AreEqual(true, resolvedC.TypeParameters[1].IsReferenceType); Assert.AreEqual(true, resolvedC.TypeParameters[1].IsReferenceType);
Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", resolvedC.TypeParameters[0].EffectiveBaseClass.ReflectionName); Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", resolvedC.TypeParameters[0].EffectiveBaseClass.ReflectionName);
Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", resolvedC.TypeParameters[1].EffectiveBaseClass.ReflectionName); Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", resolvedC.TypeParameters[1].EffectiveBaseClass.ReflectionName);
} }
[Test]
public void ImportOpenGenericType()
{
// class C<T, U> { void M<X>() {} }
var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C");
c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 0, "T"));
c.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.TypeDefinition, 1, "U"));
var m = new DefaultUnresolvedMethod(c, "M");
m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(EntityType.Method, 0, "X"));
c.Members.Add(m);
var resolvedC1 = TypeSystemHelper.CreateCompilationAndResolve(c);
var resolvedM1 = resolvedC1.Methods.Single(method => method.Name == "M");
var resolvedC2 = TypeSystemHelper.CreateCompilationAndResolve(c);
var resolvedM2 = resolvedC2.Methods.Single(method => method.Name == "M");
// the types, methods and type parameters differ in the two compilations:
Assert.AreNotEqual(resolvedC1, resolvedC2);
Assert.AreNotEqual(resolvedM1, resolvedM2);
Assert.AreNotEqual(resolvedC1.TypeParameters[1], resolvedC2.TypeParameters[1]);
Assert.AreNotEqual(resolvedM1.TypeParameters[0], resolvedM2.TypeParameters[0]);
// C<U, X>
var pt1 = new ParameterizedType(resolvedC1, new[] { resolvedC1.TypeParameters[1], resolvedM1.TypeParameters[0] });
var pt2 = (ParameterizedType)resolvedC2.Compilation.Import(pt1);
// importing resulted in C<U, X> in the new compilation:
Assert.AreEqual(resolvedC2, pt2.GetDefinition());
Assert.AreEqual(resolvedC2.TypeParameters[1], pt2.TypeArguments[0]);
Assert.AreEqual(resolvedM2.TypeParameters[0], pt2.TypeArguments[1]);
}
} }
} }

6
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemHelper.cs

@ -44,5 +44,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
pc = pc.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore }); pc = pc.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore });
return pc.CreateCompilation(); return pc.CreateCompilation();
} }
public static ITypeDefinition CreateCompilationAndResolve(IUnresolvedTypeDefinition unresolvedTypeDefinition)
{
var compilation = CreateCompilation(unresolvedTypeDefinition);
return compilation.MainAssembly.GetTypeDefinition(unresolvedTypeDefinition.FullTypeName);
}
} }
} }

10
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs

@ -332,4 +332,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
public void Foo (int? bar = 42) { } public void Foo (int? bar = 42) { }
} }
public class AccessibilityTest
{
public void Public() {}
internal void Internal() {}
protected internal void ProtectedInternal() {}
internal protected void InternalProtected() {}
protected void Protected() {}
private void Private() {}
void None() {}
}
} }

22
src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs

@ -137,8 +137,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
ParameterizedType crt = (ParameterizedType)rt.ReferencedType; ParameterizedType crt = (ParameterizedType)rt.ReferencedType;
Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName); Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName);
Assert.AreEqual("System.String", crt.TypeArguments[0].FullName); Assert.AreEqual("System.String", crt.TypeArguments[0].FullName);
// ? for NUnit.TestAttribute (because that assembly isn't in ctx) // we know the name for TestAttribute, but not necessarily the namespace, as NUnit is not in the compilation
Assert.AreEqual("System.Collections.Generic.IList`1[[?]]", crt.TypeArguments[1].ReflectionName); Assert.AreEqual("System.Collections.Generic.IList", crt.TypeArguments[1].FullName);
var testAttributeType = ((ParameterizedType)crt.TypeArguments[1]).TypeArguments.Single();
Assert.AreEqual("TestAttribute", testAttributeType.Name);
Assert.AreEqual(TypeKind.Unknown, testAttributeType.Kind);
// (more accurately, we know the namespace and reflection name if the type was loaded by cecil,
// but not if we parsed it from C#)
} }
[Test] [Test]
@ -1208,5 +1213,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
var method = type.GetMethods ().Single (m => m.Name == "Foo"); var method = type.GetMethods ().Single (m => m.Name == "Foo");
Assert.AreEqual(42, method.Parameters.Single ().ConstantValue); Assert.AreEqual(42, method.Parameters.Single ().ConstantValue);
} }
[Test]
public void AccessibilityTests()
{
ITypeDefinition type = GetTypeDefinition(typeof(AccessibilityTest));
Assert.AreEqual(Accessibility.Public, type.Methods.Single(m => m.Name == "Public").Accessibility);
Assert.AreEqual(Accessibility.Internal, type.Methods.Single(m => m.Name == "Internal").Accessibility);
Assert.AreEqual(Accessibility.ProtectedOrInternal, type.Methods.Single(m => m.Name == "ProtectedInternal").Accessibility);
Assert.AreEqual(Accessibility.ProtectedOrInternal, type.Methods.Single(m => m.Name == "InternalProtected").Accessibility);
Assert.AreEqual(Accessibility.Protected, type.Methods.Single(m => m.Name == "Protected").Accessibility);
Assert.AreEqual(Accessibility.Private, type.Methods.Single(m => m.Name == "Private").Accessibility);
Assert.AreEqual(Accessibility.Private, type.Methods.Single(m => m.Name == "None").Accessibility);
}
} }
} }

2
src/Libraries/NRefactory/ICSharpCode.NRefactory/Documentation/GetPotentiallyNestedClassTypeReference.cs

@ -51,7 +51,7 @@ namespace ICSharpCode.NRefactory.Documentation
foreach (var asm in assemblies) { foreach (var asm in assemblies) {
if (asm == null) if (asm == null)
continue; continue;
ITypeDefinition typeDef = asm.GetTypeDefinition(ns, name, topLevelTPC); ITypeDefinition typeDef = asm.GetTypeDefinition(new TopLevelTypeName(ns, name, topLevelTPC));
for (int j = i + 1; j < parts.Length && typeDef != null; j++) { for (int j = i + 1; j < parts.Length && typeDef != null; j++) {
int tpc = (j == parts.Length - 1 ? typeParameterCount : 0); int tpc = (j == parts.Length - 1 ? typeParameterCount : 0);
typeDef = typeDef.NestedTypes.FirstOrDefault(n => n.Name == parts[j] && n.TypeParameterCount == tpc); typeDef = typeDef.NestedTypes.FirstOrDefault(n => n.Name == parts[j] && n.TypeParameterCount == tpc);

6
src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -137,7 +137,8 @@
<Compile Include="TypeSystem\DefaultSolutionSnapshot.cs" /> <Compile Include="TypeSystem\DefaultSolutionSnapshot.cs" />
<Compile Include="TypeSystem\DomRegion.cs" /> <Compile Include="TypeSystem\DomRegion.cs" />
<Compile Include="TypeSystem\EntityType.cs" /> <Compile Include="TypeSystem\EntityType.cs" />
<Compile Include="TypeSystem\ExtensionMethods.cs" /> <Compile Include="TypeSystem\TypeSystemExtensions.cs" />
<Compile Include="TypeSystem\FullTypeName.cs" />
<Compile Include="TypeSystem\IAmbience.cs" /> <Compile Include="TypeSystem\IAmbience.cs" />
<Compile Include="TypeSystem\IAssembly.cs" /> <Compile Include="TypeSystem\IAssembly.cs" />
<Compile Include="TypeSystem\IAttribute.cs" /> <Compile Include="TypeSystem\IAttribute.cs" />
@ -223,6 +224,7 @@
<Compile Include="TypeSystem\ProjectReference.cs" /> <Compile Include="TypeSystem\ProjectReference.cs" />
<Compile Include="TypeSystem\ReflectionNameParseException.cs" /> <Compile Include="TypeSystem\ReflectionNameParseException.cs" />
<Compile Include="TypeSystem\SimpleTypeResolveContext.cs" /> <Compile Include="TypeSystem\SimpleTypeResolveContext.cs" />
<Compile Include="TypeSystem\TopLevelTypeName.cs" />
<Compile Include="TypeSystem\TypeKind.cs" /> <Compile Include="TypeSystem\TypeKind.cs" />
<Compile Include="TypeSystem\TypeVisitor.cs" /> <Compile Include="TypeSystem\TypeVisitor.cs" />
<Compile Include="TypeSystem\IVariable.cs" /> <Compile Include="TypeSystem\IVariable.cs" />
@ -284,4 +286,4 @@
</None> </None>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project> </Project>

10
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary> /// <summary>
/// Represents an array type. /// Represents an array type.
/// </summary> /// </summary>
public sealed class ArrayType : TypeWithElementType public sealed class ArrayType : TypeWithElementType, ICompilationProvider
{ {
readonly int dimensions; readonly int dimensions;
readonly ICompilation compilation; readonly ICompilation compilation;
@ -38,12 +38,20 @@ namespace ICSharpCode.NRefactory.TypeSystem
throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive"); throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive");
this.compilation = compilation; this.compilation = compilation;
this.dimensions = dimensions; this.dimensions = dimensions;
ICompilationProvider p = elementType as ICompilationProvider;
if (p != null && p.Compilation != compilation)
throw new InvalidOperationException("Cannot create an array type using a different compilation from the element type.");
} }
public override TypeKind Kind { public override TypeKind Kind {
get { return TypeKind.Array; } get { return TypeKind.Array; }
} }
public ICompilation Compilation {
get { return compilation; }
}
public int Dimensions { public int Dimensions {
get { return dimensions; } get { return dimensions; }
} }

20
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -190,7 +190,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
name = interningProvider.Intern(name); name = interningProvider.Intern(name);
var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount); var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount);
typeRef = interningProvider.Intern(typeRef); typeRef = interningProvider.Intern(typeRef);
var key = new FullNameAndTypeParameterCount(ns, name, typeParameterCount); var key = new TopLevelTypeName(ns, name, typeParameterCount);
currentAssembly.AddTypeForwarder(key, typeRef); currentAssembly.AddTypeForwarder(key, typeRef);
} }
} }
@ -227,6 +227,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
} }
AddToTypeSystemTranslationTable(this.currentAssembly, assemblyDefinition); AddToTypeSystemTranslationTable(this.currentAssembly, assemblyDefinition);
// Freezing the assembly here is important:
// otherwise it will be frozen when a compilation is first created
// from it. But freezing has the effect of changing some collection instances
// (to ReadOnlyCollection). This hidden mutation was causing a crash
// when the FastSerializer was saving the assembly at the same time as
// the first compilation was created from it.
// By freezing the assembly now, we ensure it is usable on multiple
// threads without issues.
currentAssembly.Freeze(); currentAssembly.Freeze();
var result = this.currentAssembly; var result = this.currentAssembly;
@ -515,7 +523,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask; MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
#region DllImportAttribute #region DllImportAttribute
if (methodDefinition.HasPInvokeInfo) { if (methodDefinition.HasPInvokeInfo && methodDefinition.PInvokeInfo != null) {
PInvokeInfo info = methodDefinition.PInvokeInfo; PInvokeInfo info = methodDefinition.PInvokeInfo;
var dllImport = new DefaultUnresolvedAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String }); var dllImport = new DefaultUnresolvedAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String });
dllImport.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, info.Module.Name)); dllImport.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, info.Module.Name));
@ -1785,6 +1793,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
get { return cecilTypeDef.FullName; } get { return cecilTypeDef.FullName; }
} }
public FullTypeName FullTypeName {
get {
return new TopLevelTypeName(namespaceName, this.Name, typeParameters.Count);
}
}
public TypeKind Kind { public TypeKind Kind {
get { return kind; } get { return kind; }
} }
@ -1876,7 +1890,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
throw new ArgumentNullException("context"); throw new ArgumentNullException("context");
if (context.CurrentAssembly == null) if (context.CurrentAssembly == null)
throw new ArgumentException("An ITypeDefinition cannot be resolved in a context without a current assembly."); throw new ArgumentException("An ITypeDefinition cannot be resolved in a context without a current assembly.");
return context.CurrentAssembly.GetTypeDefinition(this) return context.CurrentAssembly.GetTypeDefinition(this.FullTypeName)
?? (IType)new UnknownType(this.Namespace, this.Name, this.TypeParameters.Count); ?? (IType)new UnknownType(this.Namespace, this.Name, this.TypeParameters.Count);
} }

313
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/FullTypeName.cs

@ -0,0 +1,313 @@
// Copyright (c) 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 System.Text;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Holds the full name of a type definition.
/// A full type name uniquely identifies a type definition within a single assembly.
/// </summary>
/// <remarks>
/// A full type name can only represent type definitions, not arbitrary types.
/// It does not include any type arguments, and can not refer to array or pointer types.
///
/// A full type name represented as reflection name has the syntax:
/// <c>NamespaceName '.' TopLevelTypeName ['`'#] { '+' NestedTypeName ['`'#] }</c>
/// </remarks>
[Serializable]
public struct FullTypeName : IEquatable<FullTypeName>
{
[Serializable]
struct NestedTypeName
{
public readonly string Name;
public readonly int AdditionalTypeParameterCount;
public NestedTypeName(string name, int additionalTypeParameterCount)
{
if (name == null)
throw new ArgumentNullException("name");
this.Name = name;
this.AdditionalTypeParameterCount = additionalTypeParameterCount;
}
}
readonly TopLevelTypeName topLevelType;
readonly NestedTypeName[] nestedTypes;
FullTypeName(TopLevelTypeName topLevelTypeName, NestedTypeName[] nestedTypes)
{
this.topLevelType = topLevelTypeName;
this.nestedTypes = nestedTypes;
}
/// <summary>
/// Constructs a FullTypeName representing the given top-level type.
/// </summary>
/// <remarks>
/// FullTypeName has an implicit conversion operator from TopLevelTypeName,
/// so you can simply write:
/// <c>FullTypeName f = new TopLevelTypeName(...);</c>
/// </remarks>
public FullTypeName(TopLevelTypeName topLevelTypeName)
{
this.topLevelType = topLevelTypeName;
this.nestedTypes = null;
}
/// <summary>
/// Constructs a FullTypeName by parsing the given reflection name.
/// Note that FullTypeName can only represent type definition names. If the reflection name
/// might refer to a parameterized type or array etc., use
/// <see cref="ReflectionHelper.ParseReflectionName(string)"/> instead.
/// </summary>
/// <remarks>
/// Expected syntax: <c>NamespaceName '.' TopLevelTypeName ['`'#] { '+' NestedTypeName ['`'#] }</c>
/// where # are type parameter counts
/// </remarks>
public FullTypeName(string reflectionName)
{
int pos = reflectionName.IndexOf('+');
if (pos < 0) {
// top-level type
this.topLevelType = new TopLevelTypeName(reflectionName);
this.nestedTypes = null;
} else {
// nested type
string[] parts = reflectionName.Split('+');
this.topLevelType = new TopLevelTypeName(parts[0]);
this.nestedTypes = new NestedTypeName[parts.Length - 1];
for (int i = 0; i < nestedTypes.Length; i++) {
int tpc;
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(parts[i + 1], out tpc);
nestedTypes[i] = new NestedTypeName(name, tpc);
}
}
}
/// <summary>
/// Gets the top-level type name.
/// </summary>
public TopLevelTypeName TopLevelTypeName {
get { return topLevelType; }
}
/// <summary>
/// Gets whether this is a nested type.
/// </summary>
public bool IsNested {
get {
return nestedTypes != null;
}
}
/// <summary>
/// Gets the nesting level.
/// </summary>
public int NestingLevel {
get {
return nestedTypes != null ? nestedTypes.Length : 0;
}
}
/// <summary>
/// Gets the name of the type.
/// For nested types, this is the name of the innermost type.
/// </summary>
public string Name {
get {
if (nestedTypes != null)
return nestedTypes[nestedTypes.Length - 1].Name;
else
return topLevelType.Name;
}
}
public string ReflectionName {
get {
if (nestedTypes == null)
return topLevelType.ReflectionName;
StringBuilder b = new StringBuilder(topLevelType.ReflectionName);
foreach (NestedTypeName nt in nestedTypes) {
b.Append('+');
b.Append(nt.Name);
if (nt.AdditionalTypeParameterCount > 0) {
b.Append('`');
b.Append(nt.AdditionalTypeParameterCount);
}
}
return b.ToString();
}
}
/// <summary>
/// Gets the total type parameter count.
/// </summary>
public int TypeParameterCount {
get {
int tpc = topLevelType.TypeParameterCount;
if (nestedTypes != null) {
foreach (var nt in nestedTypes) {
tpc += nt.AdditionalTypeParameterCount;
}
}
return tpc;
}
}
/// <summary>
/// Gets the name of the nested type at the given level.
/// </summary>
public string GetNestedTypeName(int nestingLevel)
{
if (nestedTypes == null)
throw new InvalidOperationException();
return nestedTypes[nestingLevel].Name;
}
/// <summary>
/// Gets the number of additional type parameters of the nested type at the given level.
/// </summary>
public int GetNestedTypeAdditionalTypeParameterCount(int nestingLevel)
{
if (nestedTypes == null)
throw new InvalidOperationException();
return nestedTypes[nestingLevel].AdditionalTypeParameterCount;
}
/// <summary>
/// Gets the declaring type name.
/// </summary>
/// <exception cref="InvalidOperationException">This is a top-level type name.</exception>
public FullTypeName GetDeclaringType()
{
if (nestedTypes == null)
throw new InvalidOperationException();
if (nestedTypes.Length == 1)
return topLevelType;
NestedTypeName[] outerNestedTypeNames = new NestedTypeName[nestedTypes.Length - 1];
Array.Copy(nestedTypes, 0, outerNestedTypeNames, 0, outerNestedTypeNames.Length);
return new FullTypeName(topLevelType, nestedTypes);
}
/// <summary>
/// Gets a nested type name.
/// </summary>
public FullTypeName NestedType(string name, int additionalTypeParameterCount)
{
if (name == null)
throw new ArgumentNullException("name");
var newNestedType = new NestedTypeName(name, additionalTypeParameterCount);
if (nestedTypes == null)
return new FullTypeName(topLevelType, new[] { newNestedType });
NestedTypeName[] newNestedTypeNames = new NestedTypeName[nestedTypes.Length + 1];
nestedTypes.CopyTo(newNestedTypeNames, 0);
newNestedTypeNames[newNestedTypeNames.Length - 1] = newNestedType;
return new FullTypeName(topLevelType, newNestedTypeNames);
}
public static implicit operator FullTypeName(TopLevelTypeName topLevelTypeName)
{
return new FullTypeName(topLevelTypeName);
}
public override string ToString()
{
return this.ReflectionName;
}
#region Equals and GetHashCode implementation
public override bool Equals(object obj)
{
return obj is FullTypeName && Equals((FullTypeName)obj);
}
public bool Equals(FullTypeName other)
{
return FullTypeNameComparer.Ordinal.Equals(this, other);
}
public override int GetHashCode()
{
return FullTypeNameComparer.Ordinal.GetHashCode(this);
}
public static bool operator ==(FullTypeName left, FullTypeName right)
{
return left.Equals(right);
}
public static bool operator !=(FullTypeName left, FullTypeName right)
{
return !left.Equals(right);
}
#endregion
}
[Serializable]
public sealed class FullTypeNameComparer : IEqualityComparer<FullTypeName>
{
public static readonly FullTypeNameComparer Ordinal = new FullTypeNameComparer(StringComparer.Ordinal);
public static readonly FullTypeNameComparer OrdinalIgnoreCase = new FullTypeNameComparer(StringComparer.OrdinalIgnoreCase);
public readonly StringComparer NameComparer;
public FullTypeNameComparer(StringComparer nameComparer)
{
this.NameComparer = nameComparer;
}
public bool Equals(FullTypeName x, FullTypeName y)
{
if (x.NestingLevel != y.NestingLevel)
return false;
TopLevelTypeName topX = x.TopLevelTypeName;
TopLevelTypeName topY = y.TopLevelTypeName;
if (topX.TypeParameterCount == topY.TypeParameterCount
&& NameComparer.Equals(topX.Name, topY.Name)
&& NameComparer.Equals(topX.Namespace, topY.Namespace))
{
for (int i = 0; i < x.NestingLevel; i++) {
if (x.GetNestedTypeAdditionalTypeParameterCount(i) != y.GetNestedTypeAdditionalTypeParameterCount(i))
return false;
if (!NameComparer.Equals(x.GetNestedTypeName(i), y.GetNestedTypeName(i)))
return false;
}
return true;
}
return false;
}
public int GetHashCode(FullTypeName obj)
{
TopLevelTypeName top = obj.TopLevelTypeName;
int hash = NameComparer.GetHashCode(top.Name) ^ NameComparer.GetHashCode(top.Namespace) ^ top.TypeParameterCount;
unchecked {
for (int i = 0; i < obj.NestingLevel; i++) {
hash *= 31;
hash += NameComparer.GetHashCode(obj.Name) ^ obj.TypeParameterCount;
}
}
return hash;
}
}
}

4
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAssembly.cs

@ -69,7 +69,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary> /// <summary>
/// Represents an assembly. /// Represents an assembly.
/// </summary> /// </summary>
public interface IAssembly : IResolved public interface IAssembly : ICompilationProvider
{ {
/// <summary> /// <summary>
/// Gets the original unresolved assembly. /// Gets the original unresolved assembly.
@ -115,7 +115,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// Gets the type definition for a top-level type. /// Gets the type definition for a top-level type.
/// </summary> /// </summary>
/// <remarks>This method uses ordinal name comparison, not the compilation's name comparer.</remarks> /// <remarks>This method uses ordinal name comparison, not the compilation's name comparer.</remarks>
ITypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount); ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName);
/// <summary> /// <summary>
/// Gets all non-nested types in the assembly. /// Gets all non-nested types in the assembly.

9
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ICompilation.cs

@ -37,6 +37,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary> /// <summary>
/// Gets the list of all assemblies in the compilation. /// Gets the list of all assemblies in the compilation.
/// </summary> /// </summary>
/// <remarks>
/// This main assembly is the first entry in the list.
/// </remarks>
IList<IAssembly> Assemblies { get; } IList<IAssembly> Assemblies { get; }
/// <summary> /// <summary>
@ -69,8 +72,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
CacheManager CacheManager { get; } CacheManager CacheManager { get; }
} }
public interface IResolved public interface ICompilationProvider
{ {
/// <summary>
/// Gets the parent compilation.
/// This property never returns null.
/// </summary>
ICompilation Compilation { get; } ICompilation Compilation { get; }
} }
} }

2
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs

@ -93,7 +93,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary> /// <summary>
/// Represents a resolved entity. /// Represents a resolved entity.
/// </summary> /// </summary>
public interface IEntity : IResolved, INamedElement, IHasAccessibility public interface IEntity : ICompilationProvider, INamedElement, IHasAccessibility
{ {
/// <summary> /// <summary>
/// Gets the entity type. /// Gets the entity type.

2
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/INamespace.cs

@ -24,7 +24,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary> /// <summary>
/// Represents a resolved namespace. /// Represents a resolved namespace.
/// </summary> /// </summary>
public interface INamespace : IResolved public interface INamespace : ICompilationProvider
{ {
// No pointer back to unresolved namespace: // No pointer back to unresolved namespace:
// multiple unresolved namespaces (from different assemblies) get // multiple unresolved namespaces (from different assemblies) get

6
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs

@ -30,6 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
{ {
TypeKind Kind { get; } TypeKind Kind { get; }
FullTypeName FullTypeName { get; }
IList<ITypeReference> BaseTypes { get; } IList<ITypeReference> BaseTypes { get; }
IList<IUnresolvedTypeParameter> TypeParameters { get; } IList<IUnresolvedTypeParameter> TypeParameters { get; }
@ -119,6 +120,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary> /// </summary>
IType EnumUnderlyingType { get; } IType EnumUnderlyingType { get; }
/// <summary>
/// Gets the full name of this type.
/// </summary>
FullTypeName FullTypeName { get; }
/// <summary> /// <summary>
/// Gets/Sets the declaring type (incl. type arguments, if any). /// Gets/Sets the declaring type (incl. type arguments, if any).
/// This property never returns null -- for top-level entities, it returns SharedTypes.UnknownType. /// This property never returns null -- for top-level entities, it returns SharedTypes.UnknownType.

10
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs

@ -43,20 +43,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </param> /// </param>
/// <returns> /// <returns>
/// Returns the resolved type. /// Returns the resolved type.
/// In case of an error, returns <see cref="SpecialType.UnknownType"/>. /// In case of an error, returns an unknown type (<see cref="TypeKind.Unknown"/>).
/// Never returns null. /// Never returns null.
/// </returns> /// </returns>
IType Resolve(ITypeResolveContext context); IType Resolve(ITypeResolveContext context);
} }
public interface ITypeResolveContext public interface ITypeResolveContext : ICompilationProvider
{ {
/// <summary>
/// Gets the parent compilation.
/// This property never returns null.
/// </summary>
ICompilation Compilation { get; }
/// <summary> /// <summary>
/// Gets the current assembly. /// Gets the current assembly.
/// This property may return null if this context does not specify any assembly. /// This property may return null if this context does not specify any assembly.

2
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs

@ -24,7 +24,7 @@ using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{ {
public abstract class AbstractTypeParameter : ITypeParameter public abstract class AbstractTypeParameter : ITypeParameter, ICompilationProvider
{ {
readonly ICompilation compilation; readonly ICompilation compilation;
readonly EntityType ownerType; readonly EntityType ownerType;

4
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs

@ -566,6 +566,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return parts[0].Namespace; } get { return parts[0].Namespace; }
} }
public FullTypeName FullTypeName {
get { return parts[0].FullTypeName; }
}
public DomRegion Region { public DomRegion Region {
get { return parts[0].Region; } get { return parts[0].Region; }
} }

28
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs

@ -39,8 +39,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
string fullAssemblyName; string fullAssemblyName;
IList<IUnresolvedAttribute> assemblyAttributes; IList<IUnresolvedAttribute> assemblyAttributes;
IList<IUnresolvedAttribute> moduleAttributes; IList<IUnresolvedAttribute> moduleAttributes;
Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition> typeDefinitions = new Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition>(FullNameAndTypeParameterCountComparer.Ordinal); Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> typeDefinitions = new Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition>(TopLevelTypeNameComparer.Ordinal);
Dictionary<FullNameAndTypeParameterCount, ITypeReference> typeForwarders = new Dictionary<FullNameAndTypeParameterCount, ITypeReference>(FullNameAndTypeParameterCountComparer.Ordinal); Dictionary<TopLevelTypeName, ITypeReference> typeForwarders = new Dictionary<TopLevelTypeName, ITypeReference>(TopLevelTypeNameComparer.Ordinal);
protected override void FreezeInternal() protected override void FreezeInternal()
{ {
@ -144,7 +144,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (typeDefinition.DeclaringTypeDefinition != null) if (typeDefinition.DeclaringTypeDefinition != null)
throw new ArgumentException("Cannot add nested types."); throw new ArgumentException("Cannot add nested types.");
FreezableHelper.ThrowIfFrozen(this); FreezableHelper.ThrowIfFrozen(this);
var key = new FullNameAndTypeParameterCount(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameters.Count); var key = new TopLevelTypeName(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameters.Count);
typeDefinitions.Add(key, typeDefinition); typeDefinitions.Add(key, typeDefinition);
} }
@ -157,7 +157,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// </summary> /// </summary>
/// <param name="typeName">The name of the type.</param> /// <param name="typeName">The name of the type.</param>
/// <param name="referencedType">The reference used to look up the type in the target assembly.</param> /// <param name="referencedType">The reference used to look up the type in the target assembly.</param>
public void AddTypeForwarder(FullNameAndTypeParameterCount typeName, ITypeReference referencedType) public void AddTypeForwarder(TopLevelTypeName typeName, ITypeReference referencedType)
{ {
if (referencedType == null) if (referencedType == null)
throw new ArgumentNullException("referencedType"); throw new ArgumentNullException("referencedType");
@ -187,7 +187,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IUnresolvedTypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount) public IUnresolvedTypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount)
{ {
var key = new FullNameAndTypeParameterCount(ns ?? string.Empty, name, typeParameterCount); var key = new TopLevelTypeName(ns ?? string.Empty, name, typeParameterCount);
IUnresolvedTypeDefinition td; IUnresolvedTypeDefinition td;
if (typeDefinitions.TryGetValue(key, out td)) if (typeDefinitions.TryGetValue(key, out td))
return td; return td;
@ -216,9 +216,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
//[NonSerialized] //[NonSerialized]
//List<Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition>> cachedTypeDictionariesPerNameComparer; //List<Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition>> cachedTypeDictionariesPerNameComparer;
Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition> GetTypeDictionary(StringComparer nameComparer) Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> GetTypeDictionary(StringComparer nameComparer)
{ {
Debug.Assert(IsFrozen); Debug.Assert(IsFrozen);
if (nameComparer == StringComparer.Ordinal) if (nameComparer == StringComparer.Ordinal)
@ -291,7 +291,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
readonly DefaultUnresolvedAssembly unresolvedAssembly; readonly DefaultUnresolvedAssembly unresolvedAssembly;
readonly ICompilation compilation; readonly ICompilation compilation;
readonly ITypeResolveContext context; readonly ITypeResolveContext context;
readonly Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition> unresolvedTypeDict; readonly Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> unresolvedTypeDict;
readonly ConcurrentDictionary<IUnresolvedTypeDefinition, ITypeDefinition> typeDict = new ConcurrentDictionary<IUnresolvedTypeDefinition, ITypeDefinition>(); readonly ConcurrentDictionary<IUnresolvedTypeDefinition, ITypeDefinition> typeDict = new ConcurrentDictionary<IUnresolvedTypeDefinition, ITypeDefinition>();
readonly INamespace rootNamespace; readonly INamespace rootNamespace;
@ -338,15 +338,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return assembly == this; return assembly == this;
} }
public ITypeDefinition GetTypeDefinition(string ns, string name, int typeParameterCount) public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
{ {
var key = new FullNameAndTypeParameterCount(ns ?? string.Empty, name, typeParameterCount);
IUnresolvedTypeDefinition td; IUnresolvedTypeDefinition td;
ITypeReference typeRef; ITypeReference typeRef;
if (unresolvedAssembly.typeDefinitions.TryGetValue(key, out td)) if (unresolvedAssembly.typeDefinitions.TryGetValue(topLevelTypeName, out td))
return GetTypeDefinition(td); return GetTypeDefinition(td);
else if (unresolvedAssembly.typeForwarders.TryGetValue(key, out typeRef)) else if (unresolvedAssembly.typeForwarders.TryGetValue(topLevelTypeName, out typeRef))
return typeRef.Resolve(compilation.TypeResolveContext).GetDefinition(); return typeRef.Resolve(compilation.TypeResolveContext).GetDefinition();
else else
return null; return null;
@ -431,7 +429,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return null; return null;
} }
ICompilation IResolved.Compilation { ICompilation ICompilationProvider.Compilation {
get { return assembly.compilation; } get { return assembly.compilation; }
} }
@ -453,7 +451,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount) ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount)
{ {
var key = new FullNameAndTypeParameterCount(ns.FullName, name, typeParameterCount); var key = new TopLevelTypeName(ns.FullName, name, typeParameterCount);
IUnresolvedTypeDefinition unresolvedTypeDef; IUnresolvedTypeDefinition unresolvedTypeDef;
if (assembly.unresolvedTypeDict.TryGetValue(key, out unresolvedTypeDef)) if (assembly.unresolvedTypeDict.TryGetValue(key, out unresolvedTypeDef))
return assembly.GetTypeDefinition(unresolvedTypeDef); return assembly.GetTypeDefinition(unresolvedTypeDef);

2
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs

@ -187,7 +187,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return true; return true;
} }
sealed class DefaultResolvedAttribute : IAttribute, IResolved sealed class DefaultResolvedAttribute : IAttribute, ICompilationProvider
{ {
readonly DefaultUnresolvedAttribute unresolved; readonly DefaultUnresolvedAttribute unresolved;
readonly ITypeResolveContext context; readonly ITypeResolveContext context;

24
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedTypeDefinition.cs

@ -141,24 +141,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
public override string ReflectionName { public override string ReflectionName {
get {
return this.FullTypeName.ReflectionName;
}
}
public FullTypeName FullTypeName {
get { get {
IUnresolvedTypeDefinition declaringTypeDef = this.DeclaringTypeDefinition; IUnresolvedTypeDefinition declaringTypeDef = this.DeclaringTypeDefinition;
if (declaringTypeDef != null) { if (declaringTypeDef != null) {
if (this.TypeParameters.Count > declaringTypeDef.TypeParameters.Count) { return declaringTypeDef.FullTypeName.NestedType(this.Name, this.TypeParameters.Count - declaringTypeDef.TypeParameters.Count);
return declaringTypeDef.ReflectionName + "+" + this.Name + "`" + (this.TypeParameters.Count - declaringTypeDef.TypeParameters.Count).ToString(CultureInfo.InvariantCulture);
} else {
return declaringTypeDef.ReflectionName + "+" + this.Name;
}
} else if (string.IsNullOrEmpty(namespaceName)) {
if (this.TypeParameters.Count > 0)
return this.Name + "`" + this.TypeParameters.Count.ToString(CultureInfo.InvariantCulture);
else
return this.Name;
} else { } else {
if (this.TypeParameters.Count > 0) return new TopLevelTypeName(namespaceName, this.Name, this.TypeParameters.Count);
return namespaceName + "." + this.Name + "`" + this.TypeParameters.Count.ToString(CultureInfo.InvariantCulture);
else
return namespaceName + "." + this.Name;
} }
} }
} }
@ -226,7 +220,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
throw new ArgumentNullException("context"); throw new ArgumentNullException("context");
if (context.CurrentAssembly == null) if (context.CurrentAssembly == null)
throw new ArgumentException("An ITypeDefinition cannot be resolved in a context without a current assembly."); throw new ArgumentException("An ITypeDefinition cannot be resolved in a context without a current assembly.");
return context.CurrentAssembly.GetTypeDefinition(this) return context.CurrentAssembly.GetTypeDefinition(this.FullTypeName)
?? (IType)new UnknownType(this.Namespace, this.Name, this.TypeParameters.Count); ?? (IType)new UnknownType(this.Namespace, this.Name, this.TypeParameters.Count);
} }

69
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/FullNameAndTypeParameterCount.cs

@ -21,73 +21,8 @@ using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{ {
[Serializable] [Obsolete("This struct was renamed to 'TopLevelTypeName'.", true)]
public struct FullNameAndTypeParameterCount : IEquatable<FullNameAndTypeParameterCount> public struct FullNameAndTypeParameterCount
{ {
public readonly string Namespace;
public readonly string Name;
public readonly int TypeParameterCount;
public FullNameAndTypeParameterCount(string nameSpace, string name, int typeParameterCount)
{
if (nameSpace == null)
throw new ArgumentNullException("nameSpace");
if (name == null)
throw new ArgumentNullException("name");
this.Namespace = nameSpace;
this.Name = name;
this.TypeParameterCount = typeParameterCount;
}
public override bool Equals(object obj)
{
return (obj is FullNameAndTypeParameterCount) && Equals((FullNameAndTypeParameterCount)obj);
}
public bool Equals(FullNameAndTypeParameterCount other)
{
return this.Namespace == other.Namespace && this.Name == other.Name && this.TypeParameterCount == other.TypeParameterCount;
}
public override int GetHashCode()
{
return Name.GetHashCode() ^ Namespace.GetHashCode() ^ TypeParameterCount;
}
public static bool operator ==(FullNameAndTypeParameterCount lhs, FullNameAndTypeParameterCount rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(FullNameAndTypeParameterCount lhs, FullNameAndTypeParameterCount rhs)
{
return !lhs.Equals(rhs);
}
}
[Serializable]
public sealed class FullNameAndTypeParameterCountComparer : IEqualityComparer<FullNameAndTypeParameterCount>
{
public static readonly FullNameAndTypeParameterCountComparer Ordinal = new FullNameAndTypeParameterCountComparer(StringComparer.Ordinal);
public static readonly FullNameAndTypeParameterCountComparer OrdinalIgnoreCase = new FullNameAndTypeParameterCountComparer(StringComparer.OrdinalIgnoreCase);
public readonly StringComparer NameComparer;
public FullNameAndTypeParameterCountComparer(StringComparer nameComparer)
{
this.NameComparer = nameComparer;
}
public bool Equals(FullNameAndTypeParameterCount x, FullNameAndTypeParameterCount y)
{
return x.TypeParameterCount == y.TypeParameterCount
&& NameComparer.Equals(x.Name, y.Name)
&& NameComparer.Equals(x.Namespace, y.Namespace);
}
public int GetHashCode(FullNameAndTypeParameterCount obj)
{
return NameComparer.GetHashCode(obj.Name) ^ NameComparer.GetHashCode(obj.Namespace) ^ obj.TypeParameterCount;
}
} }
} }

99
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs

@ -28,24 +28,31 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public sealed class GetClassTypeReference : ITypeReference, ISupportsInterning public sealed class GetClassTypeReference : ITypeReference, ISupportsInterning
{ {
readonly IAssemblyReference assembly; readonly IAssemblyReference assembly;
readonly string nameSpace, name; readonly FullTypeName fullTypeName;
readonly int typeParameterCount;
/// <summary> /// <summary>
/// Creates a new GetClassTypeReference that searches a top-level type. /// Creates a new GetClassTypeReference that searches a type definition.
/// </summary> /// </summary>
/// <param name="nameSpace">The namespace name containing the type, e.g. "System.Collections.Generic".</param> /// <param name="fullTypeName">The full name of the type.</param>
/// <param name="assembly">A reference to the assembly containing this type.
/// If this parameter is null, the GetClassTypeReference will search in all
/// assemblies belonging to the compilation.
/// </param>
public GetClassTypeReference(FullTypeName fullTypeName, IAssemblyReference assembly = null)
{
this.fullTypeName = fullTypeName;
this.assembly = assembly;
}
/// <summary>
/// Creates a new GetClassTypeReference that searches a top-level type in all assemblies.
/// </summary>
/// <param name="namespaceName">The namespace name containing the type, e.g. "System.Collections.Generic".</param>
/// <param name="name">The name of the type, e.g. "List".</param> /// <param name="name">The name of the type, e.g. "List".</param>
/// <param name="typeParameterCount">The number of type parameters, (e.g. 1 for List&lt;T&gt;).</param> /// <param name="typeParameterCount">The number of type parameters, (e.g. 1 for List&lt;T&gt;).</param>
public GetClassTypeReference(string nameSpace, string name, int typeParameterCount = 0) public GetClassTypeReference(string namespaceName, string name, int typeParameterCount = 0)
{ {
if (nameSpace == null) this.fullTypeName = new TopLevelTypeName(namespaceName, name, typeParameterCount);
throw new ArgumentNullException("nameSpace");
if (name == null)
throw new ArgumentNullException("name");
this.nameSpace = nameSpace;
this.name = name;
this.typeParameterCount = typeParameterCount;
} }
/// <summary> /// <summary>
@ -53,25 +60,33 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// </summary> /// </summary>
/// <param name="assembly">A reference to the assembly containing this type. /// <param name="assembly">A reference to the assembly containing this type.
/// If this parameter is null, the GetClassTypeReference will search in all assemblies belonging to the ICompilation.</param> /// If this parameter is null, the GetClassTypeReference will search in all assemblies belonging to the ICompilation.</param>
/// <param name="nameSpace">The namespace name containing the type, e.g. "System.Collections.Generic".</param> /// <param name="namespaceName">The namespace name containing the type, e.g. "System.Collections.Generic".</param>
/// <param name="name">The name of the type, e.g. "List".</param> /// <param name="name">The name of the type, e.g. "List".</param>
/// <param name="typeParameterCount">The number of type parameters, (e.g. 1 for List&lt;T&gt;).</param> /// <param name="typeParameterCount">The number of type parameters, (e.g. 1 for List&lt;T&gt;).</param>
public GetClassTypeReference(IAssemblyReference assembly, string nameSpace, string name, int typeParameterCount = 0) public GetClassTypeReference(IAssemblyReference assembly, string namespaceName, string name, int typeParameterCount = 0)
{ {
if (nameSpace == null)
throw new ArgumentNullException("nameSpace");
if (name == null)
throw new ArgumentNullException("name");
this.assembly = assembly; this.assembly = assembly;
this.nameSpace = nameSpace; this.fullTypeName = new TopLevelTypeName(namespaceName, name, typeParameterCount);
this.name = name;
this.typeParameterCount = typeParameterCount;
} }
/// <summary>
/// Gets the assembly reference.
/// This property returns null if the GetClassTypeReference is searching in all assemblies
/// of the compilation.
/// </summary>
public IAssemblyReference Assembly { get { return assembly; } } public IAssemblyReference Assembly { get { return assembly; } }
public string Namespace { get { return nameSpace; } }
public string Name { get { return name; } } /// <summary>
public int TypeParameterCount { get { return typeParameterCount; } } /// Gets the full name of the type this reference is searching for.
/// </summary>
public FullTypeName FullTypeName { get { return fullTypeName; } }
[Obsolete("Use the FullTypeName property instead. GetClassTypeReference now supports nested types, where the Namespace/Name/TPC tripel isn't sufficient for identifying the type.")]
public string Namespace { get { return fullTypeName.TopLevelTypeName.Namespace; } }
[Obsolete("Use the FullTypeName property instead. GetClassTypeReference now supports nested types, where the Namespace/Name/TPC tripel isn't sufficient for identifying the type.")]
public string Name { get { return fullTypeName.Name; } }
[Obsolete("Use the FullTypeName property instead. GetClassTypeReference now supports nested types, where the Namespace/Name/TPC tripel isn't sufficient for identifying the type.")]
public int TypeParameterCount { get { return fullTypeName.TypeParameterCount; } }
public IType Resolve(ITypeResolveContext context) public IType Resolve(ITypeResolveContext context)
{ {
@ -80,52 +95,42 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
IType type = null; IType type = null;
if (assembly == null) { if (assembly == null) {
var compilation = context.Compilation; if (context.CurrentAssembly != null) {
foreach (var asm in new[] { context.CurrentAssembly }.Concat(compilation.Assemblies)) { type = context.CurrentAssembly.GetTypeDefinition(fullTypeName);
if (asm != null) { }
type = asm.GetTypeDefinition(nameSpace, name, typeParameterCount); if (type == null) {
var compilation = context.Compilation;
foreach (var asm in compilation.Assemblies) {
type = asm.GetTypeDefinition(fullTypeName);
if (type != null) if (type != null)
return type; break;
} }
} }
} else { } else {
IAssembly asm = assembly.Resolve(context); IAssembly asm = assembly.Resolve(context);
if (asm != null) { if (asm != null) {
type = asm.GetTypeDefinition(nameSpace, name, typeParameterCount); type = asm.GetTypeDefinition(fullTypeName);
} }
} }
return type ?? new UnknownType(nameSpace, name, typeParameterCount); return type ?? new UnknownType(fullTypeName);
} }
public override string ToString() public override string ToString()
{ {
string asmSuffix = (assembly != null ? ", " + assembly.ToString() : null); return fullTypeName.ToString() + (assembly != null ? ", " + assembly.ToString() : null);
if (typeParameterCount == 0)
return BuildQualifiedName(nameSpace, name) + asmSuffix;
else
return BuildQualifiedName(nameSpace, name) + "`" + typeParameterCount + asmSuffix;
}
static string BuildQualifiedName (string name1, string name2)
{
if (string.IsNullOrEmpty (name1))
return name2;
if (string.IsNullOrEmpty (name2))
return name1;
return name1 + "." + name2;
} }
int ISupportsInterning.GetHashCodeForInterning() int ISupportsInterning.GetHashCodeForInterning()
{ {
unchecked { unchecked {
return 33 * assembly.GetHashCode() + 27 * nameSpace.GetHashCode() + name.GetHashCode() + typeParameterCount; return 33 * assembly.GetHashCode() + fullTypeName.GetHashCode();
} }
} }
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{ {
GetClassTypeReference o = other as GetClassTypeReference; GetClassTypeReference o = other as GetClassTypeReference;
return o != null && assembly == o.assembly && name == o.name && nameSpace == o.nameSpace && typeParameterCount == o.typeParameterCount; return o != null && assembly == o.assembly && fullTypeName == o.fullTypeName;
} }
} }
} }

2
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/KnownTypeCache.cs

@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (typeRef == null) if (typeRef == null)
return SpecialType.UnknownType; return SpecialType.UnknownType;
foreach (IAssembly asm in compilation.Assemblies) { foreach (IAssembly asm in compilation.Assemblies) {
var typeDef = asm.GetTypeDefinition(typeRef.Namespace, typeRef.Name, typeRef.TypeParameterCount); var typeDef = asm.GetTypeDefinition(new TopLevelTypeName(typeRef.Namespace, typeRef.Name, typeRef.TypeParameterCount));
if (typeDef != null) if (typeDef != null)
return typeDef; return typeDef;
} }

50
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/UnknownType.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Diagnostics;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{ {
@ -26,9 +27,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
[Serializable] [Serializable]
public class UnknownType : AbstractType, ITypeReference public class UnknownType : AbstractType, ITypeReference
{ {
readonly string namespaceName; readonly bool namespaceKnown;
readonly string name; readonly FullTypeName fullTypeName;
readonly int typeParameterCount;
/// <summary> /// <summary>
/// Creates a new unknown type. /// Creates a new unknown type.
@ -40,9 +40,24 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{ {
if (name == null) if (name == null)
throw new ArgumentNullException("name"); throw new ArgumentNullException("name");
this.namespaceName = namespaceName; this.namespaceKnown = namespaceName != null;
this.name = name; this.fullTypeName = new TopLevelTypeName(namespaceName ?? string.Empty, name, typeParameterCount);
this.typeParameterCount = typeParameterCount; }
/// <summary>
/// Creates a new unknown type.
/// </summary>
/// <param name="fullTypeName">Full name of the unknown type.</param>
public UnknownType(FullTypeName fullTypeName)
{
if (fullTypeName.Name == null) {
Debug.Assert(fullTypeName == default(FullTypeName));
this.namespaceKnown = false;
this.fullTypeName = new TopLevelTypeName(string.Empty, "?", 0);
} else {
this.namespaceKnown = true;
this.fullTypeName = fullTypeName;
}
} }
public override TypeKind Kind { public override TypeKind Kind {
@ -62,15 +77,19 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
public override string Name { public override string Name {
get { return name; } get { return fullTypeName.Name; }
} }
public override string Namespace { public override string Namespace {
get { return namespaceName ?? string.Empty; } get { return fullTypeName.TopLevelTypeName.Namespace; }
} }
public override string ReflectionName { public override string ReflectionName {
get { return "?"; } get { return namespaceKnown ? fullTypeName.ReflectionName : "?"; }
}
public override int TypeParameterCount {
get { return fullTypeName.TypeParameterCount; }
} }
public override bool? IsReferenceType { public override bool? IsReferenceType {
@ -79,14 +98,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public override int GetHashCode() public override int GetHashCode()
{ {
int hashCode = 0; return (namespaceKnown ? 812571 : 12651) ^ fullTypeName.GetHashCode();
unchecked {
if (namespaceName != null)
hashCode += 1000000007 * namespaceName.GetHashCode();
hashCode += 1000000009 * name.GetHashCode();
hashCode += 1000000021 * typeParameterCount.GetHashCode();
}
return hashCode;
} }
public override bool Equals(IType other) public override bool Equals(IType other)
@ -94,12 +106,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
UnknownType o = other as UnknownType; UnknownType o = other as UnknownType;
if (o == null) if (o == null)
return false; return false;
return this.namespaceName == o.namespaceName && this.name == o.name && this.typeParameterCount == o.typeParameterCount; return this.namespaceKnown == o.namespaceKnown && this.fullTypeName == o.fullTypeName;
} }
public override string ToString() public override string ToString()
{ {
return "[UnknownType " + this.FullName + "]"; return "[UnknownType " + fullTypeName.ReflectionName + "]";
} }
} }
} }

6
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs

@ -37,7 +37,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// the type arguments. /// the type arguments.
/// </remarks> /// </remarks>
[Serializable] [Serializable]
public sealed class ParameterizedType : IType public sealed class ParameterizedType : IType, ICompilationProvider
{ {
readonly ITypeDefinition genericType; readonly ITypeDefinition genericType;
readonly IType[] typeArguments; readonly IType[] typeArguments;
@ -57,8 +57,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
for (int i = 0; i < this.typeArguments.Length; i++) { for (int i = 0; i < this.typeArguments.Length; i++) {
if (this.typeArguments[i] == null) if (this.typeArguments[i] == null)
throw new ArgumentNullException("typeArguments[" + i + "]"); throw new ArgumentNullException("typeArguments[" + i + "]");
IResolved r = this.typeArguments[i] as IResolved; ICompilationProvider p = this.typeArguments[i] as ICompilationProvider;
if (r != null && r.Compilation != genericType.Compilation) if (p != null && p.Compilation != genericType.Compilation)
throw new InvalidOperationException("Cannot parameterize a type with type arguments from a different compilation."); throw new InvalidOperationException("Cannot parameterize a type with type arguments from a different compilation.");
} }
} }

12
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs

@ -56,17 +56,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
{ {
return type.ToTypeReference().Resolve(compilation.TypeResolveContext); return type.ToTypeReference().Resolve(compilation.TypeResolveContext);
} }
/// <summary>
/// Retrieves the specified type in this compilation.
/// Returns <see cref="SpecialType.UnknownType"/> if the type cannot be found in this compilation.
/// </summary>
[Obsolete("Use ReflectionHelper.ParseReflectionName(reflectionTypeName).Resolve(compilation.TypeResolveContext) instead. " +
"Make sure to read the ParseReflectionName() documentation for caveats.")]
public static IType FindType(this ICompilation compilation, string reflectionTypeName)
{
return ParseReflectionName(reflectionTypeName).Resolve(compilation.TypeResolveContext);
}
#endregion #endregion
#region Type.ToTypeReference() #region Type.ToTypeReference()
@ -218,6 +207,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <see cref="ITypeResolveContext.CurrentAssembly"/> first, and if the type is not found there, /// <see cref="ITypeResolveContext.CurrentAssembly"/> first, and if the type is not found there,
/// it will look in all other assemblies of the compilation. /// it will look in all other assemblies of the compilation.
/// </remarks> /// </remarks>
/// <seealso cref="FullTypeName(string)"/>
public static ITypeReference ParseReflectionName(string reflectionTypeName) public static ITypeReference ParseReflectionName(string reflectionTypeName)
{ {
if (reflectionTypeName == null) if (reflectionTypeName == null)

144
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TopLevelTypeName.cs

@ -0,0 +1,144 @@
// Copyright (c) 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 System.Text;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Holds the name of a top-level type.
/// This struct cannot refer to nested classes.
/// </summary>
[Serializable]
public struct TopLevelTypeName : IEquatable<TopLevelTypeName>
{
readonly string namespaceName;
readonly string name;
readonly int typeParameterCount;
public TopLevelTypeName(string namespaceName, string name, int typeParameterCount = 0)
{
if (namespaceName == null)
throw new ArgumentNullException("namespaceName");
if (name == null)
throw new ArgumentNullException("name");
this.namespaceName = namespaceName;
this.name = name;
this.typeParameterCount = typeParameterCount;
}
public TopLevelTypeName(string reflectionName)
{
int pos = reflectionName.LastIndexOf('.');
if (pos < 0) {
namespaceName = string.Empty;
name = reflectionName;
} else {
namespaceName = reflectionName.Substring(0, pos);
name = reflectionName.Substring(pos + 1);
}
name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount);
}
public string Namespace {
get { return namespaceName; }
}
public string Name {
get { return name; }
}
public int TypeParameterCount {
get { return typeParameterCount; }
}
public string ReflectionName {
get {
StringBuilder b = new StringBuilder();
if (!string.IsNullOrEmpty(namespaceName)) {
b.Append(namespaceName);
b.Append('.');
}
b.Append(name);
if (typeParameterCount > 0) {
b.Append('`');
b.Append(typeParameterCount);
}
return b.ToString();
}
}
public override string ToString()
{
return this.ReflectionName;
}
public override bool Equals(object obj)
{
return (obj is TopLevelTypeName) && Equals((TopLevelTypeName)obj);
}
public bool Equals(TopLevelTypeName other)
{
return this.namespaceName == other.namespaceName && this.name == other.name && this.typeParameterCount == other.typeParameterCount;
}
public override int GetHashCode()
{
return (name != null ? name.GetHashCode() : 0) ^ (namespaceName != null ? namespaceName.GetHashCode() : 0) ^ typeParameterCount;
}
public static bool operator ==(TopLevelTypeName lhs, TopLevelTypeName rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(TopLevelTypeName lhs, TopLevelTypeName rhs)
{
return !lhs.Equals(rhs);
}
}
[Serializable]
public sealed class TopLevelTypeNameComparer : IEqualityComparer<TopLevelTypeName>
{
public static readonly TopLevelTypeNameComparer Ordinal = new TopLevelTypeNameComparer(StringComparer.Ordinal);
public static readonly TopLevelTypeNameComparer OrdinalIgnoreCase = new TopLevelTypeNameComparer(StringComparer.OrdinalIgnoreCase);
public readonly StringComparer NameComparer;
public TopLevelTypeNameComparer(StringComparer nameComparer)
{
this.NameComparer = nameComparer;
}
public bool Equals(TopLevelTypeName x, TopLevelTypeName y)
{
return x.TypeParameterCount == y.TypeParameterCount
&& NameComparer.Equals(x.Name, y.Name)
&& NameComparer.Equals(x.Namespace, y.Namespace);
}
public int GetHashCode(TopLevelTypeName obj)
{
return NameComparer.GetHashCode(obj.Name) ^ NameComparer.GetHashCode(obj.Namespace) ^ obj.TypeParameterCount;
}
}
}

118
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TypeSystemExtensions.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary> /// <summary>
/// Contains extension methods for the type system. /// Contains extension methods for the type system.
/// </summary> /// </summary>
public static class ExtensionMethods public static class TypeSystemExtensions
{ {
#region GetAllBaseTypes #region GetAllBaseTypes
/// <summary> /// <summary>
@ -96,12 +96,31 @@ namespace ICSharpCode.NRefactory.TypeSystem
sealed class TypeClassificationVisitor : TypeVisitor sealed class TypeClassificationVisitor : TypeVisitor
{ {
internal bool isOpen; internal bool isOpen;
internal IEntity typeParameterOwner;
int typeParameterOwnerNestingLevel;
public override IType VisitTypeParameter(ITypeParameter type) public override IType VisitTypeParameter(ITypeParameter type)
{ {
isOpen = true; isOpen = true;
// If both classes and methods, or different classes (nested types)
// are involved, find the most specific one
int newNestingLevel = GetNestingLevel(type.Owner);
if (newNestingLevel > typeParameterOwnerNestingLevel) {
typeParameterOwner = type.Owner;
typeParameterOwnerNestingLevel = newNestingLevel;
}
return base.VisitTypeParameter(type); return base.VisitTypeParameter(type);
} }
static int GetNestingLevel(IEntity entity)
{
int level = 0;
while (entity != null) {
level++;
entity = entity.DeclaringTypeDefinition;
}
return level;
}
} }
/// <summary> /// <summary>
@ -126,6 +145,21 @@ namespace ICSharpCode.NRefactory.TypeSystem
return v.isOpen; return v.isOpen;
} }
/// <summary>
/// Gets the entity that owns the type parameters occurring in the specified type.
/// If both class and method type parameters are present, the method is returned.
/// Returns null if the specified type is closed.
/// </summary>
/// <seealso cref="IsOpen"/>
static IEntity GetTypeParameterOwner(IType type)
{
if (type == null)
throw new ArgumentNullException("type");
TypeClassificationVisitor v = new TypeClassificationVisitor();
type.AcceptVisitor(v);
return v.typeParameterOwner;
}
/// <summary> /// <summary>
/// Gets whether the type is unbound (is a generic type, but no type arguments were provided). /// Gets whether the type is unbound (is a generic type, but no type arguments were provided).
/// </summary> /// </summary>
@ -162,7 +196,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
throw new ArgumentNullException("compilation"); throw new ArgumentNullException("compilation");
if (type == null) if (type == null)
return null; return null;
return type.ToTypeReference().Resolve(compilation.TypeResolveContext); var compilationProvider = type as ICompilationProvider;
if (compilationProvider != null && compilationProvider.Compilation == compilation)
return type;
IEntity typeParameterOwner = GetTypeParameterOwner(type);
IEntity importedTypeParameterOwner = compilation.Import(typeParameterOwner);
if (importedTypeParameterOwner != null) {
return type.ToTypeReference().Resolve(new SimpleTypeResolveContext(importedTypeParameterOwner));
} else {
return type.ToTypeReference().Resolve(compilation.TypeResolveContext);
}
} }
/// <summary> /// <summary>
@ -392,28 +435,59 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endregion #endregion
#region IAssembly.GetTypeDefinition() #region IAssembly.GetTypeDefinition()
/// <summary>
/// Retrieves the specified type in this compilation.
/// Returns an <see cref="UnknownType"/> if the type cannot be found in this compilation.
/// </summary>
/// <remarks>
/// There can be multiple types with the same full name in a compilation, as a
/// full type name is only unique per assembly.
/// If there are multiple possible matches, this method will return just one of them.
/// When possible, use <see cref="IAssembly.GetTypeDefinition"/> instead to
/// retrieve a type from a specific assembly.
/// </remarks>
public static IType FindType(this ICompilation compilation, FullTypeName fullTypeName)
{
if (compilation == null)
throw new ArgumentNullException("compilation");
foreach (IAssembly asm in compilation.Assemblies) {
ITypeDefinition def = asm.GetTypeDefinition(fullTypeName);
if (def != null)
return def;
}
return new UnknownType(fullTypeName);
}
/// <summary> /// <summary>
/// Gets the type definition for the specified unresolved type. /// Gets the type definition for the specified unresolved type.
/// Returns null if the unresolved type does not belong to this assembly. /// Returns null if the unresolved type does not belong to this assembly.
/// </summary> /// </summary>
public static ITypeDefinition GetTypeDefinition(this IAssembly assembly, IUnresolvedTypeDefinition unresolved) public static ITypeDefinition GetTypeDefinition(this IAssembly assembly, FullTypeName fullTypeName)
{ {
if (assembly == null) if (assembly == null)
throw new ArgumentNullException("assembly"); throw new ArgumentNullException("assembly");
if (unresolved == null) TopLevelTypeName topLevelTypeName = fullTypeName.TopLevelTypeName;
ITypeDefinition typeDef = assembly.GetTypeDefinition(topLevelTypeName);
if (typeDef == null)
return null; return null;
if (unresolved.DeclaringTypeDefinition != null) { int typeParameterCount = topLevelTypeName.TypeParameterCount;
ITypeDefinition parentType = GetTypeDefinition(assembly, unresolved.DeclaringTypeDefinition); for (int i = 0; i < fullTypeName.NestingLevel; i++) {
if (parentType == null) string name = fullTypeName.GetNestedTypeName(i);
return null; typeParameterCount += fullTypeName.GetNestedTypeAdditionalTypeParameterCount(i);
foreach (var nestedType in parentType.NestedTypes) { typeDef = FindNestedType(typeDef, name, typeParameterCount);
if (nestedType.Name == unresolved.Name && nestedType.TypeParameterCount == unresolved.TypeParameters.Count) if (typeDef == null)
return nestedType; break;
} }
return null; return typeDef;
} else { }
return assembly.GetTypeDefinition(unresolved.Namespace, unresolved.Name, unresolved.TypeParameters.Count);
static ITypeDefinition FindNestedType(ITypeDefinition typeDef, string name, int typeParameterCount)
{
foreach (var nestedType in typeDef.NestedTypes) {
if (nestedType.Name == name && nestedType.TypeParameterCount == typeParameterCount)
return nestedType;
} }
return null;
} }
#endregion #endregion
@ -437,5 +511,19 @@ namespace ICSharpCode.NRefactory.TypeSystem
return reference.Resolve (compilation.TypeResolveContext); return reference.Resolve (compilation.TypeResolveContext);
} }
#endregion #endregion
#region IAssembly.GetTypeDefinition(string,string,int)
/// <summary>
/// Gets the type definition for a top-level type.
/// </summary>
/// <remarks>This method uses ordinal name comparison, not the compilation's name comparer.</remarks>
public static ITypeDefinition GetTypeDefinition(this IAssembly assembly, string namespaceName, string name, int typeParameterCount = 0)
{
if (assembly == null)
throw new ArgumentNullException ("assembly");
return assembly.GetTypeDefinition (new TopLevelTypeName (namespaceName, name, typeParameterCount));
}
#endregion
} }
} }
Loading…
Cancel
Save