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 @@ -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> ();
nodeStack.Push(this);
while (nodeStack.Count > 0) {
var curNode = nodeStack.Pop();
if (curNode is TypeDeclaration) {
yield return (TypeDeclaration)curNode;
if (curNode is TypeDeclaration || curNode is DelegateDeclaration) {
yield return (EntityDeclaration)curNode;
}
foreach (var child in curNode.Children) {
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);
}
}
}
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 @@ -669,8 +669,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (!(Char.IsWhiteSpace(prevCh) || allowedChars.IndexOf(prevCh) >= 0)) {
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;
token = GetPreviousToken(ref tokenIndex, false);
if (token == "class" || token == "interface" || token == "struct" || token == "enum" || token == "namespace") {
@ -688,7 +687,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -688,7 +687,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
// after these always follows a name
return null;
}
if (identifierStart == null && !string.IsNullOrEmpty(token) && !IsInsideCommentStringOrDirective() && (prevToken2 == ";" || prevToken2 == "{" || prevToken2 == "}")) {
char last = token [token.Length - 1];
if (char.IsLetterOrDigit(last) || last == '_' || token == ">") {
@ -708,7 +707,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -708,7 +707,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (n != null && n.Parent is AnonymousTypeCreateExpression) {
AutoSelect = false;
}
// Handle foreach (type name _
if (n is IdentifierExpression) {
var prev = n.GetPrevNode() as ForeachStatement;
@ -719,24 +718,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -719,24 +718,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
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$"
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);
if (result != null)
return result;
@ -777,7 +762,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -777,7 +762,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
}
}
if (n != null && n.Parent is ObjectCreateExpression) {
var invokeResult = ResolveExpression(n.Parent);
var mgr = invokeResult != null ? invokeResult.Item1 as ResolveResult : null;
@ -1147,6 +1132,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1147,6 +1132,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return wrapper.Result;
}
}
/* if (Unit != null && (node == null || node is TypeDeclaration)) {
var constructor = Unit.GetNodeAt<ConstructorDeclaration>(
location.Line,
@ -1192,6 +1178,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1192,6 +1178,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
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)) {
foreach (var variable in state.LocalVariables) {
if (variable.Region.IsInside(location.Line, location.Column - 1)) {
@ -1222,10 +1211,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1222,10 +1211,12 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return t.GetAllBaseTypeDefinitions().Any(bt => bt.Equals(attribute)) ? t : null;
};
}
AddTypesAndNamespaces(wrapper, state, node, typePred);
wrapper.Result.Add(factory.CreateLiteralCompletionData("global"));
if (node != null || state.CurrentTypeDefinition != null || isInGlobalDelegate) {
AddTypesAndNamespaces(wrapper, state, node, typePred);
wrapper.Result.Add(factory.CreateLiteralCompletionData("global"));
}
if (!(node is AstType)) {
if (currentMember != null || node is Expression) {
AddKeywords(wrapper, statementStartKeywords);
@ -1235,7 +1226,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1235,7 +1226,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
} else if (currentType != null) {
AddKeywords(wrapper, typeLevelKeywords);
} else {
AddKeywords(wrapper, globalLevelKeywords);
if (!isInGlobalDelegate)
AddKeywords(wrapper, globalLevelKeywords);
}
var prop = currentMember as IUnresolvedProperty;
if (prop != null && prop.Setter != null && prop.Setter.Region.IsInside(location)) {
@ -1253,7 +1245,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1253,7 +1245,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
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)) {
wrapper.AddCustom("var");
wrapper.AddCustom("dynamic");
@ -1342,7 +1336,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1342,7 +1336,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
}
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) {
bool isProtectedAllowed = true;
foreach (var member in def.GetMembers ()) {
@ -1791,8 +1787,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1791,8 +1787,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
if (hintType is ParameterizedType && hintType.TypeParameterCount == 1 && hintType.FullName == "System.Collections.Generic.IEnumerable") {
var arg = ((ParameterizedType)hintType).TypeArguments.FirstOrDefault();
var array = new ArrayTypeReference(arg.ToTypeReference(), 1).Resolve(ctx);
wrapper.AddType(array, amb.ConvertType(array));
if (arg.Kind != TypeKind.TypeParameter) {
var array = new ArrayType (ctx.Compilation, arg, 1);
wrapper.AddType(array, amb.ConvertType(array));
}
}
} else {
var hint = wrapper.AddType(hintType, DefaultCompletionString);
@ -2014,7 +2012,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2014,7 +2012,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
"delegate",
"Creates anonymous delegate.",
"delegate {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString
);
);
}
var sb = new StringBuilder("(");
var sbWithoutTypes = new StringBuilder("(");
@ -2026,10 +2024,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2026,10 +2024,10 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
sb.Append(", ");
sbWithoutTypes.Append(", ");
}
var convertedParameter = builder.ConvertParameter (delegateMethod.Parameters [k]);
var convertedParameter = builder.ConvertParameter(delegateMethod.Parameters [k]);
if (convertedParameter.ParameterModifier == ParameterModifier.Params)
convertedParameter.ParameterModifier = ParameterModifier.None;
sb.Append(convertedParameter.GetText (FormattingPolicy));
sb.Append(convertedParameter.GetText(FormattingPolicy));
sbWithoutTypes.Append(delegateMethod.Parameters [k].Name);
}
@ -2039,22 +2037,22 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2039,22 +2037,22 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
"delegate" + sb,
"Creates anonymous delegate.",
"delegate" + sb + " {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString
);
);
if (!completionList.Result.Any(data => data.DisplayText == sb.ToString())) {
completionList.AddCustom(
sb.ToString(),
"Creates typed lambda expression.",
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(
sbWithoutTypes.ToString(),
"Creates lambda expression.",
sbWithoutTypes + " => |" + (addSemicolon ? ";" : "")
);
);
}
/* TODO:Make factory method out of it.
// 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 @@ -2298,7 +2296,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var lookup = new MemberLookup(
ctx.CurrentTypeDefinition,
Compilation.MainAssembly
);
);
if (resolveResult is NamespaceResolveResult) {
var nr = (NamespaceResolveResult)resolveResult;
@ -2317,10 +2315,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2317,10 +2315,9 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
return namespaceContents.Result;
}
IType type = resolveResult.Type;
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();
@ -2354,7 +2351,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2354,7 +2351,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
resolveResult,
((IdentifierExpression)resolvedNode).Identifier,
out trr
)) {
)) {
if (currentMember != null && mrr.Member.IsStatic ^ currentMember.IsStatic) {
skipNonStaticMembers = true;
@ -2398,20 +2395,21 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2398,20 +2395,21 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (resolvedNode.Annotation<ObjectCreateExpression>() == null) {
//tags the created expression as part of an object create expression.
/*
var filteredList = new List<IMember>();
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) {
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) {
continue;
}
@ -2435,18 +2433,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2435,18 +2433,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (member.EntityType == EntityType.Operator) {
continue;
}
if (member.IsExplicitInterfaceImplementation) {
continue;
}
if (member.IsShadowing) {
filteredList.RemoveAll(m => m.Name == member.Name);
if (member is IMember) {
result.AddMember ((IMember)member);
} else {
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 @@ -2492,7 +2485,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return result.Result;
}
IEnumerable<ICompletionData> CreateCaseCompletionData(TextLocation location)
{
var unit = ParseStub("a: break;");

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

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

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

@ -35,6 +35,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -35,6 +35,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
{
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 CreateDelegateDataProvider (int startOffset, IType type);

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

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

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

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

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

@ -476,7 +476,6 @@ @@ -476,7 +476,6 @@
<Compile Include="Refactoring\NamingHelper.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\ConvertToInitializerAction.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\StatementsToInitializerConverter.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\InitializerPath.cs" />
<Compile Include="Refactoring\CodeActions\MoveToOuterScopeAction.cs" />
<Compile Include="Refactoring\CodeIssues\VariableDeclaredInWideScopeIssue.cs" />
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\ParameterCanBeDemotedIssue.cs" />
@ -503,6 +502,7 @@ @@ -503,6 +502,7 @@
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\IsArrayTypeCriterion.cs" />
<Compile Include="Refactoring\CodeIssues\ParameterCanBeDemotedIssue\SupportsIndexingCriterion.cs" />
<Compile Include="Refactoring\CodeIssues\RedundantWhereWithPredicateIssue.cs" />
<Compile Include="Refactoring\CodeActions\ConvertToInitializer\AccessPath.cs" />
</ItemGroup>
<ItemGroup>
<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 @@ -54,7 +54,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Condition = new BinaryOperatorExpression (new IdentifierExpression (parameter.Name), BinaryOperatorType.Equality, new NullReferenceExpression ()),
TrueStatement = new ThrowStatement (new ObjectCreateExpression (context.CreateShortType("System", "ArgumentNullException"), new PrimitiveExpression (parameter.Name)))
};
System.Console.WriteLine(bodyStatement.StartLocation +"/" + bodyStatement.EndLocation);
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; @@ -32,25 +32,16 @@ using System.Linq;
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>();
}
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 currentResolveResult = resolveResult;
do {
@ -59,42 +50,38 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -59,42 +50,38 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
memberPath.Add(memberResolveResult.Member);
currentResolveResult = memberResolveResult.TargetResult;
} else if (currentResolveResult is LocalResolveResult) {
// This is the root variable
var localResolveResult = (LocalResolveResult)currentResolveResult;
memberPath.Reverse();
initializerPath = new InitializerPath(localResolveResult.Variable) {
return new AccessPath(localResolveResult.Variable) {
MemberPath = memberPath
};
break;
} else if (currentResolveResult is ThisResolveResult) {
break;
} else {
// Unsupported path
return null;
}
} while (currentResolveResult != null);
if (initializerPath == null) {
// This path is rooted at a member
memberPath.Reverse();
initializerPath = new InitializerPath(memberPath [0]) {
MemberPath = memberPath.Skip(1).ToList()
};
}
return initializerPath;
memberPath.Reverse();
return new AccessPath(null) {
MemberPath = memberPath
};
}
public InitializerPath GetParentPath()
public AccessPath GetParentPath()
{
if (MemberPath.Count < 1)
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()
};
}
public bool IsSubPath(InitializerPath other)
public bool IsSubPath(AccessPath other)
{
if (!other.anchor.Equals(anchor))
if (!object.Equals(other.VariableRoot, VariableRoot))
return false;
if (MemberPath.Count <= other.MemberPath.Count)
return false;
@ -105,22 +92,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -105,22 +92,19 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return true;
}
object anchor;
public IVariable VariableRoot { get; set; }
public IVariable VariableRoot {
get { return anchor as IVariable; }
}
public IMember MemberRoot {
get { return anchor as IMember; }
public int PartCount {
get {
return MemberPath.Count + (VariableRoot == null ? 0 : 1);
}
}
public string RootName {
get {
if (anchor is IMember)
return (anchor as IMember).Name;
else
return (anchor as IVariable).Name;
if (VariableRoot != null)
return VariableRoot.Name;
return MemberPath.First().Name;
}
}
@ -128,12 +112,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -128,12 +112,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override bool Equals(object obj)
{
if (obj.GetType() != typeof(InitializerPath))
if (obj.GetType() != typeof(AccessPath))
return false;
var other = (InitializerPath)obj;
var other = (AccessPath)obj;
if (!object.Equals(anchor, other.anchor))
if (!object.Equals(VariableRoot, other.VariableRoot))
return false;
if (MemberPath.Count != other.MemberPath.Count)
@ -148,29 +132,28 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -148,29 +132,28 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public override int GetHashCode()
{
int hash = anchor.GetHashCode();
int hash = VariableRoot != null ? VariableRoot.GetHashCode() : 37;
foreach (var member in MemberPath)
hash ^= member.GetHashCode();
hash ^= 31 * member.GetHashCode();
return hash;
}
public static bool operator==(InitializerPath left, InitializerPath right)
public static bool operator==(AccessPath left, AccessPath 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);
}
public override string ToString()
{
if (MemberPath.Count > 0)
return string.Format("[InitializerPath: {0}.{1}]", RootName,
string.Join(".", MemberPath.Select<IMember, string>(member => member.Name)));
else
return string.Format("[InitializerPath: {0}]", RootName);
string memberPathString = string.Join(".", MemberPath.Select<IMember, string>(member => member.Name));
if (VariableRoot == null)
return string.Format("[AccessPath: {0}]", memberPathString);
return string.Format("[AccessPath: {0}.{1}]", VariableRoot.Name, memberPathString);
}
}

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

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

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

@ -29,6 +29,7 @@ using System.Collections.Generic; @@ -29,6 +29,7 @@ using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.PatternMatching;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -62,14 +63,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -62,14 +63,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var resolveResult = ctx.Resolve (assignmentExpression.Left);
var memberResolveResult = resolveResult as MemberResolveResult;
if (memberResolveResult != null) {
if (!(memberResolveResult.Member is IField))
var memberResolveResult2 = ctx.Resolve (assignmentExpression.Right) as MemberResolveResult;
if (memberResolveResult2 == null || !AreEquivalent(memberResolveResult, memberResolveResult2))
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) {
if (!assignmentExpression.Left.Match (assignmentExpression.Right).Success)
return;
@ -89,6 +85,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -89,6 +85,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
AddIssue (node, ctx.TranslateString ("CS1717:Assignment made to same variable"),
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 @@ -79,7 +79,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
if (resolveResult == null) {
return;
}
if (resolveResult.Member.Name != "ToString") {
var member = resolveResult.Member;
if (member.Name != "ToString" || member.Parameters.Count != 0) {
return;
}
AddRedundantToStringIssue(memberExpression, invocationExpression);

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

@ -28,6 +28,7 @@ using System.Collections.Generic; @@ -28,6 +28,7 @@ using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -73,17 +74,45 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -73,17 +74,45 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var invocationExpr = memberRefExpr.Parent as InvocationExpression;
if (invocationExpr != null && invocationExpr.Target == memberRefExpr) {
var invocationResolveResult = ctx.Resolve (invocationExpr) as InvocationResolveResult;
if (invocationResolveResult != null)
if (invocationResolveResult != null) {
return invocationResolveResult.Member.DeclaringType;
}
} else {
var memberResolveResult = ctx.Resolve (memberRefExpr) as MemberResolveResult;
if (memberResolveResult != null)
if (memberResolveResult != null) {
return memberResolveResult.Member.DeclaringType;
}
}
}
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)
{
AddIssue (start, end, ctx.TranslateString ("Remove redundant type cast"),
@ -94,9 +123,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -94,9 +123,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
while (typeCastNode.Parent != null && typeCastNode.Parent is ParenthesizedExpression)
typeCastNode = (Expression)typeCastNode.Parent;
var expectedType = GetExpectedType (typeCastNode);
var exprType = ctx.Resolve (expr).Type;
if (expectedType.Kind == TypeKind.Interface && IsExplicitImplementation (exprType, expectedType, typeCastNode))
return;
if (exprType.GetAllBaseTypes ().Any (t => t.Equals(expectedType)))
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 @@ -41,47 +41,76 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public class StringIsNullOrEmptyIssue : ICodeIssueProvider
{
static readonly Pattern pattern = new Choice {
// str == null || str == ""
// str == null || str == ""
// str == null || str.Length == 0
new BinaryOperatorExpression (
PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ()),
PatternHelper.CommutativeOperator (new AnyNode ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ()),
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.Length == 0 || str == null
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,
PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.Equality, new NullReferenceExpression ())
),
)
};
static readonly Pattern negPattern = new Choice {
// str != null && str != ""
// str != null && str != ""
// str != null && str.Length != 0
new BinaryOperatorExpression (
PatternHelper.CommutativeOperator(new AnyNode ("str"), BinaryOperatorType.InEquality, new NullReferenceExpression ()),
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.Length != 0 && str != null
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,
PatternHelper.CommutativeOperator(new Backreference ("str"), BinaryOperatorType.InEquality, new NullReferenceExpression ())
),
)
};
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{
return new GatherVisitor(context, this).GetIssues();
return new GatherVisitor(context).GetIssues();
}
class GatherVisitor : GatherVisitorBase
{
readonly StringIsNullOrEmptyIssue inspector;
public GatherVisitor (BaseRefactoringContext ctx, StringIsNullOrEmptyIssue inspector) : base (ctx)
public GatherVisitor (BaseRefactoringContext ctx) : base (ctx)
{
this.inspector = inspector;
}
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 @@ -88,14 +88,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var path = GetPath(rootNode, deepestCommonAncestor);
// 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
var pathToCheck = path.Skip(1).ToList();
var firstInitializerChangeNode = GetFirstInitializerChange(variableDeclarationStatement, pathToCheck, variableInitializer.Initializer);
if (firstInitializerChangeNode != null) {
// The initializer and usage nodes may not be in the same path, so merge them
// instead of just making a path to firstInitializerChange
// The node changing the initializer expression may not be on the path
// 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 deepestCommonIndex = GetLowestCommonAncestorIndex(path, pathToChange);
anchorNode = pathToChange [deepestCommonIndex + 1];
@ -109,9 +110,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -109,9 +110,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
anchorNode = firstBlackListedNode;
}
// Get the parent statement
while (anchorNode != null && !(anchorNode is Statement))
anchorNode = anchorNode.Parent;
anchorNode = GetInsertionPoint(anchorNode);
if (anchorNode != null && anchorNode != rootNode && anchorNode.Parent != rootNode) {
AddIssue(variableDeclarationStatement, context.TranslateString("Variable could be moved to a nested scope"),
@ -119,6 +118,31 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -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)
{
if (identifiers.Count > 1) {

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

@ -25,6 +25,8 @@ @@ -25,6 +25,8 @@
// THE SOFTWARE.
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
@ -51,6 +53,24 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -51,6 +53,24 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
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)
{
base.VisitParameterDeclaration (parameterDeclaration);

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

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

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

@ -152,6 +152,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -152,6 +152,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
text += Options.EolMarker;
InsertText(startOffset, text);
output.RegisterTrackedSegments(this, startOffset);
CorrectFormatting (node, insertNode);
}
public void InsertAfter(AstNode node, AstNode insertNode)
@ -164,6 +165,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -164,6 +165,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var insertOffset = GetCurrentOffset(node.EndLocation);
InsertText(insertOffset, text);
output.RegisterTrackedSegments(this, insertOffset);
CorrectFormatting (node, insertNode);
}
public void AddTo(BlockStatement bodyStatement, AstNode insertNode)
@ -172,6 +174,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -172,6 +174,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
var output = OutputNode(1 + GetIndentLevelAt(startOffset), insertNode, true);
InsertText(startOffset, output.Text);
output.RegisterTrackedSegments(this, startOffset);
CorrectFormatting (null, insertNode);
}
public virtual Task Link (params AstNode[] nodes)
@ -196,6 +199,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -196,6 +199,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
output.TrimStart ();
Replace (startOffset, segment.Length, output.Text);
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);

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

@ -142,17 +142,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -142,17 +142,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return astType;
}
public AstType ConvertType(string ns, string name, int typeParameterCount = 0)
public AstType ConvertType(FullTypeName fullTypeName)
{
if (resolver != null) {
foreach (var asm in resolver.Compilation.Assemblies) {
var def = asm.GetTypeDefinition(ns, name, typeParameterCount);
var def = asm.GetTypeDefinition(fullTypeName);
if (def != null) {
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)
@ -601,7 +611,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -601,7 +611,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
if (GenerateBody) {
return new BlockStatement {
new ThrowStatement(new ObjectCreateExpression(ConvertType("System", "NotImplementedException")))
new ThrowStatement(new ObjectCreateExpression(ConvertType(new TopLevelTypeName("System", "NotImplementedException", 0))))
};
} else {
return BlockStatement.Null;

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

@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@ -141,6 +140,90 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -141,6 +140,90 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#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
sealed class LookupGroup
{

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

@ -58,7 +58,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -58,7 +58,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
node = node.Parent;
} else if (node.NodeType == NodeType.Token) {
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,
// so we need to resolve it when hovering over the '[' or ']'.
// 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 @@ -51,6 +51,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return resolver.ResolveAlias(identifier);
}
public override IType ResolveType(CSharpResolver resolver)
{
// alias cannot refer to types
return SpecialType.UnknownType;
}
public override string ToString()
{
return identifier + "::";

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

@ -181,9 +181,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -181,9 +181,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
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);
if (dict != null) {
@ -192,9 +192,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -192,9 +192,9 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
// Always use the ordinal comparer for the main dictionary so that partial classes
// get merged correctly.
// The compilation's comparer will be used for the per-namespace dictionaries.
var comparer = FullNameAndTypeParameterCountComparer.Ordinal;
var comparer = TopLevelTypeNameComparer.Ordinal;
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);
return LazyInit.GetOrSet(ref this.typeDict, dict);
}
@ -205,11 +205,10 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -205,11 +205,10 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
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;
if (GetTypes().TryGetValue(key, out def))
if (GetTypes().TryGetValue(topLevelTypeName, out def))
return def;
else
return null;
@ -233,7 +232,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -233,7 +232,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
readonly string fullName;
readonly string name;
internal readonly List<NS> childNamespaces = new List<NS>();
internal readonly Dictionary<FullNameAndTypeParameterCount, ITypeDefinition> types;
internal readonly Dictionary<TopLevelTypeName, ITypeDefinition> types;
public NS(CSharpAssembly assembly)
{
@ -243,7 +242,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -243,7 +242,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
// 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 (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 @@ -254,7 +253,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
this.fullName = fullName;
this.name = name;
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 {
@ -290,7 +289,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -290,7 +289,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
}
}
ICompilation IResolved.Compilation {
ICompilation ICompilationProvider.Compilation {
get { return assembly.Compilation; }
}
@ -310,15 +309,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -310,15 +309,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount)
{
var key = new TopLevelTypeName(fullName, name, typeParameterCount);
if (types != null) {
var key = new FullNameAndTypeParameterCount(fullName, name, typeParameterCount);
ITypeDefinition typeDef;
if (types.TryGetValue(key, out typeDef))
return typeDef;
else
return null;
} 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; @@ -22,6 +22,7 @@ using System.Collections.ObjectModel;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.TypeSystem
@ -58,7 +59,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -58,7 +59,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
}
public IList<ITypeReference> TypeArguments {
get { return new ReadOnlyCollection<ITypeReference>(typeArguments); }
get { return typeArguments; }
}
public NameLookupMode LookupMode {
get { return lookupMode; }
}
/// <summary>
@ -67,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -67,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
/// </summary>
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)
@ -86,6 +91,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -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()
{
if (typeArguments.Count == 0)

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

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

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

@ -23,6 +23,7 @@ using System.Collections.ObjectModel; @@ -23,6 +23,7 @@ using System.Collections.ObjectModel;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.TypeSystem
@ -51,7 +52,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -51,7 +52,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
}
public IList<ITypeReference> TypeArguments {
get { return new ReadOnlyCollection<ITypeReference>(typeArguments); }
get { return typeArguments; }
}
public NameLookupMode LookupMode {
get { return lookupMode; }
}
/// <summary>
@ -69,6 +74,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -69,6 +74,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
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()
{
if (typeArguments.Count == 0)

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

@ -34,6 +34,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -34,6 +34,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
/// </summary>
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>
/// Returns the namespace that is referenced; or null if no such namespace is found.
/// </summary>
@ -43,15 +48,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -43,15 +48,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
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)
{
// 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 @@ -50,8 +50,7 @@ class TestClass
public void F()
{
try {
}
catch (System.Exception e) {
} catch (System.Exception e) {
}
}
}");
@ -107,8 +106,7 @@ class TestClass @@ -107,8 +106,7 @@ class TestClass
public void F()
{
try {
}
catch (Exception e) {
} catch (Exception e) {
}
}
}");

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

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

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

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

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

@ -47,8 +47,8 @@ class A @@ -47,8 +47,8 @@ class A
void F ()
{
System.Action<int, int> = delegate (int i1, int i2) {
System.Console.WriteLine (i1);
};
System.Console.WriteLine (i1);
};
}
}");
}
@ -69,8 +69,8 @@ class A @@ -69,8 +69,8 @@ class A
void F ()
{
System.Action<int, int> = delegate (int i1, int i2) {
System.Console.WriteLine (i1);
};
System.Console.WriteLine (i1);
};
}
}");
}
@ -91,8 +91,8 @@ class A @@ -91,8 +91,8 @@ class A
void F ()
{
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 @@ -61,11 +61,9 @@ class TestClass
{
if (a == 0) {
return 0;
} else
if (a == 1 || a == 2) {
} else if (a == 1 || a == 2) {
return 1;
} else
if (a == 3 || a == 4 || a == 5) {
} else if (a == 3 || a == 4 || a == 5) {
return 1;
} else {
return 2;
@ -101,11 +99,9 @@ class TestClass @@ -101,11 +99,9 @@ class TestClass
{
if (a == 0) {
return 0;
} else
if (a == 1 || a == 2) {
} else if (a == 1 || a == 2) {
return 1;
} else
if (a == 3 || a == 4 || a == 5) {
} else if (a == 3 || a == 4 || a == 5) {
return 1;
}
}
@ -142,10 +138,8 @@ class TestClass @@ -142,10 +138,8 @@ class TestClass
{
if (a == 0) {
int b = 1;
} else
if (a == 1 || a == 2) {
} else
if (a == 3 || a == 4 || a == 5) {
} else if (a == 1 || a == 2) {
} else if (a == 3 || a == 4 || a == 5) {
} else {
}
}
@ -176,8 +170,7 @@ class TestClass @@ -176,8 +170,7 @@ class TestClass
{
if (a == 0) {
return 0;
} else
if (a == (1 == 1 ? 1 : 2)) {
} else if (a == (1 == 1 ? 1 : 2)) {
return 1;
} else {
return 2;

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

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

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

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

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

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

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

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

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

@ -100,7 +100,8 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions @@ -100,7 +100,8 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions
" void Test ()" + Environment.NewLine +
" {" + 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 +
"}", result);
}

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

@ -29,6 +29,7 @@ @@ -29,6 +29,7 @@
using System;
using NUnit.Framework;
using System.Diagnostics;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
{
@ -1345,5 +1346,80 @@ public class Foo @@ -1345,5 +1346,80 @@ public class Foo
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 @@ -74,6 +74,9 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
#region ICompletionData implementation
public void AddOverload (ICompletionData data)
{
if (overloadedData.Count == 0)
overloadedData.Add (this);
overloadedData.Add (data);
}
public CompletionCategory CompletionCategory {
@ -103,13 +106,17 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion @@ -103,13 +106,17 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
public bool HasOverloads {
get {
throw new NotImplementedException ();
return overloadedData.Count > 0;
}
}
List<ICompletionData> overloadedData = new List<ICompletionData> ();
public System.Collections.Generic.IEnumerable<ICompletionData> OverloadedData {
get;
set;
get {
return overloadedData;
}
set {
throw new NotImplementedException ();
}
}
#endregion
@ -5415,5 +5422,59 @@ public class FooBar @@ -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 @@ -187,6 +187,20 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
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 @@ -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)
{
return new Provider () {

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

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

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

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

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

@ -127,7 +127,7 @@ class TestClass @@ -127,7 +127,7 @@ class TestClass
}";
Test<AssignmentMadeToSameVariableIssue> (input, 2, output);
}
[Test]
public void TestNoIssue ()
{
@ -146,6 +146,69 @@ class TestClass @@ -146,6 +146,69 @@ class TestClass
this.a = a;
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);
}

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

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

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

@ -39,7 +39,8 @@ class TestClass @@ -39,7 +39,8 @@ class TestClass
{
void TestMethod (" + variableType + @" x)
{
if (x is " + providedType + @") ;
if (x is " + providedType + @")
;
}
}";
var output = @"
@ -47,7 +48,8 @@ class TestClass @@ -47,7 +48,8 @@ class TestClass
{
void TestMethod (" + variableType + @" x)
{
if (x != null) ;
if (x != null)
;
}
}";
Test<ExpressionIsAlwaysOfProvidedTypeIssue> (input, 1, output);
@ -73,7 +75,8 @@ class TestClass @@ -73,7 +75,8 @@ class TestClass
{
void TestMethod<T> (T x) where T : TestClass
{
if (x is TestClass) ;
if (x is TestClass)
;
}
}";
var output = @"
@ -81,7 +84,8 @@ class TestClass @@ -81,7 +84,8 @@ class TestClass
{
void TestMethod<T> (T x) where T : TestClass
{
if (x != null) ;
if (x != null)
;
}
}";
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 @@ -59,6 +59,9 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
}
bool pass = expectedOutput == ctx.Text;
if (!pass) {
Console.WriteLine ("expected:");
Console.WriteLine (expectedOutput);
Console.WriteLine ("got:");
Console.WriteLine (ctx.Text);
}
Assert.AreEqual (expectedOutput, ctx.Text);

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

@ -43,6 +43,36 @@ class TestClass { @@ -43,6 +43,36 @@ class TestClass {
}";
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]
public void TestUsedParameter ()

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

@ -76,6 +76,23 @@ class Foo @@ -76,6 +76,23 @@ class Foo
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]
public void StringTarget ()
{
@ -123,7 +140,7 @@ class Foo @@ -123,7 +140,7 @@ class Foo
{
void Bar (int i)
{
string s = string.Format(""{0}"", i);
string s = string.Format (""{0}"", i);
}
}");
}
@ -150,7 +167,7 @@ class Foo @@ -150,7 +167,7 @@ class Foo
void Bar (int i)
{
string format = ""{0}"";
string s = string.Format(format, i);
string s = string.Format (format, i);
}
}");
}
@ -179,7 +196,7 @@ class Foo @@ -179,7 +196,7 @@ class Foo
{
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)
@ -212,7 +229,7 @@ class Foo @@ -212,7 +229,7 @@ class Foo
{
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)
@ -244,8 +261,8 @@ class Foo @@ -244,8 +261,8 @@ class Foo
void Bar (int i)
{
var w = new System.IO.StringWriter();
w.Write(i);
w.WriteLine(i);
w.Write (i);
w.WriteLine (i);
}
}");
}

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

@ -146,5 +146,29 @@ class TestClass @@ -146,5 +146,29 @@ class TestClass
}";
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 @@ -46,7 +46,7 @@ class C
{
void Main()
{
B.F();
B.F ();
}
}";
TestRefactoringContext context;
@ -64,7 +64,7 @@ class C @@ -64,7 +64,7 @@ class C
{
void Main()
{
A.F();
A.F ();
}
}"
);
@ -181,7 +181,7 @@ class D @@ -181,7 +181,7 @@ class D
{
void Main()
{
A.B.F();
A.B.F ();
}
}"
);
@ -205,7 +205,7 @@ namespace Second @@ -205,7 +205,7 @@ namespace Second
{
void Main()
{
B.F();
B.F ();
}
}
}";
@ -229,7 +229,7 @@ namespace Second @@ -229,7 +229,7 @@ namespace Second
{
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 @@ -410,7 +410,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
}
}");
}
[Test]
public void TestInspectorCaseSN8 ()
{
@ -422,7 +422,39 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues @@ -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;
var issues = GetIssues (new StringIsNullOrEmptyIssue (), input, out context);
Assert.AreEqual (1, issues.Count);
@ -433,6 +465,38 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues @@ -433,6 +465,38 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues
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 @@ -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 { @@ -217,7 +217,7 @@ namespace OtherNS {
public void AmbiguousType()
{
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 @@ -397,6 +397,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public void ImplicitLongConstantExpressionConversion()
{
Assert.IsFalse(IntegerLiteralConversion(0L, typeof(int)));
Assert.IsFalse(IntegerLiteralConversion(0L, typeof(short)));
Assert.IsTrue(IntegerLiteralConversion(0L, typeof(long)));
Assert.IsTrue(IntegerLiteralConversion(0L, typeof(ulong)));
@ -508,8 +509,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -508,8 +509,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
) } ) }));
ICompilation compilation = TypeSystemHelper.CreateCompilation(a, b);
ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a);
ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b);
ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a.FullTypeName);
ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b.FullTypeName);
IType type1 = new ParameterizedType(resolvedB, new [] { compilation.FindType(KnownTypeCode.Double) });
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 @@ -44,6 +44,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
CSharpUnresolvedFile unresolvedFile = syntaxTree.ToTypeSystem();
project = project.AddOrUpdateFiles(unresolvedFile);
compilation = project.CreateCompilation();
lookup = new MemberLookup(null, compilation.MainAssembly);
return unresolvedFile;
}
@ -61,7 +62,7 @@ class Derived : Middle { @@ -61,7 +62,7 @@ class Derived : Middle {
public override void Method() {}
}";
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;
Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count());
@ -88,7 +89,7 @@ class Derived : Base<int> { @@ -88,7 +89,7 @@ class Derived : Base<int> {
public override void Method(string a) {}
}";
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;
Assert.AreEqual(2, rr.MethodsGroupedByDeclaringType.Count());
@ -116,7 +117,7 @@ class Derived : Base { @@ -116,7 +117,7 @@ class Derived : Base {
public override void Method<S>(S a) {}
}";
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;
Assert.AreEqual(1, rr.MethodsGroupedByDeclaringType.Count());
@ -456,5 +457,37 @@ class TestClass { @@ -456,5 +457,37 @@ class TestClass {
var mrr = Resolve<MemberResolveResult>(program);
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 @@ -59,7 +59,7 @@ namespace ICSharpCode.NRefactory.Documentation
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]

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

@ -48,6 +48,9 @@ namespace ICSharpCode.NRefactory.CSharp.FormattingTests @@ -48,6 +48,9 @@ namespace ICSharpCode.NRefactory.CSharp.FormattingTests
expectedOutput = NormalizeNewlines(expectedOutput);
IDocument doc = GetResult(policy, input, mode);
if (expectedOutput != doc.Text) {
Console.WriteLine ("expected:");
Console.WriteLine (expectedOutput);
Console.WriteLine ("got:");
Console.WriteLine (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 { @@ -83,7 +83,7 @@ namespace System.Collections.Generic {
ITypeDefinition Resolve(IUnresolvedTypeDefinition typeDef)
{
return compilation.MainAssembly.GetTypeDefinition(typeDef);
return typeDef.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition();
}
[Test]
@ -135,8 +135,7 @@ namespace System.Collections.Generic { @@ -135,8 +135,7 @@ namespace System.Collections.Generic {
// class C : C {}
var c = new DefaultUnresolvedTypeDefinition(string.Empty, "C");
c.BaseTypes.Add(c);
compilation = TypeSystemHelper.CreateCompilation(c);
ITypeDefinition resolvedC = Resolve(c);
ITypeDefinition resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
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 @@ -31,8 +31,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
public void EmptyClassHasToString()
{
DefaultUnresolvedTypeDefinition c = new DefaultUnresolvedTypeDefinition(string.Empty, "C");
var compilation = TypeSystemHelper.CreateCompilation(c);
Assert.AreEqual("System.Object.ToString", compilation.MainAssembly.GetTypeDefinition(c).GetMethods(m => m.Name == "ToString").Single().FullName);
var resolvedC = TypeSystemHelper.CreateCompilationAndResolve(c);
Assert.AreEqual("System.Object.ToString", resolvedC.GetMethods(m => m.Name == "ToString").Single().FullName);
}
[Test]
@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
c.BaseTypes.Add(b2);
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());
// Test that there's only one copy of ToString():
Assert.AreEqual(1, resolvedC.GetMethods(m => m.Name == "ToString").Count());
@ -91,8 +91,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -91,8 +91,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
a.NestedTypes.Add(b);
var compilation = TypeSystemHelper.CreateCompilation(a, b);
ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a);
ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b);
ITypeDefinition resolvedA = compilation.MainAssembly.GetTypeDefinition(a.FullTypeName);
ITypeDefinition resolvedB = compilation.MainAssembly.GetTypeDefinition(b.FullTypeName);
// A<> gets self-parameterized, B<> stays unbound
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 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
@ -36,7 +37,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -36,7 +37,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
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
// from one type parameter to another.
Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType);
@ -54,7 +55,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -54,7 +55,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
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
// from one type parameter to another.
Assert.AreEqual(true, resolvedC.TypeParameters[0].IsReferenceType);
@ -73,11 +74,45 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -73,11 +74,45 @@ namespace ICSharpCode.NRefactory.TypeSystem
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[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[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 @@ -44,5 +44,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
pc = pc.AddAssemblyReferences(new [] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore });
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 @@ -332,4 +332,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
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 @@ -137,8 +137,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
ParameterizedType crt = (ParameterizedType)rt.ReferencedType;
Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName);
Assert.AreEqual("System.String", crt.TypeArguments[0].FullName);
// ? for NUnit.TestAttribute (because that assembly isn't in ctx)
Assert.AreEqual("System.Collections.Generic.IList`1[[?]]", crt.TypeArguments[1].ReflectionName);
// we know the name for TestAttribute, but not necessarily the namespace, as NUnit is not in the compilation
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]
@ -1208,5 +1213,18 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1208,5 +1213,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
var method = type.GetMethods ().Single (m => m.Name == "Foo");
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 @@ -51,7 +51,7 @@ namespace ICSharpCode.NRefactory.Documentation
foreach (var asm in assemblies) {
if (asm == null)
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++) {
int tpc = (j == parts.Length - 1 ? typeParameterCount : 0);
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 @@ @@ -137,7 +137,8 @@
<Compile Include="TypeSystem\DefaultSolutionSnapshot.cs" />
<Compile Include="TypeSystem\DomRegion.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\IAssembly.cs" />
<Compile Include="TypeSystem\IAttribute.cs" />
@ -223,6 +224,7 @@ @@ -223,6 +224,7 @@
<Compile Include="TypeSystem\ProjectReference.cs" />
<Compile Include="TypeSystem\ReflectionNameParseException.cs" />
<Compile Include="TypeSystem\SimpleTypeResolveContext.cs" />
<Compile Include="TypeSystem\TopLevelTypeName.cs" />
<Compile Include="TypeSystem\TypeKind.cs" />
<Compile Include="TypeSystem\TypeVisitor.cs" />
<Compile Include="TypeSystem\IVariable.cs" />
@ -284,4 +286,4 @@ @@ -284,4 +286,4 @@
</None>
</ItemGroup>
<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 @@ -25,7 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Represents an array type.
/// </summary>
public sealed class ArrayType : TypeWithElementType
public sealed class ArrayType : TypeWithElementType, ICompilationProvider
{
readonly int dimensions;
readonly ICompilation compilation;
@ -38,12 +38,20 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -38,12 +38,20 @@ namespace ICSharpCode.NRefactory.TypeSystem
throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive");
this.compilation = compilation;
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 {
get { return TypeKind.Array; }
}
public ICompilation Compilation {
get { return compilation; }
}
public int Dimensions {
get { return dimensions; }
}

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

@ -190,7 +190,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -190,7 +190,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
name = interningProvider.Intern(name);
var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Scope), ns, name, typeParameterCount);
typeRef = interningProvider.Intern(typeRef);
var key = new FullNameAndTypeParameterCount(ns, name, typeParameterCount);
var key = new TopLevelTypeName(ns, name, typeParameterCount);
currentAssembly.AddTypeForwarder(key, typeRef);
}
}
@ -227,6 +227,14 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -227,6 +227,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
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();
var result = this.currentAssembly;
@ -515,7 +523,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -515,7 +523,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
#region DllImportAttribute
if (methodDefinition.HasPInvokeInfo) {
if (methodDefinition.HasPInvokeInfo && methodDefinition.PInvokeInfo != null) {
PInvokeInfo info = methodDefinition.PInvokeInfo;
var dllImport = new DefaultUnresolvedAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String });
dllImport.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, info.Module.Name));
@ -1785,6 +1793,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1785,6 +1793,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
get { return cecilTypeDef.FullName; }
}
public FullTypeName FullTypeName {
get {
return new TopLevelTypeName(namespaceName, this.Name, typeParameters.Count);
}
}
public TypeKind Kind {
get { return kind; }
}
@ -1876,7 +1890,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1876,7 +1890,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
throw new ArgumentNullException("context");
if (context.CurrentAssembly == null)
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);
}

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

@ -0,0 +1,313 @@ @@ -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 @@ -69,7 +69,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Represents an assembly.
/// </summary>
public interface IAssembly : IResolved
public interface IAssembly : ICompilationProvider
{
/// <summary>
/// Gets the original unresolved assembly.
@ -115,7 +115,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -115,7 +115,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// Gets the type definition for a top-level type.
/// </summary>
/// <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>
/// 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 @@ -37,6 +37,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Gets the list of all assemblies in the compilation.
/// </summary>
/// <remarks>
/// This main assembly is the first entry in the list.
/// </remarks>
IList<IAssembly> Assemblies { get; }
/// <summary>
@ -69,8 +72,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -69,8 +72,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
CacheManager CacheManager { get; }
}
public interface IResolved
public interface ICompilationProvider
{
/// <summary>
/// Gets the parent compilation.
/// This property never returns null.
/// </summary>
ICompilation Compilation { get; }
}
}

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

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

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

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

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

@ -30,6 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -30,6 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
{
TypeKind Kind { get; }
FullTypeName FullTypeName { get; }
IList<ITypeReference> BaseTypes { get; }
IList<IUnresolvedTypeParameter> TypeParameters { get; }
@ -119,6 +120,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -119,6 +120,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary>
IType EnumUnderlyingType { get; }
/// <summary>
/// Gets the full name of this type.
/// </summary>
FullTypeName FullTypeName { get; }
/// <summary>
/// Gets/Sets the declaring type (incl. type arguments, if any).
/// 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 @@ -43,20 +43,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </param>
/// <returns>
/// 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.
/// </returns>
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>
/// Gets the current 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; @@ -24,7 +24,7 @@ using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
public abstract class AbstractTypeParameter : ITypeParameter
public abstract class AbstractTypeParameter : ITypeParameter, ICompilationProvider
{
readonly ICompilation compilation;
readonly EntityType ownerType;

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

@ -566,6 +566,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -566,6 +566,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return parts[0].Namespace; }
}
public FullTypeName FullTypeName {
get { return parts[0].FullTypeName; }
}
public DomRegion 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 @@ -39,8 +39,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
string fullAssemblyName;
IList<IUnresolvedAttribute> assemblyAttributes;
IList<IUnresolvedAttribute> moduleAttributes;
Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition> typeDefinitions = new Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition>(FullNameAndTypeParameterCountComparer.Ordinal);
Dictionary<FullNameAndTypeParameterCount, ITypeReference> typeForwarders = new Dictionary<FullNameAndTypeParameterCount, ITypeReference>(FullNameAndTypeParameterCountComparer.Ordinal);
Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> typeDefinitions = new Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition>(TopLevelTypeNameComparer.Ordinal);
Dictionary<TopLevelTypeName, ITypeReference> typeForwarders = new Dictionary<TopLevelTypeName, ITypeReference>(TopLevelTypeNameComparer.Ordinal);
protected override void FreezeInternal()
{
@ -144,7 +144,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -144,7 +144,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (typeDefinition.DeclaringTypeDefinition != null)
throw new ArgumentException("Cannot add nested types.");
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);
}
@ -157,7 +157,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -157,7 +157,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// </summary>
/// <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>
public void AddTypeForwarder(FullNameAndTypeParameterCount typeName, ITypeReference referencedType)
public void AddTypeForwarder(TopLevelTypeName typeName, ITypeReference referencedType)
{
if (referencedType == null)
throw new ArgumentNullException("referencedType");
@ -187,7 +187,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -187,7 +187,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
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;
if (typeDefinitions.TryGetValue(key, out td))
return td;
@ -216,9 +216,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -216,9 +216,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
//[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);
if (nameComparer == StringComparer.Ordinal)
@ -291,7 +291,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -291,7 +291,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
readonly DefaultUnresolvedAssembly unresolvedAssembly;
readonly ICompilation compilation;
readonly ITypeResolveContext context;
readonly Dictionary<FullNameAndTypeParameterCount, IUnresolvedTypeDefinition> unresolvedTypeDict;
readonly Dictionary<TopLevelTypeName, IUnresolvedTypeDefinition> unresolvedTypeDict;
readonly ConcurrentDictionary<IUnresolvedTypeDefinition, ITypeDefinition> typeDict = new ConcurrentDictionary<IUnresolvedTypeDefinition, ITypeDefinition>();
readonly INamespace rootNamespace;
@ -338,15 +338,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -338,15 +338,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
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;
ITypeReference typeRef;
if (unresolvedAssembly.typeDefinitions.TryGetValue(key, out td))
if (unresolvedAssembly.typeDefinitions.TryGetValue(topLevelTypeName, out 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();
else
return null;
@ -431,7 +429,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -431,7 +429,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return null;
}
ICompilation IResolved.Compilation {
ICompilation ICompilationProvider.Compilation {
get { return assembly.compilation; }
}
@ -453,7 +451,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -453,7 +451,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
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;
if (assembly.unresolvedTypeDict.TryGetValue(key, out unresolvedTypeDef))
return assembly.GetTypeDefinition(unresolvedTypeDef);

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

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

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

@ -141,24 +141,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -141,24 +141,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public override string ReflectionName {
get {
return this.FullTypeName.ReflectionName;
}
}
public FullTypeName FullTypeName {
get {
IUnresolvedTypeDefinition declaringTypeDef = this.DeclaringTypeDefinition;
if (declaringTypeDef != null) {
if (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;
return declaringTypeDef.FullTypeName.NestedType(this.Name, this.TypeParameters.Count - declaringTypeDef.TypeParameters.Count);
} else {
if (this.TypeParameters.Count > 0)
return namespaceName + "." + this.Name + "`" + this.TypeParameters.Count.ToString(CultureInfo.InvariantCulture);
else
return namespaceName + "." + this.Name;
return new TopLevelTypeName(namespaceName, this.Name, this.TypeParameters.Count);
}
}
}
@ -226,7 +220,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -226,7 +220,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
throw new ArgumentNullException("context");
if (context.CurrentAssembly == null)
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);
}

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

@ -21,73 +21,8 @@ using System.Collections.Generic; @@ -21,73 +21,8 @@ using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
[Serializable]
public struct FullNameAndTypeParameterCount : IEquatable<FullNameAndTypeParameterCount>
[Obsolete("This struct was renamed to 'TopLevelTypeName'.", true)]
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 @@ -28,24 +28,31 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public sealed class GetClassTypeReference : ITypeReference, ISupportsInterning
{
readonly IAssemblyReference assembly;
readonly string nameSpace, name;
readonly int typeParameterCount;
readonly FullTypeName fullTypeName;
/// <summary>
/// Creates a new GetClassTypeReference that searches a top-level type.
/// Creates a new GetClassTypeReference that searches a type definition.
/// </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="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)
throw new ArgumentNullException("nameSpace");
if (name == null)
throw new ArgumentNullException("name");
this.nameSpace = nameSpace;
this.name = name;
this.typeParameterCount = typeParameterCount;
this.fullTypeName = new TopLevelTypeName(namespaceName, name, typeParameterCount);
}
/// <summary>
@ -53,25 +60,33 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -53,25 +60,33 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// </summary>
/// <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>
/// <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="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.nameSpace = nameSpace;
this.name = name;
this.typeParameterCount = typeParameterCount;
this.fullTypeName = new TopLevelTypeName(namespaceName, name, 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 string Namespace { get { return nameSpace; } }
public string Name { get { return name; } }
public int TypeParameterCount { get { return typeParameterCount; } }
/// <summary>
/// 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)
{
@ -80,52 +95,42 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -80,52 +95,42 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
IType type = null;
if (assembly == null) {
var compilation = context.Compilation;
foreach (var asm in new[] { context.CurrentAssembly }.Concat(compilation.Assemblies)) {
if (asm != null) {
type = asm.GetTypeDefinition(nameSpace, name, typeParameterCount);
if (context.CurrentAssembly != null) {
type = context.CurrentAssembly.GetTypeDefinition(fullTypeName);
}
if (type == null) {
var compilation = context.Compilation;
foreach (var asm in compilation.Assemblies) {
type = asm.GetTypeDefinition(fullTypeName);
if (type != null)
return type;
break;
}
}
} else {
IAssembly asm = assembly.Resolve(context);
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()
{
string asmSuffix = (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;
return fullTypeName.ToString() + (assembly != null ? ", " + assembly.ToString() : null);
}
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
return 33 * assembly.GetHashCode() + 27 * nameSpace.GetHashCode() + name.GetHashCode() + typeParameterCount;
return 33 * assembly.GetHashCode() + fullTypeName.GetHashCode();
}
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
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 @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (typeRef == null)
return SpecialType.UnknownType;
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)
return typeDef;
}

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

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
@ -26,9 +27,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -26,9 +27,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
[Serializable]
public class UnknownType : AbstractType, ITypeReference
{
readonly string namespaceName;
readonly string name;
readonly int typeParameterCount;
readonly bool namespaceKnown;
readonly FullTypeName fullTypeName;
/// <summary>
/// Creates a new unknown type.
@ -40,9 +40,24 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -40,9 +40,24 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
if (name == null)
throw new ArgumentNullException("name");
this.namespaceName = namespaceName;
this.name = name;
this.typeParameterCount = typeParameterCount;
this.namespaceKnown = namespaceName != null;
this.fullTypeName = new TopLevelTypeName(namespaceName ?? string.Empty, name, 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 {
@ -62,15 +77,19 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -62,15 +77,19 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public override string Name {
get { return name; }
get { return fullTypeName.Name; }
}
public override string Namespace {
get { return namespaceName ?? string.Empty; }
get { return fullTypeName.TopLevelTypeName.Namespace; }
}
public override string ReflectionName {
get { return "?"; }
get { return namespaceKnown ? fullTypeName.ReflectionName : "?"; }
}
public override int TypeParameterCount {
get { return fullTypeName.TypeParameterCount; }
}
public override bool? IsReferenceType {
@ -79,14 +98,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -79,14 +98,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public override int GetHashCode()
{
int hashCode = 0;
unchecked {
if (namespaceName != null)
hashCode += 1000000007 * namespaceName.GetHashCode();
hashCode += 1000000009 * name.GetHashCode();
hashCode += 1000000021 * typeParameterCount.GetHashCode();
}
return hashCode;
return (namespaceKnown ? 812571 : 12651) ^ fullTypeName.GetHashCode();
}
public override bool Equals(IType other)
@ -94,12 +106,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -94,12 +106,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
UnknownType o = other as UnknownType;
if (o == null)
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()
{
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 @@ -37,7 +37,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// the type arguments.
/// </remarks>
[Serializable]
public sealed class ParameterizedType : IType
public sealed class ParameterizedType : IType, ICompilationProvider
{
readonly ITypeDefinition genericType;
readonly IType[] typeArguments;
@ -57,8 +57,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -57,8 +57,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
for (int i = 0; i < this.typeArguments.Length; i++) {
if (this.typeArguments[i] == null)
throw new ArgumentNullException("typeArguments[" + i + "]");
IResolved r = this.typeArguments[i] as IResolved;
if (r != null && r.Compilation != genericType.Compilation)
ICompilationProvider p = this.typeArguments[i] as ICompilationProvider;
if (p != null && p.Compilation != genericType.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 @@ -56,17 +56,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
{
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
#region Type.ToTypeReference()
@ -218,6 +207,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -218,6 +207,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <see cref="ITypeResolveContext.CurrentAssembly"/> first, and if the type is not found there,
/// it will look in all other assemblies of the compilation.
/// </remarks>
/// <seealso cref="FullTypeName(string)"/>
public static ITypeReference ParseReflectionName(string reflectionTypeName)
{
if (reflectionTypeName == null)

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

@ -0,0 +1,144 @@ @@ -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 @@ -28,7 +28,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Contains extension methods for the type system.
/// </summary>
public static class ExtensionMethods
public static class TypeSystemExtensions
{
#region GetAllBaseTypes
/// <summary>
@ -96,12 +96,31 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -96,12 +96,31 @@ namespace ICSharpCode.NRefactory.TypeSystem
sealed class TypeClassificationVisitor : TypeVisitor
{
internal bool isOpen;
internal IEntity typeParameterOwner;
int typeParameterOwnerNestingLevel;
public override IType VisitTypeParameter(ITypeParameter type)
{
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);
}
static int GetNestingLevel(IEntity entity)
{
int level = 0;
while (entity != null) {
level++;
entity = entity.DeclaringTypeDefinition;
}
return level;
}
}
/// <summary>
@ -126,6 +145,21 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -126,6 +145,21 @@ namespace ICSharpCode.NRefactory.TypeSystem
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>
/// Gets whether the type is unbound (is a generic type, but no type arguments were provided).
/// </summary>
@ -162,7 +196,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -162,7 +196,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
throw new ArgumentNullException("compilation");
if (type == 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>
@ -392,28 +435,59 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -392,28 +435,59 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endregion
#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>
/// Gets the type definition for the specified unresolved type.
/// Returns null if the unresolved type does not belong to this assembly.
/// </summary>
public static ITypeDefinition GetTypeDefinition(this IAssembly assembly, IUnresolvedTypeDefinition unresolved)
public static ITypeDefinition GetTypeDefinition(this IAssembly assembly, FullTypeName fullTypeName)
{
if (assembly == null)
throw new ArgumentNullException("assembly");
if (unresolved == null)
TopLevelTypeName topLevelTypeName = fullTypeName.TopLevelTypeName;
ITypeDefinition typeDef = assembly.GetTypeDefinition(topLevelTypeName);
if (typeDef == null)
return null;
if (unresolved.DeclaringTypeDefinition != null) {
ITypeDefinition parentType = GetTypeDefinition(assembly, unresolved.DeclaringTypeDefinition);
if (parentType == null)
return null;
foreach (var nestedType in parentType.NestedTypes) {
if (nestedType.Name == unresolved.Name && nestedType.TypeParameterCount == unresolved.TypeParameters.Count)
return nestedType;
}
return null;
} else {
return assembly.GetTypeDefinition(unresolved.Namespace, unresolved.Name, unresolved.TypeParameters.Count);
int typeParameterCount = topLevelTypeName.TypeParameterCount;
for (int i = 0; i < fullTypeName.NestingLevel; i++) {
string name = fullTypeName.GetNestedTypeName(i);
typeParameterCount += fullTypeName.GetNestedTypeAdditionalTypeParameterCount(i);
typeDef = FindNestedType(typeDef, name, typeParameterCount);
if (typeDef == null)
break;
}
return typeDef;
}
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
@ -437,5 +511,19 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -437,5 +511,19 @@ namespace ICSharpCode.NRefactory.TypeSystem
return reference.Resolve (compilation.TypeResolveContext);
}
#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