Browse Source

Merge branch 'master' of github.com:icsharpcode/NRefactory

newNRvisualizers
Mike Krüger 14 years ago
parent
commit
c3feace3a4
  1. 11
      ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs
  2. 160
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs
  3. 83
      ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs
  4. 4
      ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs
  5. 26
      ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs
  6. 6
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  7. 2
      ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs
  8. 1
      ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  9. 1
      ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs
  10. 6
      ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs
  11. 93
      ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs
  12. 36
      ICSharpCode.NRefactory.CSharp/Refactoring/IInspector.cs
  13. 61
      ICSharpCode.NRefactory.CSharp/Refactoring/InspectionIssue.cs
  14. 131
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/ConditionalToNullCoalescingInspector.cs
  15. 58
      ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/GatherVisitorBase.cs
  16. 54
      ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs
  17. 2
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs
  18. 75
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpOperators.cs
  19. 14
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  20. 42
      ICSharpCode.NRefactory.CSharp/Resolver/FindReferencedEntities.cs
  21. 35
      ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs
  22. 2
      ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs
  23. 11
      ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs
  24. 8
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  25. 24
      ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs
  26. 9
      ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs
  27. 9
      ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAttribute.cs
  28. 2
      ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpParsedFile.cs
  29. 9
      ICSharpCode.NRefactory.CSharp/TypeSystem/ResolvedUsingScope.cs
  30. 52
      ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs
  31. 13
      ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/NameContextTests.cs
  32. 13
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs
  33. 19
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs
  34. 2
      ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs
  35. 48
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  36. 3
      ICSharpCode.NRefactory.Xml/AXmlObject.cs
  37. 2
      ICSharpCode.NRefactory/Editor/ITextSource.cs
  38. 4
      ICSharpCode.NRefactory/TypeSystem/ArrayType.cs
  39. 6
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  40. 17
      ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs
  41. 1
      ICSharpCode.NRefactory/TypeSystem/IMember.cs
  42. 6
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedMember.cs
  43. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs
  44. 21
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs
  45. 3
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  46. 3
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs
  47. 3
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs
  48. 10
      ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs
  49. 3
      ICSharpCode.NRefactory/TypeSystem/Implementation/KnownTypeCache.cs
  50. 3
      ICSharpCode.NRefactory/TypeSystem/Implementation/MergedNamespace.cs
  51. 3
      ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleCompilation.cs
  52. 23
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs
  53. 15
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs
  54. 184
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs
  55. 103
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs
  56. 21
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs
  57. 45
      ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializingMemberReference.cs
  58. 94
      ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs
  59. 17
      ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs
  60. 23
      ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs
  61. 7
      ICSharpCode.NRefactory/Utils/EmptyList.cs
  62. 14
      ICSharpCode.NRefactory/Utils/LazyInit.cs
  63. 6
      ICSharpCode.NRefactory/Utils/ProjectedList.cs

11
ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs

@ -273,6 +273,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -273,6 +273,17 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
/// <summary>
/// Gets the ancestors of this node (including this node itself)
/// </summary>
public IEnumerable<AstNode> AncestorsAndSelf {
get {
for (AstNode cur = this; cur != null; cur = cur.parent) {
yield return cur;
}
}
}
/// <summary>
/// Gets all descendants of this node (excluding this node itself).
/// </summary>

160
ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs

@ -73,6 +73,34 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -73,6 +73,34 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
this.IndentString = "\t";
}
public bool TryGetCompletionWord (int offset, out int startPos, out int wordLength)
{
startPos = wordLength = 0;
int pos = offset - 1;
while (pos >= 0) {
char c = document.GetCharAt (pos);
if (!char.IsLetterOrDigit (c) && c != '_')
break;
pos--;
}
if (pos == -1)
return false;
pos++;
startPos = pos;
while (pos < document.TextLength) {
char c = document.GetCharAt (pos);
if (!char.IsLetterOrDigit (c) && c != '_')
break;
pos++;
}
wordLength = pos - startPos;
return true;
}
public IEnumerable<ICompletionData> GetCompletionData(int offset, bool controlSpace)
{
this.AutoCompleteEmptyMatch = true;
@ -161,6 +189,29 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -161,6 +189,29 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
}
IEnumerable<ICompletionData> HandleMemberReferenceCompletion(ExpressionResult expr)
{
if (expr == null)
return null;
// do not complete <number>. (but <number>.<number>.)
if (expr.Node is PrimitiveExpression) {
var pexpr = (PrimitiveExpression)expr.Node;
if (!(pexpr.Value is string || pexpr.Value is char) && !pexpr.LiteralValue.Contains('.')) {
return null;
}
}
var resolveResult = ResolveExpression (expr);
if (resolveResult == null) {
return null;
}
if (expr.Node is AstType) {
return CreateTypeAndNamespaceCompletionData(location, resolveResult.Item1, expr.Node, resolveResult.Item2);
}
return CreateCompletionData(location, resolveResult.Item1, expr.Node, resolveResult.Item2);
}
IEnumerable<ICompletionData> MagicKeyCompletion(char completionChar, bool controlSpace)
{
ExpressionResult expr;
@ -173,26 +224,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -173,26 +224,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (IsInsideCommentOrString()) {
return Enumerable.Empty<ICompletionData>();
}
expr = GetExpressionBeforeCursor();
if (expr == null) {
return null;
}
// do not complete <number>. (but <number>.<number>.)
if (expr.Node is PrimitiveExpression) {
var pexpr = (PrimitiveExpression)expr.Node;
if (!(pexpr.Value is string || pexpr.Value is char) && !pexpr.LiteralValue.Contains('.')) {
return null;
}
}
resolveResult = ResolveExpression(expr);
if (resolveResult == null) {
return null;
}
if (expr.Node is AstType) {
return CreateTypeAndNamespaceCompletionData(location, resolveResult.Item1, expr.Node, resolveResult.Item2);
}
return CreateCompletionData(location, resolveResult.Item1, expr.Node, resolveResult.Item2);
return HandleMemberReferenceCompletion(GetExpressionBeforeCursor());
case '#':
if (IsInsideCommentOrString()) {
return null;
@ -478,19 +510,32 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -478,19 +510,32 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var contextList = new CompletionDataWrapper (this);
var identifierStart = GetExpressionAtCursor();
if (identifierStart != null && identifierStart.Node is TypeParameterDeclaration) {
return null;
}
if (identifierStart != null) {
if (identifierStart != null && identifierStart.Node is VariableInitializer && location <= ((VariableInitializer)identifierStart.Node).NameToken.EndLocation) {
return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(identifierStart) : null;
}
if (identifierStart != null && identifierStart.Node is CatchClause) {
if (((CatchClause)identifierStart.Node).VariableNameToken.Contains(location)) {
if (identifierStart.Node is TypeParameterDeclaration) {
return null;
}
identifierStart = null;
if (identifierStart.Node is MemberReferenceExpression) {
return HandleMemberReferenceCompletion(new ExpressionResult (((MemberReferenceExpression)identifierStart.Node).Target, identifierStart.Unit));
}
if (identifierStart.Node is Identifier) {
// May happen in variable names
return controlSpace ? DefaultControlSpaceItems(identifierStart) : null;
}
if (identifierStart.Node is VariableInitializer && location <= ((VariableInitializer)identifierStart.Node).NameToken.EndLocation) {
return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(identifierStart) : null;
}
if (identifierStart.Node is CatchClause) {
if (((CatchClause)identifierStart.Node).VariableNameToken.Contains(location)) {
return null;
}
identifierStart = null;
}
}
if (!(char.IsLetter(completionChar) || completionChar == '_') && (!controlSpace || identifierStart == null || !(identifierStart.Node.Parent is ArrayInitializerExpression))) {
return controlSpace ? HandleAccessorContext() ?? DefaultControlSpaceItems(identifierStart) : null;
@ -1415,7 +1460,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1415,7 +1460,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
if (newParentNode is ReturnStatement) {
var varDecl = (ReturnStatement)newParentNode;
//var varDecl = (ReturnStatement)newParentNode;
if (ctx.CurrentMember != null) {
hintType = ctx.CurrentMember.ReturnType;
}
@ -1561,8 +1606,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1561,8 +1606,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
IEnumerable<ICompletionData> GetOverrideCompletionData(IUnresolvedTypeDefinition type, string modifiers)
{
var wrapper = new CompletionDataWrapper (this);
var alreadyInserted = new Dictionary<string, bool> ();
bool addedVirtuals = false;
var alreadyInserted = new List<IMember> ();
//bool addedVirtuals = false;
int declarationBegin = offset;
int j = declarationBegin;
@ -1643,16 +1688,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1643,16 +1688,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return null;
}
static string GetNameWithParamCount(IMember member)
{
var e = member as IMethod;
if (e == null || e.TypeParameters.Count == 0) {
return member.Name;
}
return e.Name + "`" + e.TypeParameters.Count;
}
void AddVirtuals(Dictionary<string, bool> alreadyInserted, CompletionDataWrapper col, string modifiers, IType curType, int declarationBegin)
void AddVirtuals(List<IMember> alreadyInserted, CompletionDataWrapper col, string modifiers, IType curType, int declarationBegin)
{
if (curType == null) {
return;
@ -1667,17 +1703,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1667,17 +1703,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
var data = factory.CreateNewOverrideCompletionData(declarationBegin, currentType, m);
string text = GetNameWithParamCount(m);
// check if the member is already implemented
bool foundMember = curType.GetMembers().Any(cm => GetNameWithParamCount(cm) == text && cm.DeclaringTypeDefinition == curType.GetDefinition());
bool foundMember = curType.GetMembers().Any(cm => SignatureComparer.Ordinal.Equals(cm, m) && cm.DeclaringTypeDefinition == curType.GetDefinition());
if (foundMember) {
continue;
}
if (alreadyInserted.ContainsKey(text)) {
if (alreadyInserted.Any(cm => SignatureComparer.Ordinal.Equals(cm, m)))
continue;
}
alreadyInserted [text] = true;
alreadyInserted.Add (m);
data.CompletionCategory = col.GetCompletionCategory(curType);
col.Add(data);
}
@ -1742,7 +1775,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1742,7 +1775,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
IMethod delegateMethod = delegateType.GetDelegateInvokeMethod();
var thisLineIndent = GetLineIndent(location.Line);
string delegateEndString = EolMarker + thisLineIndent + "}" + (addSemicolon ? ";" : "");
bool containsDelegateData = completionList.Result.Any(d => d.DisplayText.StartsWith("delegate("));
//bool containsDelegateData = completionList.Result.Any(d => d.DisplayText.StartsWith("delegate("));
if (addDefault) {
completionList.AddCustom("delegate", "Creates anonymous delegate.", "delegate {" + EolMarker + thisLineIndent + IndentString + "|" + delegateEndString);
}
@ -1800,8 +1833,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -1800,8 +1833,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
}
if (member.IsInternal || member.IsProtectedAndInternal || member.IsProtectedOrInternal) {
var type1 = member is ITypeDefinition ? (ITypeDefinition)member : member.DeclaringTypeDefinition;
var type2 = currentMember is ITypeDefinition ? (ITypeDefinition)currentMember : currentMember.DeclaringTypeDefinition;
//var type1 = member is ITypeDefinition ? (ITypeDefinition)member : member.DeclaringTypeDefinition;
//var type2 = currentMember is ITypeDefinition ? (ITypeDefinition)currentMember : currentMember.DeclaringTypeDefinition;
bool result = true;
// easy case, projects are the same
/*// if (type1.ProjectContent == type2.ProjectContent) {
@ -2008,7 +2041,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2008,7 +2041,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
IType type = resolveResult.Type;
var typeDef = resolveResult.Type.GetDefinition();
//var typeDef = resolveResult.Type.GetDefinition();
var result = new CompletionDataWrapper (this);
bool includeStaticMembers = false;
@ -2240,7 +2273,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2240,7 +2273,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
return null;
}
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
//var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
if (mref == null) {
var invoke = baseUnit.GetNodeAt<InvocationExpression>(location);
if (invoke != null) {
@ -2290,14 +2323,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2290,14 +2323,14 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
ExpressionResult GetExpressionAtCursor()
{
TextLocation memberLocation;
if (currentMember != null) {
memberLocation = currentMember.Region.Begin;
} else if (currentType != null) {
memberLocation = currentType.Region.Begin;
} else {
memberLocation = location;
}
// TextLocation memberLocation;
// if (currentMember != null) {
// memberLocation = currentMember.Region.Begin;
// } else if (currentType != null) {
// memberLocation = currentType.Region.Begin;
// } else {
// memberLocation = location;
// }
var baseUnit = ParseStub("a");
var tmpUnit = baseUnit;
@ -2305,7 +2338,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -2305,7 +2338,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (expr == null) {
expr = baseUnit.GetNodeAt<AstType>(location.Line, location.Column - 1);
}
if (expr == null)
expr = baseUnit.GetNodeAt<Identifier>(location.Line, location.Column - 1);
// try insertStatement
if (expr == null && baseUnit.GetNodeAt<EmptyStatement>(location.Line, location.Column) != null) {
tmpUnit = baseUnit = ParseStub("a();", false);

83
ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngineBase.cs

@ -365,7 +365,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -365,7 +365,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
{
var bracketStack = GetBracketStack (memberText);
bool didAppendSemicolon = !appendSemicolon;
char lastBracket = '\0';
//char lastBracket = '\0';
while (bracketStack.Count > 0) {
var t = bracketStack.Pop ();
switch (t.Item1) {
@ -373,19 +373,19 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -373,19 +373,19 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
wrapper.Append (')');
if (appendSemicolon)
didAppendSemicolon = false;
lastBracket = ')';
//lastBracket = ')';
break;
case '[':
wrapper.Append (']');
if (appendSemicolon)
didAppendSemicolon = false;
lastBracket = ']';
//lastBracket = ']';
break;
case '<':
wrapper.Append ('>');
if (appendSemicolon)
didAppendSemicolon = false;
lastBracket = '>';
//lastBracket = '>';
break;
case '{':
int o = t.Item2 - 1;
@ -421,7 +421,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -421,7 +421,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
if (mt == null) {
return null;
}
string memberText = mt.Item1;
var memberLocation = mt.Item2;
int closingBrackets = 1;
@ -429,18 +429,38 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -429,18 +429,38 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
var wrapper = new StringBuilder ();
bool wrapInClass = memberLocation != new TextLocation (1, 1);
if (wrapInClass) {
/* foreach (var child in Unit.Children) {
if (child is UsingDeclaration) {
var offset = document.GetOffset (child.StartLocation);
wrapper.Append (document.GetText (offset, document.GetOffset (child.EndLocation) - offset));
var nodeAtLocation = Unit.GetNodeAt(memberLocation, n => n is TypeDeclaration || n is NamespaceDeclaration);
if (nodeAtLocation != null) {
foreach (var n in nodeAtLocation.AncestorsAndSelf) {
if (memberLocation == n.StartLocation) {
continue;
}
if (n is TypeDeclaration) {
var t = (TypeDeclaration)n;
switch (t.ClassType) {
case ClassType.Class:
wrapper.Append("class");
break;
case ClassType.Struct:
wrapper.Append("struct");
break;
case ClassType.Interface:
wrapper.Append("interface");
break;
case ClassType.Enum:
wrapper.Append("enum");
break;
}
wrapper.Append(" " + t.Name + " {");
wrapper.AppendLine();
closingBrackets++;
generatedLines++;
} else {
Console.WriteLine(n);
}
}
}*/
wrapper.Append("class Stub {");
wrapper.AppendLine();
closingBrackets++;
generatedLines = 1;
}
}
wrapper.Append(memberText);
wrapper.Append(continuation);
AppendMissingClosingBrackets(wrapper, memberText, appendSemicolon);
@ -486,7 +506,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -486,7 +506,6 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
--startOffset;
}
startOffset = 0;
if (cachedText == null)
cachedText = document.GetText (startOffset, offset - startOffset);
@ -508,7 +527,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -508,7 +527,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
}
baseUnit = ParseStub (afterBracket ? "" : "x");
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
//var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
var mref = baseUnit.GetNodeAt (location.Line, location.Column - 1, n => n is InvocationExpression || n is ObjectCreateExpression);
AstNode expr = null;
if (mref is InvocationExpression) {
@ -552,10 +571,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -552,10 +571,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return ResolveExpression (tuple.Node, tuple.Unit);
}
protected Tuple<ResolveResult, CSharpResolver> ResolveExpression (AstNode expr, CompilationUnit unit)
protected Tuple<ResolveResult, CSharpResolver> ResolveExpression(AstNode expr, CompilationUnit unit)
{
if (expr == null)
if (expr == null) {
return null;
}
AstNode resolveNode;
if (expr is Expression || expr is AstType) {
resolveNode = expr;
@ -565,21 +585,21 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -565,21 +585,21 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
resolveNode = expr;
}
try {
var csResolver = new CSharpAstResolver (GetState (), unit, CSharpParsedFile);
var result = csResolver.Resolve (resolveNode);
var state = csResolver.GetResolverStateBefore (resolveNode);
return Tuple.Create (result, state);
var ctx = CSharpParsedFile.GetResolver(Compilation, location);
var root = expr.AncestorsAndSelf.FirstOrDefault(n => n is EntityDeclaration || n is CompilationUnit);
if (root == null) {
return null;
}
var csResolver = new CSharpAstResolver (ctx, root, CSharpParsedFile);
var result = csResolver.Resolve(resolveNode);
var state = csResolver.GetResolverStateBefore(resolveNode);
return Tuple.Create(result, state);
} catch (Exception e) {
Console.WriteLine(e);
return null;
}
}
protected static void Print (AstNode node)
{
var v = new CSharpOutputVisitor (Console.Out, new CSharpFormattingOptions ());
node.AcceptVisitor (v);
}
#endregion
class DefaultMemberProvider : IMemberProvider
@ -594,7 +614,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -594,7 +614,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
public void GetCurrentMembers (int offset, out IUnresolvedTypeDefinition currentType, out IUnresolvedMember currentMember)
{
var document = engine.document;
//var document = engine.document;
var location = engine.location;
currentType = null;
@ -648,7 +668,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -648,7 +668,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
int startOffset = document.GetOffset (currentType.Region.Begin);
int endOffset = document.GetOffset (location);
bool foundEndBracket = false;
//bool foundEndBracket = false;
var bracketStack = new Stack<char> ();
@ -702,6 +722,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -702,6 +722,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return bracketStack.Any (t => t == '{');
}
}
}
}

4
ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs

@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return null;
baseUnit = ParseStub ("x] = a[1");
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
//var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
var mref = baseUnit.GetNodeAt (location, n => n is IndexerExpression);
AstNode expr;
if (mref is IndexerExpression) {
@ -94,7 +94,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion @@ -94,7 +94,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion
return null;
baseUnit = ParseStub ("x> a");
var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
//var memberLocation = currentMember != null ? currentMember.Region.Begin : currentType.Region.Begin;
var expr = baseUnit.GetNodeAt<AstType> (location.Line, location.Column + 1); // '>' position
return new ExpressionResult ((AstNode)expr, baseUnit);
}

26
ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs

@ -129,12 +129,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -129,12 +129,12 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public void ApplyChanges()
{
ApplyChanges(0, document.TextLength, document.Replace);
ApplyChanges(0, document.TextLength, document.Replace, (o, l, v) => document.GetText(o, l) == v);
}
public void ApplyChanges(int startOffset, int length)
{
ApplyChanges(startOffset, length, document.Replace);
ApplyChanges(startOffset, length, document.Replace, (o, l, v) => document.GetText(o, l) == v);
}
/// <summary>
@ -150,11 +150,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -150,11 +150,12 @@ namespace ICSharpCode.NRefactory.CSharp
ApplyChanges(startOffset, length, script.Replace);
}
public void ApplyChanges(int startOffset, int length, Action<int, int, string> documentReplace)
public void ApplyChanges(int startOffset, int length, Action<int, int, string> documentReplace, Func<int, int, string, bool> filter = null)
{
int endOffset = startOffset + length;
TextReplaceAction previousChange = null;
int delta = 0;
var depChanges = new List<TextReplaceAction> ();
foreach (var change in changes.OrderBy(c => c.Offset)) {
if (previousChange != null) {
if (change.Equals(previousChange)) {
@ -174,16 +175,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -174,16 +175,17 @@ namespace ICSharpCode.NRefactory.CSharp
}
previousChange = change;
if (change.Offset < startOffset) {
// skip all changes in front of the begin offset
continue;
} else if (change.Offset > endOffset) {
// skip this change unless it depends on one that we already applied
continue;
bool skipChange = change.Offset < startOffset || change.Offset > endOffset;
skipChange |= filter != null && filter(change.Offset + delta, change.RemovalLength, change.NewText);
skipChange &= !depChanges.Contains(change);
if (!skipChange) {
documentReplace(change.Offset + delta, change.RemovalLength, change.NewText);
delta += change.NewText.Length - change.RemovalLength;
if (change.DependsOn != null) {
depChanges.Add(change.DependsOn);
}
}
documentReplace(change.Offset + delta, change.RemovalLength, change.NewText);
delta += change.NewText.Length - change.RemovalLength;
}
changes.Clear();
}

6
ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -322,6 +322,11 @@ @@ -322,6 +322,11 @@
<Compile Include="Refactoring\ContextAction\RemoveRegion.cs" />
<Compile Include="Refactoring\ContextAction\GenerateProperty.cs" />
<Compile Include="Ast\Roles.cs" />
<Compile Include="Refactoring\Inspector\ConditionalToNullCoalescingInspector.cs" />
<Compile Include="Refactoring\IInspector.cs" />
<Compile Include="Refactoring\InspectionIssue.cs" />
<Compile Include="Refactoring\BaseRefactoringContext.cs" />
<Compile Include="Refactoring\Inspector\GatherVisitorBase.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
@ -332,6 +337,7 @@ @@ -332,6 +337,7 @@
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<ItemGroup>
<Folder Include="Completion\" />
<Folder Include="Refactoring\Inspector\" />
</ItemGroup>
<ProjectExtensions>
<MonoDevelop>

2
ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs

@ -717,7 +717,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -717,7 +717,7 @@ namespace ICSharpCode.NRefactory.CSharp
CodeObject IAstVisitor<CodeObject>.VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{
bool isNestedType = typeStack.Count > 0;
//bool isNestedType = typeStack.Count > 0;
CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(typeDeclaration.Name);
typeDecl.Attributes = ConvertMemberAttributes(typeDeclaration.Modifiers);
typeDecl.CustomAttributes.AddRange(Convert(typeDeclaration.Attributes));

1
ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs

@ -3658,7 +3658,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3658,7 +3658,6 @@ namespace ICSharpCode.NRefactory.CSharp
var file = new SourceFile (fileName, fileName, 0);
Location.Initialize (new List<SourceFile> (new [] { file }));
var module = new ModuleContainer (ctx);
var driver = new Driver (ctx);
var parser = Driver.Parse (reader, file, module, lineModifier);
var top = new CompilerCompilationUnit () {

1
ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs

@ -1535,7 +1535,6 @@ namespace Mono.CSharp @@ -1535,7 +1535,6 @@ namespace Mono.CSharp
#endif
number_pos = 0;
var loc = Location;
bool hasLeadingDot = c == '.';
if (c >= '0' && c <= '9'){
if (c == '0'){

6
ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs

@ -2056,8 +2056,8 @@ namespace Mono.CSharp { @@ -2056,8 +2056,8 @@ namespace Mono.CSharp {
static int id;
public int ID = id++;
static int clone_id_counter;
int clone_id;
// static int clone_id_counter;
// int clone_id;
#endif
// int assignable_slots;
@ -2369,7 +2369,7 @@ namespace Mono.CSharp { @@ -2369,7 +2369,7 @@ namespace Mono.CSharp {
{
Block target = (Block) t;
#if DEBUG
target.clone_id = clone_id_counter++;
// target.clone_id = clone_id_counter++;
#endif
clonectx.AddBlockMap (this, target);

93
ICSharpCode.NRefactory.CSharp/Refactoring/BaseRefactoringContext.cs

@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
//
// BaseRefactoringContext.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Editor;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
public abstract class BaseRefactoringContext
{
protected readonly CSharpAstResolver resolver;
readonly CancellationToken cancellationToken;
public virtual bool Supports(Version version)
{
return true;
}
public CancellationToken CancellationToken {
get { return cancellationToken; }
}
public virtual AstNode RootNode {
get { return resolver.RootNode; }
}
public ICompilation Compilation {
get { return resolver.Compilation; }
}
public BaseRefactoringContext (ICSharpCode.NRefactory.CSharp.Resolver.CSharpAstResolver resolver, System.Threading.CancellationToken cancellationToken)
{
this.resolver = resolver;
this.cancellationToken = cancellationToken;
}
#region Resolving
public ResolveResult Resolve (AstNode node)
{
return resolver.Resolve (node, cancellationToken);
}
public IType ResolveType (AstType type)
{
return resolver.Resolve (type, cancellationToken).Type;
}
public IType GetExpectedType (Expression expression)
{
return resolver.GetExpectedType(expression, cancellationToken);
}
public Conversion GetConversion (Expression expression)
{
return resolver.GetConversion(expression, cancellationToken);
}
#endregion
public abstract Script StartScript();
}
}

36
ICSharpCode.NRefactory.CSharp/Refactoring/IInspector.cs

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
//
// IInspector.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
public interface IInspector
{
IEnumerable<InspectionIssue> Run (BaseRefactoringContext context);
}
}

61
ICSharpCode.NRefactory.CSharp/Refactoring/InspectionIssue.cs

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
//
// InspectionIssue.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
public class InspectionIssue
{
public string Title {
get;
private set;
}
public TextLocation Start {
get;
private set;
}
public TextLocation End {
get;
private set;
}
public System.Action Fix {
get;
private set;
}
public InspectionIssue (string title, TextLocation start, TextLocation end, System.Action fix)
{
this.Title = title;
this.Start = start;
this.End = end;
this.Fix = fix;
}
}
}

131
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/ConditionalToNullCoalescingInspector.cs

@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
//
// ConditionalToNullCoalescingInspector.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Checks for obj != null ? obj : <expr>
/// Converts to: obj ?? <expr>
/// </summary>
public class ConditionalToNullCoalescingInspector : IInspector
{
static ConditionalExpression[] Matches;
string title = "Convert to '??' expression";
public string Title {
get {
return title;
}
set {
title = value;
}
}
public ConditionalToNullCoalescingInspector ()
{
Matches = new [] {
new ConditionalExpression (new BinaryOperatorExpression (new NullReferenceExpression (), BinaryOperatorType.Equality, new AnyNode ()), new AnyNode (), new AnyNode ()),
new ConditionalExpression (new BinaryOperatorExpression (new AnyNode (), BinaryOperatorType.Equality, new NullReferenceExpression ()), new AnyNode (), new AnyNode ()),
new ConditionalExpression (new BinaryOperatorExpression (new NullReferenceExpression (), BinaryOperatorType.InEquality, new AnyNode ()), new AnyNode (), new AnyNode ()),
new ConditionalExpression (new BinaryOperatorExpression (new AnyNode (), BinaryOperatorType.InEquality, new NullReferenceExpression ()), new AnyNode (), new AnyNode ()),
};
}
public IEnumerable<InspectionIssue> Run (BaseRefactoringContext context)
{
var visitor = new GatherVisitor (context, this);
context.RootNode.AcceptVisitor (visitor);
return visitor.FoundIssues;
}
class GatherVisitor : GatherVisitorBase
{
readonly ConditionalToNullCoalescingInspector inspector;
public GatherVisitor (BaseRefactoringContext ctx, ConditionalToNullCoalescingInspector inspector) : base (ctx)
{
this.inspector = inspector;
}
public override void VisitConditionalExpression (ConditionalExpression conditionalExpression)
{
foreach (var match in Matches) {
if (match.IsMatch (conditionalExpression) && IsCandidate (conditionalExpression)) {
AddIssue (conditionalExpression,
inspector.Title,
delegate {
using (var script = ctx.StartScript ()) {
var expressions = SortExpressions (conditionalExpression);
var expr = new BinaryOperatorExpression (expressions.Item1.Clone (), BinaryOperatorType.NullCoalescing, expressions.Item2.Clone ());
script.Replace (conditionalExpression, expr);
}
});
}
}
base.VisitConditionalExpression (conditionalExpression);
}
}
static bool IsCandidate (ConditionalExpression node)
{
var condition = node.Condition as BinaryOperatorExpression;
var compareNode = condition.Left is NullReferenceExpression ? condition.Right : condition.Left;
if (compareNode.IsMatch (node.TrueExpression)) {
// a == null ? a : other
if (condition.Operator == BinaryOperatorType.Equality)
return false;
// a != null ? a : other
return compareNode.IsMatch (node.TrueExpression);
} else {
// a == null ? other : a
if (condition.Operator == BinaryOperatorType.Equality)
return compareNode.IsMatch (node.FalseExpression);
// a != null ? other : a
return false;
}
}
static Tuple<Expression, Expression> SortExpressions (ConditionalExpression cond)
{
var condition = cond.Condition as BinaryOperatorExpression;
var compareNode = condition.Left is NullReferenceExpression ? condition.Right : condition.Left;
if (compareNode.IsMatch (cond.TrueExpression)) {
// a != null ? a : other
return new Tuple<Expression, Expression> (cond.TrueExpression, cond.FalseExpression);
}
// a == null ? other : a
return new Tuple<Expression, Expression> (cond.FalseExpression, cond.TrueExpression);
}
}
}

58
ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/GatherVisitorBase.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
//
// GatherVisitorBase.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp
{
class GatherVisitorBase : DepthFirstAstVisitor
{
protected readonly BaseRefactoringContext ctx;
public readonly List<InspectionIssue> FoundIssues = new List<InspectionIssue> ();
public GatherVisitorBase (BaseRefactoringContext ctx)
{
this.ctx = ctx;
}
protected override void VisitChildren (AstNode node)
{
if (ctx.CancellationToken.IsCancellationRequested)
return;
base.VisitChildren (node);
}
protected void AddIssue (AstNode node, string title, System.Action fix)
{
FoundIssues.Add (new InspectionIssue (title, node.StartLocation, node.EndLocation, fix));
}
}
}

54
ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs

@ -36,36 +36,14 @@ using ICSharpCode.NRefactory.Editor; @@ -36,36 +36,14 @@ using ICSharpCode.NRefactory.Editor;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
public abstract class RefactoringContext
public abstract class RefactoringContext : BaseRefactoringContext
{
readonly CSharpAstResolver resolver;
readonly CancellationToken cancellationToken;
public RefactoringContext(CSharpAstResolver resolver, CancellationToken cancellationToken)
public RefactoringContext(CSharpAstResolver resolver, CancellationToken cancellationToken) : base (resolver, cancellationToken)
{
this.resolver = resolver;
this.cancellationToken = cancellationToken;
}
public CancellationToken CancellationToken {
get { return cancellationToken; }
}
public virtual AstNode RootNode {
get { return resolver.RootNode; }
}
public abstract TextLocation Location { get; }
public virtual bool Supports(Version version)
{
return true;
}
public ICompilation Compilation {
get { return resolver.Compilation; }
}
public virtual AstType CreateShortType (IType fullType)
{
var csResolver = resolver.GetResolverStateBefore(GetNode());
@ -132,29 +110,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -132,29 +110,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
public abstract string GetText (ISegment segment);
#endregion
#region Resolving
public ResolveResult Resolve (AstNode node)
{
return resolver.Resolve (node, cancellationToken);
}
public IType ResolveType (AstType type)
{
return resolver.Resolve (type, cancellationToken).Type;
}
public IType GetExpectedType (Expression expression)
{
return resolver.GetExpectedType(expression, cancellationToken);
}
public Conversion GetConversion (Expression expression)
{
return resolver.GetConversion(expression, cancellationToken);
}
#endregion
public virtual string GetNameProposal (string name, bool camelCase = true)
{
string baseName = (camelCase ? char.ToLower (name [0]) : char.ToUpper (name [0])) + name.Substring (1);
@ -175,8 +131,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -175,8 +131,6 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
return baseName + (number > 0 ? (number + 1).ToString () : "");
}
public abstract Script StartScript();
}
}

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

@ -418,7 +418,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -418,7 +418,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ParameterizedType toPT = toType as ParameterizedType;
if (fromArray.Dimensions == 1 && toPT != null && toPT.TypeParameterCount == 1
&& toPT.Namespace == "System.Collections.Generic"
&& (toPT.Name == "IList" || toPT.Name == "ICollection" || toPT.Name == "IEnumerable"))
&& (toPT.Name == "IList" || toPT.Name == "ICollection" || toPT.Name == "IEnumerable" || toPT.Name == "IReadOnlyList"))
{
// array covariance plays a part here as well (string[] is IList<object>)
return IdentityConversion(fromArray.ElementType, toPT.GetTypeArgument(0))

75
ICSharpCode.NRefactory.CSharp/Resolver/CSharpOperators.cs

@ -327,9 +327,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -327,9 +327,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] UnaryPlusOperators {
get {
OperatorMethod[] ops = unaryPlusOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref unaryPlusOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref unaryPlusOperators, Lift(
@ -350,9 +349,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -350,9 +349,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] UncheckedUnaryMinusOperators {
get {
OperatorMethod[] ops = uncheckedUnaryMinusOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref uncheckedUnaryMinusOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref uncheckedUnaryMinusOperators, Lift(
@ -370,9 +368,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -370,9 +368,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] CheckedUnaryMinusOperators {
get {
OperatorMethod[] ops = checkedUnaryMinusOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref checkedUnaryMinusOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref checkedUnaryMinusOperators, Lift(
@ -391,9 +388,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -391,9 +388,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] LogicalNegationOperators {
get {
OperatorMethod[] ops = logicalNegationOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalNegationOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref logicalNegationOperators, Lift(
@ -408,9 +404,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -408,9 +404,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] BitwiseComplementOperators {
get {
OperatorMethod[] ops = bitwiseComplementOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseComplementOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref bitwiseComplementOperators, Lift(
@ -501,9 +496,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -501,9 +496,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] MultiplicationOperators {
get {
OperatorMethod[] ops = multiplicationOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref multiplicationOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref multiplicationOperators, Lift(
@ -524,9 +518,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -524,9 +518,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] DivisionOperators {
get {
OperatorMethod[] ops = divisionOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref divisionOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref divisionOperators, Lift(
@ -547,9 +540,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -547,9 +540,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] RemainderOperators {
get {
OperatorMethod[] ops = remainderOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref remainderOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref remainderOperators, Lift(
@ -570,9 +562,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -570,9 +562,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] AdditionOperators {
get {
OperatorMethod[] ops = additionOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref additionOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref additionOperators, Lift(
@ -620,9 +611,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -620,9 +611,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] SubtractionOperators {
get {
OperatorMethod[] ops = subtractionOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref subtractionOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref subtractionOperators, Lift(
@ -643,9 +633,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -643,9 +633,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] ShiftLeftOperators {
get {
OperatorMethod[] ops = shiftLeftOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref shiftLeftOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref shiftLeftOperators, Lift(
@ -662,9 +651,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -662,9 +651,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] ShiftRightOperators {
get {
OperatorMethod[] ops = shiftRightOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref shiftRightOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref shiftRightOperators, Lift(
@ -767,9 +755,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -767,9 +755,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] ValueEqualityOperators {
get {
OperatorMethod[] ops = valueEqualityOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref valueEqualityOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref valueEqualityOperators, Lift(
@ -783,9 +770,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -783,9 +770,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] ValueInequalityOperators {
get {
OperatorMethod[] ops = valueInequalityOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref valueInequalityOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref valueInequalityOperators, Lift(
@ -799,9 +785,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -799,9 +785,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] ReferenceEqualityOperators {
get {
OperatorMethod[] ops = referenceEqualityOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref referenceEqualityOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref referenceEqualityOperators, Lift(
@ -816,9 +801,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -816,9 +801,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] ReferenceInequalityOperators {
get {
OperatorMethod[] ops = referenceInequalityOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref referenceInequalityOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref referenceInequalityOperators, Lift(
@ -868,9 +852,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -868,9 +852,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] LessThanOperators {
get {
OperatorMethod[] ops = lessThanOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref lessThanOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref lessThanOperators, Lift(
@ -890,9 +873,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -890,9 +873,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] LessThanOrEqualOperators {
get {
OperatorMethod[] ops = lessThanOrEqualOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref lessThanOrEqualOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref lessThanOrEqualOperators, Lift(
@ -912,9 +894,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -912,9 +894,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] GreaterThanOperators {
get {
OperatorMethod[] ops = greaterThanOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref greaterThanOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref greaterThanOperators, Lift(
@ -934,9 +915,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -934,9 +915,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] GreaterThanOrEqualOperators {
get {
OperatorMethod[] ops = greaterThanOrEqualOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref greaterThanOrEqualOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref greaterThanOrEqualOperators, Lift(
@ -958,9 +938,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -958,9 +938,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] LogicalAndOperators {
get {
OperatorMethod[] ops = logicalAndOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalAndOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref logicalAndOperators, new OperatorMethod[] {
@ -975,9 +954,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -975,9 +954,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] BitwiseAndOperators {
get {
OperatorMethod[] ops = bitwiseAndOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseAndOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref bitwiseAndOperators, Lift(
@ -996,9 +974,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -996,9 +974,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] LogicalOrOperators {
get {
OperatorMethod[] ops = logicalOrOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref logicalOrOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref logicalOrOperators, new OperatorMethod[] {
@ -1012,9 +989,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1012,9 +989,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] BitwiseOrOperators {
get {
OperatorMethod[] ops = bitwiseOrOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseOrOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref bitwiseOrOperators, Lift(
@ -1036,9 +1012,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1036,9 +1012,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public OperatorMethod[] BitwiseXorOperators {
get {
OperatorMethod[] ops = bitwiseXorOperators;
OperatorMethod[] ops = LazyInit.VolatileRead(ref bitwiseXorOperators);
if (ops != null) {
LazyInit.ReadBarrier();
return ops;
} else {
return LazyInit.GetOrSet(ref bitwiseXorOperators, Lift(

14
ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs

@ -1167,13 +1167,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1167,13 +1167,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
internal readonly IParameterizedMember nonLiftedOperator;
public LiftedUserDefinedOperator(IMethod nonLiftedMethod)
: base(nonLiftedMethod.DeclaringType, (IMethod)nonLiftedMethod.MemberDefinition,
EmptyList<IType>.Instance, new MakeNullableVisitor(nonLiftedMethod.Compilation))
: base(nonLiftedMethod, TypeParameterSubstitution.Identity)
{
this.nonLiftedOperator = nonLiftedMethod;
var substitution = new MakeNullableVisitor(nonLiftedMethod.Compilation);
this.Parameters = base.CreateParameters(substitution);
// Comparison operators keep the 'bool' return type even when lifted.
if (IsComparisonOperator(nonLiftedMethod))
this.ReturnType = nonLiftedMethod.ReturnType;
else
this.ReturnType = nonLiftedMethod.ReturnType.AcceptVisitor(substitution);
}
public IList<IParameter> NonLiftedParameters {
@ -1726,13 +1729,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1726,13 +1729,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (typeArguments != null && typeArguments.Count > 0) {
if (method.TypeParameters.Count != typeArguments.Count)
continue;
SpecializedMethod sm = new SpecializedMethod(method.DeclaringType, method, typeArguments);
SpecializedMethod sm = new SpecializedMethod(method, new TypeParameterSubstitution(null, typeArguments));
if (IsEligibleExtensionMethod(targetType, method, false, out inferredTypes))
outputGroup.Add(sm);
} else {
if (IsEligibleExtensionMethod(targetType, method, true, out inferredTypes)) {
if (substituteInferredTypes && inferredTypes != null) {
outputGroup.Add(new SpecializedMethod(method.DeclaringType, method, inferredTypes));
outputGroup.Add(new SpecializedMethod(method, new TypeParameterSubstitution(null, inferredTypes)));
} else {
outputGroup.Add(method);
}
@ -1794,9 +1797,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1794,9 +1797,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var currentUsingScope = context.CurrentUsingScope;
if (currentUsingScope == null)
return EmptyList<List<IMethod>>.Instance;
List<List<IMethod>> extensionMethodGroups = currentUsingScope.AllExtensionMethods;
List<List<IMethod>> extensionMethodGroups = LazyInit.VolatileRead(ref currentUsingScope.AllExtensionMethods);
if (extensionMethodGroups != null) {
LazyInit.ReadBarrier();
return extensionMethodGroups;
}
extensionMethodGroups = new List<List<IMethod>>();

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

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

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

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

2
ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs

@ -164,7 +164,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -164,7 +164,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.TargetType, method, true, out inferredTypes))
{
if (substituteInferredTypes && inferredTypes != null) {
outputGroup.Add(new SpecializedMethod(method.DeclaringType, method, inferredTypes));
outputGroup.Add(new SpecializedMethod(method, new TypeParameterSubstitution(null, inferredTypes)));
} else {
outputGroup.Add(method);
}

11
ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs

@ -807,7 +807,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -807,7 +807,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return null;
IMethod method = bestCandidate.Member as IMethod;
if (method != null && method.TypeParameters.Count > 0) {
return new SpecializedMethod(method.DeclaringType, (IMethod)method.MemberDefinition, bestCandidate.InferredTypes);
SpecializedMethod sm = method as SpecializedMethod;
if (sm != null) {
// Do not compose the substitutions, but merge them.
// This is required for InvocationTests.SubstituteClassAndMethodTypeParametersAtOnce
return new SpecializedMethod(
(IMethod)method.MemberDefinition,
new TypeParameterSubstitution(sm.Substitution.ClassTypeArguments, bestCandidate.InferredTypes));
} else {
return new SpecializedMethod(method, new TypeParameterSubstitution(null, bestCandidate.InferredTypes));
}
} else {
return bestCandidate.Member;
}

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

@ -1310,8 +1310,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1310,8 +1310,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
if (resolverEnabled || !objectCreateExpression.Initializer.IsNull) {
var typeResolveResult = Resolve(objectCreateExpression.Type);
if (typeResolveResult.IsError)
if (typeResolveResult.IsError) {
ScanChildren (objectCreateExpression);
return typeResolveResult;
}
IType type = typeResolveResult.Type;
List<ResolveResult> initializerStatements = null;
@ -1712,7 +1714,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1712,7 +1714,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
CSharpResolver oldResolver = resolver;
List<IParameter> parameters = (hasParameterList || parameterDeclarations.Any()) ? new List<IParameter>() : null;
bool oldIsWithinLambdaExpression = resolver.IsWithinLambdaExpression;
//bool oldIsWithinLambdaExpression = resolver.IsWithinLambdaExpression;
resolver = resolver.WithIsWithinLambdaExpression(true);
foreach (var pd in parameterDeclarations) {
IType type = ResolveType(pd.Type);
@ -2626,7 +2628,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2626,7 +2628,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (string.IsNullOrEmpty(catchClause.VariableName)) {
Scan(catchClause.Type);
} else {
DomRegion region = MakeRegion(catchClause.VariableNameToken);
//DomRegion region = MakeRegion(catchClause.VariableNameToken);
StoreCurrentState(catchClause.VariableNameToken);
IVariable v = MakeVariable(ResolveType(catchClause.Type), catchClause.VariableNameToken);
resolver = resolver.AddVariable(v);

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

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

9
ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAssembly.cs

@ -68,9 +68,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -68,9 +68,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
IList<IAttribute> GetAttributes(ref IList<IAttribute> field, bool assemblyAttributes)
{
IList<IAttribute> result = field;
IList<IAttribute> result = LazyInit.VolatileRead(ref field);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
result = new List<IAttribute>();
@ -89,9 +88,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -89,9 +88,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
public INamespace RootNamespace {
get {
NS root = this.rootNamespace;
NS root = LazyInit.VolatileRead(ref this.rootNamespace);
if (root != null) {
LazyInit.ReadBarrier();
return root;
} else {
root = new NS(this);
@ -183,9 +181,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -183,9 +181,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
Dictionary<FullNameAndTypeParameterCount, ITypeDefinition> GetTypes()
{
var dict = this.typeDict;
var dict = LazyInit.VolatileRead(ref this.typeDict);
if (dict != null) {
LazyInit.ReadBarrier();
return dict;
} else {
// Always use the ordinal comparer for the main dictionary so that partial classes

9
ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpAttribute.cs

@ -93,9 +93,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -93,9 +93,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
InvocationResolveResult GetCtorInvocation()
{
ResolveResult rr = this.ctorInvocation;
ResolveResult rr = LazyInit.VolatileRead(ref this.ctorInvocation);
if (rr != null) {
LazyInit.ReadBarrier();
return rr as InvocationResolveResult;
} else {
CSharpResolver resolver = new CSharpResolver(context);
@ -132,9 +131,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -132,9 +131,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
IList<ResolveResult> IAttribute.PositionalArguments {
get {
var result = this.positionalArguments;
var result = LazyInit.VolatileRead(ref this.positionalArguments);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
var invocation = GetCtorInvocation();
@ -149,9 +147,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -149,9 +147,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
IList<KeyValuePair<IMember, ResolveResult>> IAttribute.NamedArguments {
get {
var namedArgs = this.namedArguments;
var namedArgs = LazyInit.VolatileRead(ref this.namedArguments);
if (namedArgs != null) {
LazyInit.ReadBarrier();
return namedArgs;
} else {
namedArgs = new List<KeyValuePair<IMember, ResolveResult>>();

2
ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpParsedFile.cs

@ -159,7 +159,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -159,7 +159,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
return null;
}
public CSharpTypeResolveContext GetTypeResolveContext (ICompilation compilation, TextLocation loc)
public CSharpTypeResolveContext GetTypeResolveContext(ICompilation compilation, TextLocation loc)
{
var rctx = new CSharpTypeResolveContext (compilation.MainAssembly);
rctx = rctx.WithUsingScope (GetUsingScope (loc).Resolve (compilation));

9
ICSharpCode.NRefactory.CSharp/TypeSystem/ResolvedUsingScope.cs

@ -64,9 +64,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -64,9 +64,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
public INamespace Namespace {
get {
INamespace result = this.@namespace;
INamespace result = LazyInit.VolatileRead(ref this.@namespace);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
if (parentContext.CurrentUsingScope != null) {
@ -90,9 +89,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -90,9 +89,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
public IList<INamespace> Usings {
get {
var result = this.usings;
var result = LazyInit.VolatileRead(ref this.usings);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
result = new List<INamespace>();
@ -111,9 +109,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -111,9 +109,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
public IList<KeyValuePair<string, ResolveResult>> UsingAliases {
get {
var result = this.usingAliases;
var result = LazyInit.VolatileRead(ref this.usingAliases);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
CSharpResolver resolver = new CSharpResolver(parentContext.WithUsingScope(this));

52
ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/CodeCompletionBugTests.cs

@ -43,8 +43,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion @@ -43,8 +43,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
[TestFixture()]
public class CodeCompletionBugTests : TestBase
{
static int pcount = 0;
public static CompletionDataList CreateProvider (string text)
{
return CreateProvider (text, false);
@ -350,7 +349,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion @@ -350,7 +349,7 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
}
}
} catch (Exception e) {
Console.WriteLine ("Exception in:" + file);
Console.WriteLine ("Exception in:" + file + "/" + e);
exceptions++;
}
}
@ -4765,5 +4764,52 @@ class MainClass @@ -4765,5 +4764,52 @@ class MainClass
Assert.IsNull (provider.Find ("IEnumerable"), "'IEnumerable' found.");
}
/// <summary>
/// Bug 3957 - [New Resolver]Override completion doesn't work well for overloaded methods
/// </summary>
[Test()]
public void TestBug3957 ()
{
var provider = CreateProvider (
@"class A
{
public virtual void Method()
{}
public virtual void Method(int i)
{}
}
class B : A
{
$override $
}
");
Assert.AreEqual (2, provider.Data.Where (d => d.DisplayText == "Method").Count ());
}
/// <summary>
/// Bug 3973 - code completion forgets context if text is deleted
/// </summary>
[Test()]
public void TestBug3973 ()
{
var provider = CreateProvider (
@"
using System;
class A
{
public static void Main (string[] args)
{
Console.$W$
}
}
");
Assert.IsNotNull (provider.Find ("WriteLine"), "'WriteLine' not found.");
}
}
}

13
ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/NameContextTests.cs

@ -122,6 +122,19 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion @@ -122,6 +122,19 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion
Assert.IsTrue (provider == null || provider.Count == 0, "provider should be empty.");
}
[Test()]
public void TestForLoopLocalVariableName ()
{
var provider = CodeCompletionBugTests.CreateProvider (@"class MyClass {
void Test()
{
$for (int f$
}
}");
Assert.IsTrue (provider == null || provider.Count == 0, "provider should be empty.");
}
[Test()]
public void TestCatchExceptionName ()
{

13
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs

@ -260,5 +260,18 @@ class Test { @@ -260,5 +260,18 @@ class Test {
Assert.AreEqual("Test", rr.Type.ReflectionName);
Assert.AreEqual(5, rr.InitializerStatements.Count);
}
[Test]
public void CreateGeneric()
{
string program = @"using System;
class Test<T> where T : new() {
object x = $new T()$;
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.IsFalse(rr.IsError);
Assert.AreEqual(TypeKind.TypeParameter, rr.Type.Kind);
Assert.AreEqual(TypeKind.TypeParameter, rr.Member.DeclaringType.Kind);
}
}
}

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

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

2
ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs

@ -69,6 +69,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -69,6 +69,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
[Test]
[Ignore("Produces different results in .NET 4.5 due to new read-only interfaces")]
public void ArrayOfString()
{
Assert.AreEqual(GetTypes(typeof(string[]), typeof(Array), typeof(object),
@ -216,6 +217,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -216,6 +217,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
[Test]
[Ignore("Produces different results in .NET 4.5 due to new read-only interfaces")]
public void BaseTypeDefinitionsOfStringArray()
{
Assert.AreEqual(

48
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs

@ -182,6 +182,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -182,6 +182,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
IMethod m = testClass.Methods.Single(me => me.Name == "GetIndex");
Assert.AreEqual("T", m.TypeParameters[0].Name);
Assert.AreEqual(EntityType.Method, m.TypeParameters[0].OwnerType);
Assert.AreSame(m, m.TypeParameters[0].Owner);
ParameterizedType constraint = (ParameterizedType)m.TypeParameters[0].DirectBaseTypes.First();
Assert.AreEqual("IEquatable", constraint.Name);
@ -190,6 +191,53 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -190,6 +191,53 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreSame(m.TypeParameters[0], constraint.TypeArguments[0]);
}
[Test]
public void GetIndexSpecializedTypeParameter()
{
var testClass = GetTypeDefinition(typeof(GenericClass<,>));
var methodDef = testClass.Methods.Single(me => me.Name == "GetIndex");
var m = new SpecializedMethod(methodDef, new TypeParameterSubstitution(
new[] { compilation.FindType(KnownTypeCode.Int16), compilation.FindType(KnownTypeCode.Int32) },
null
));
Assert.AreEqual("T", m.TypeParameters[0].Name);
Assert.AreEqual(EntityType.Method, m.TypeParameters[0].OwnerType);
Assert.AreSame(m, m.TypeParameters[0].Owner);
ParameterizedType constraint = (ParameterizedType)m.TypeParameters[0].DirectBaseTypes.First();
Assert.AreEqual("IEquatable", constraint.Name);
Assert.AreEqual(1, constraint.TypeParameterCount);
Assert.AreEqual(1, constraint.TypeArguments.Count);
Assert.AreSame(m.TypeParameters[0], constraint.TypeArguments[0]);
}
[Test]
public void GetIndexDoubleSpecialization()
{
var testClass = GetTypeDefinition(typeof(GenericClass<,>));
// GenericClass<A, B>.GetIndex<T>
var methodDef = testClass.Methods.Single(me => me.Name == "GetIndex");
// GenericClass<B, A>.GetIndex<A>
var m1 = new SpecializedMethod(methodDef, new TypeParameterSubstitution(
new[] { testClass.TypeParameters[1], testClass.TypeParameters[0] },
new[] { testClass.TypeParameters[0] }
));
// GenericClass<string, int>.GetIndex<int>
var m2 = new SpecializedMethod(m1, new TypeParameterSubstitution(
new[] { compilation.FindType(KnownTypeCode.Int32), compilation.FindType(KnownTypeCode.String) },
null
));
// GenericClass<string, int>.GetIndex<int>
var m12 = new SpecializedMethod(methodDef, new TypeParameterSubstitution(
new[] { compilation.FindType(KnownTypeCode.String), compilation.FindType(KnownTypeCode.Int32) },
new[] { compilation.FindType(KnownTypeCode.Int32) }
));
Assert.AreEqual(m12, m2);
}
[Test]
public void GenericEnum()
{

3
ICSharpCode.NRefactory.Xml/AXmlObject.cs

@ -79,9 +79,8 @@ namespace ICSharpCode.NRefactory.Xml @@ -79,9 +79,8 @@ namespace ICSharpCode.NRefactory.Xml
/// </summary>
public IList<AXmlObject> Children {
get {
var result = this.children;
var result = LazyInit.VolatileRead(ref this.children);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
if (internalObject.NestedObjects != null) {

2
ICSharpCode.NRefactory/Editor/ITextSource.cs

@ -168,7 +168,7 @@ namespace ICSharpCode.NRefactory.Editor @@ -168,7 +168,7 @@ namespace ICSharpCode.NRefactory.Editor
/// <remarks>
/// Verions can be used to efficiently detect whether a document has changed and needs reparsing;
/// or even to implement incremental parsers.
/// It is a separate class from ITextBuffer to allow the GC to collect the text buffer while
/// It is a separate class from ITextSource to allow the GC to collect the text source while
/// the version checkpoint is still in use.
/// </remarks>
public interface ITextSourceVersion

4
ICSharpCode.NRefactory/TypeSystem/ArrayType.cs

@ -85,6 +85,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -85,6 +85,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
ITypeDefinition def = compilation.FindType(KnownTypeCode.IListOfT) as ITypeDefinition;
if (def != null)
baseTypes.Add(new ParameterizedType(def, new[] { elementType }));
// And in .NET 4.5 they also implement IReadOnlyList<T>
def = compilation.FindType(KnownTypeCode.IReadOnlyListOfT) as ITypeDefinition;
if (def != null)
baseTypes.Add(new ParameterizedType(def, new[] { elementType }));
}
return baseTypes;
}

6
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -869,9 +869,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -869,9 +869,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
public IList<ResolveResult> PositionalArguments {
get {
var result = this.positionalArguments;
var result = LazyInit.VolatileRead(ref this.positionalArguments);
if (result != null) {
LazyInit.ReadBarrier();
return result;
}
DecodeBlob();
@ -881,9 +880,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -881,9 +880,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
public IList<KeyValuePair<IMember, ResolveResult>> NamedArguments {
get {
var result = this.namedArguments;
var result = LazyInit.VolatileRead(ref this.namedArguments);
if (result != null) {
LazyInit.ReadBarrier();
return result;
}
DecodeBlob();

17
ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs

@ -246,19 +246,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -246,19 +246,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
{
if (type == null)
throw new ArgumentNullException("type");
ITypeDefinition def = type.GetDefinition();
if (def != null && def.Kind == TypeKind.Delegate) {
foreach (IMember member in def.Members) {
if (member.Name == "Invoke" && member is IMethod) {
ParameterizedType pt = type as ParameterizedType;
if (pt != null) {
return new SpecializedMethod(pt, (IMethod)member);
}
return (IMethod)member;
}
}
}
return null;
if (type.Kind == TypeKind.Delegate)
return type.GetMethods(m => m.Name == "Invoke", GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
else
return null;
}
#endregion

1
ICSharpCode.NRefactory/TypeSystem/IMember.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.TypeSystem
{

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

@ -56,9 +56,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -56,9 +56,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IList<IMember> ImplementedInterfaceMembers {
get {
IList<IMember> result = this.implementedInterfaceMembers;
IList<IMember> result = LazyInit.VolatileRead(ref this.implementedInterfaceMembers);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
return LazyInit.GetOrSet(ref implementedInterfaceMembers, FindImplementedInterfaceMembers());
@ -123,9 +122,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -123,9 +122,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
if (unresolvedAccessor == null)
return null;
IMethod result = accessorField;
IMethod result = LazyInit.VolatileRead(ref accessorField);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
return LazyInit.GetOrSet(ref accessorField, (IMethod)unresolvedAccessor.CreateResolved(context));

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

@ -261,7 +261,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -261,7 +261,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (this.HasDefaultConstructorConstraint || this.HasValueTypeConstraint) {
if (filter == null || filter(dummyConstructor)) {
var resolvedCtor = GetDummyConstructor(compilation);
IMethod m = new SpecializedMethod(this, resolvedCtor, EmptyList<IType>.Instance);
IMethod m = new SpecializedMethod(resolvedCtor, TypeParameterSubstitution.Identity) { DeclaringType = this };
return new [] { m };
}
}

21
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs

@ -61,9 +61,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -61,9 +61,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IList<ITypeParameter> TypeParameters {
get {
var result = this.typeParameters;
var result = LazyInit.VolatileRead(ref this.typeParameters);
if (result != null) {
LazyInit.ReadBarrier();
return result;
}
ITypeResolveContext contextForTypeParameters = parts[0].CreateResolveContext(parentContext);
@ -91,9 +90,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -91,9 +90,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IList<IAttribute> Attributes {
get {
var result = this.attributes;
var result = LazyInit.VolatileRead(ref this.attributes);
if (result != null) {
LazyInit.ReadBarrier();
return result;
}
result = new List<IAttribute>();
@ -126,9 +124,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -126,9 +124,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IList<ITypeDefinition> NestedTypes {
get {
IList<ITypeDefinition> result = this.nestedTypes;
IList<ITypeDefinition> result = LazyInit.VolatileRead(ref this.nestedTypes);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
result = (
@ -171,9 +168,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -171,9 +168,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IMember this[int index] {
get {
IMember output = resolvedMembers[index];
IMember output = LazyInit.VolatileRead(ref resolvedMembers[index]);
if (output != null) {
LazyInit.ReadBarrier();
return output;
}
return LazyInit.GetOrSet(ref resolvedMembers[index], unresolvedMembers[index].CreateResolved(contextPerMember[index]));
@ -288,9 +284,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -288,9 +284,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
MemberList GetMemberList()
{
var result = this.memberList;
var result = LazyInit.VolatileRead(ref this.memberList);
if (result != null) {
LazyInit.ReadBarrier();
return result;
}
List<IUnresolvedMember> unresolvedMembers = new List<IUnresolvedMember>();
@ -506,9 +501,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -506,9 +501,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IEnumerable<IType> DirectBaseTypes {
get {
IList<IType> result = this.directBaseTypes;
IList<IType> result = LazyInit.VolatileRead(ref this.directBaseTypes);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
result = CalculateDirectBaseTypes();
@ -787,7 +781,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -787,7 +781,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
IType coClass = ComHelper.GetCoClass(this);
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
return coClass.GetConstructors(filter, options).Select(m => new SpecializedMethod(this, m));
return coClass.GetConstructors(filter, options)
.Select(m => new SpecializedMethod(m, TypeParameterSubstitution.Identity) { DeclaringType = this });
}
}
return EmptyList<IMethod>.Instance;

3
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs

@ -340,9 +340,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -340,9 +340,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
IEnumerable<ITypeDefinition> INamespace.Types {
get {
var result = this.types;
var result = LazyInit.VolatileRead(ref this.types);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
var hashSet = new HashSet<ITypeDefinition>();

3
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs

@ -246,9 +246,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -246,9 +246,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IList<KeyValuePair<IMember, ResolveResult>> NamedArguments {
get {
var namedArgs = this.namedArguments;
var namedArgs = LazyInit.VolatileRead(ref this.namedArguments);
if (namedArgs != null) {
LazyInit.ReadBarrier();
return namedArgs;
} else {
namedArgs = new List<KeyValuePair<IMember, ResolveResult>>();

3
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultUnresolvedParameter.cs

@ -234,9 +234,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -234,9 +234,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public object ConstantValue {
get {
ResolveResult rr = this.resolvedDefaultValue;
ResolveResult rr = LazyInit.VolatileRead(ref this.resolvedDefaultValue);
if (rr != null) {
LazyInit.ReadBarrier();
return rr.ConstantValue;
} else {
rr = defaultValue.Resolve(context);

10
ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs

@ -132,7 +132,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -132,7 +132,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
else
substitution = new TypeParameterSubstitution(null, methodTypeArguments);
}
yield return new SpecializedMethod(baseType, m, methodTypeArguments, substitution);
yield return new SpecializedMethod(m, substitution);
}
} else {
foreach (IMethod m in declaredMethods) {
@ -162,7 +162,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -162,7 +162,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
ParameterizedType pt = baseType as ParameterizedType;
if (pt != null) {
var substitution = pt.GetSubstitution();
return declaredCtors.Select(m => new SpecializedMethod(pt, m, null, substitution));
return declaredCtors.Select(m => new SpecializedMethod(m, substitution) { DeclaringType = pt });
} else {
return declaredCtors;
}
@ -189,7 +189,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -189,7 +189,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
ParameterizedType pt = baseType as ParameterizedType;
if (pt != null) {
var substitution = pt.GetSubstitution();
return declaredProperties.Select(m => new SpecializedProperty(pt, m, substitution));
return declaredProperties.Select(m => new SpecializedProperty(m, substitution) { DeclaringType = pt });
} else {
return declaredProperties;
}
@ -216,7 +216,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -216,7 +216,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
ParameterizedType pt = baseType as ParameterizedType;
if (pt != null) {
var substitution = pt.GetSubstitution();
return declaredFields.Select(m => new SpecializedField(pt, m, substitution));
return declaredFields.Select(m => new SpecializedField(m, substitution) { DeclaringType = pt });
} else {
return declaredFields;
}
@ -243,7 +243,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -243,7 +243,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
ParameterizedType pt = baseType as ParameterizedType;
if (pt != null) {
var substitution = pt.GetSubstitution();
return declaredEvents.Select(m => new SpecializedEvent(pt, m, substitution));
return declaredEvents.Select(m => new SpecializedEvent(m, substitution) { DeclaringType = pt });
} else {
return declaredEvents;
}

3
ICSharpCode.NRefactory/TypeSystem/Implementation/KnownTypeCache.cs

@ -36,9 +36,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -36,9 +36,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public IType FindType(KnownTypeCode typeCode)
{
IType type = knownTypes[(int)typeCode];
IType type = LazyInit.VolatileRead(ref knownTypes[(int)typeCode]);
if (type != null) {
LazyInit.ReadBarrier();
return type;
}
return LazyInit.GetOrSet(ref knownTypes[(int)typeCode], SearchType(typeCode));

3
ICSharpCode.NRefactory/TypeSystem/Implementation/MergedNamespace.cs

@ -111,9 +111,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -111,9 +111,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
Dictionary<string, INamespace> GetChildNamespaces()
{
var result = this.childNamespaces;
var result = LazyInit.VolatileRead(ref this.childNamespaces);
if (result != null) {
LazyInit.ReadBarrier();
return result;
} else {
result = new Dictionary<string, INamespace>(compilation.NameComparer);

3
ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleCompilation.cs

@ -110,9 +110,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -110,9 +110,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public INamespace RootNamespace {
get {
INamespace ns = this.rootNamespace;
INamespace ns = LazyInit.VolatileRead(ref this.rootNamespace);
if (ns != null) {
LazyInit.ReadBarrier();
return ns;
} else {
if (referencedAssemblies == null)

23
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs

@ -27,18 +27,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -27,18 +27,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
readonly IEvent eventDefinition;
public SpecializedEvent(IType declaringType, IEvent eventDefinition)
: base(declaringType, eventDefinition)
public SpecializedEvent(IEvent eventDefinition, TypeParameterSubstitution substitution)
: base(eventDefinition)
{
this.eventDefinition = eventDefinition;
Initialize(GetSubstitution(declaringType));
}
internal SpecializedEvent(IType declaringType, IEvent eventDefinition, TypeVisitor substitution)
: base(declaringType, eventDefinition)
{
this.eventDefinition = eventDefinition;
Initialize(substitution);
AddSubstitution(substitution);
this.eventDefinition = (IEvent)base.MemberDefinition;
}
public bool CanAdd {
@ -53,16 +46,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -53,16 +46,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return eventDefinition.CanInvoke; }
}
IMethod addAccessor, removeAccessor, invokeAccessor;
public IMethod AddAccessor {
get { return WrapAccessor(eventDefinition.AddAccessor); }
get { return WrapAccessor(ref this.addAccessor, eventDefinition.AddAccessor); }
}
public IMethod RemoveAccessor {
get { return WrapAccessor(eventDefinition.RemoveAccessor); }
get { return WrapAccessor(ref this.removeAccessor, eventDefinition.RemoveAccessor); }
}
public IMethod InvokeAccessor {
get { return WrapAccessor(eventDefinition.InvokeAccessor); }
get { return WrapAccessor(ref this.invokeAccessor, eventDefinition.InvokeAccessor); }
}
}
}

15
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs

@ -27,18 +27,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -27,18 +27,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
readonly IField fieldDefinition;
public SpecializedField(IType declaringType, IField fieldDefinition)
: base(declaringType, fieldDefinition)
public SpecializedField(IField fieldDefinition, TypeParameterSubstitution substitution)
: base(fieldDefinition)
{
this.fieldDefinition = fieldDefinition;
Initialize(GetSubstitution(declaringType));
}
internal SpecializedField(IType declaringType, IField fieldDefinition, TypeVisitor substitution)
: base(declaringType, fieldDefinition)
{
this.fieldDefinition = fieldDefinition;
Initialize(substitution);
AddSubstitution(substitution);
this.fieldDefinition = (IField)base.MemberDefinition;
}
public bool IsReadOnly {

184
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
@ -31,58 +32,115 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -31,58 +32,115 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// </summary>
public abstract class SpecializedMember : IMember
{
readonly IType declaringType;
readonly IMember memberDefinition;
TypeParameterSubstitution substitution;
IType declaringType;
IType returnType;
protected SpecializedMember(IType declaringType, IMember memberDefinition)
protected SpecializedMember(IMember memberDefinition)
{
if (declaringType == null)
throw new ArgumentNullException("declaringType");
if (memberDefinition == null)
throw new ArgumentNullException("memberDefinition");
this.declaringType = declaringType;
this.memberDefinition = memberDefinition;
SpecializedMember sm = memberDefinition as SpecializedMember;
if (sm != null) {
this.memberDefinition = sm.memberDefinition;
this.substitution = sm.substitution;
} else {
this.memberDefinition = memberDefinition;
this.substitution = TypeParameterSubstitution.Identity;
}
}
protected virtual void Initialize(TypeVisitor substitution)
/// <summary>
/// Performs a substitution. This method may only be called by constructors in derived classes.
/// </summary>
protected void AddSubstitution(TypeParameterSubstitution newSubstitution)
{
this.returnType = Substitute(memberDefinition.ReturnType, substitution);
Debug.Assert(declaringType == null);
Debug.Assert(returnType == null);
this.substitution = TypeParameterSubstitution.Compose(newSubstitution, this.substitution);
}
public virtual IMemberReference ToMemberReference()
public static SpecializedMember Create(IMember memberDefinition, TypeParameterSubstitution substitution)
{
return new SpecializingMemberReference(declaringType.ToTypeReference(), memberDefinition.ToMemberReference());
if (memberDefinition == null) {
return null;
} else if (memberDefinition is IMethod) {
return new SpecializedMethod((IMethod)memberDefinition, substitution);
} else if (memberDefinition is IProperty) {
return new SpecializedProperty((IProperty)memberDefinition, substitution);
} else if (memberDefinition is IField) {
return new SpecializedField((IField)memberDefinition, substitution);
} else if (memberDefinition is IEvent) {
return new SpecializedEvent((IEvent)memberDefinition, substitution);
} else {
throw new NotSupportedException("Unknown IMember: " + memberDefinition);
}
}
internal static TypeVisitor GetSubstitution(IType declaringType)
public IMemberReference ToMemberReference()
{
ParameterizedType pt = declaringType as ParameterizedType;
if (pt != null)
return pt.GetSubstitution();
else
return null;
return new SpecializingMemberReference(
memberDefinition.ToMemberReference(),
ToTypeReference(substitution.ClassTypeArguments),
ToTypeReference(substitution.MethodTypeArguments));
}
internal static IType Substitute(IType type, TypeVisitor substitution)
static IList<ITypeReference> ToTypeReference(IList<IType> typeArguments)
{
if (substitution == null)
return type;
if (typeArguments == null)
return null;
else
return type.AcceptVisitor(substitution);
return typeArguments.Select(t => t.ToTypeReference()).ToArray();
}
internal IMethod WrapAccessor(IMethod accessorDefinition)
internal IMethod WrapAccessor(ref IMethod cachingField, IMethod accessorDefinition)
{
if (accessorDefinition == null)
return null;
var result = LazyInit.VolatileRead(ref cachingField);
if (result != null)
return result;
else
return new SpecializedMethod(declaringType, accessorDefinition);
return LazyInit.GetOrSet(ref cachingField, new SpecializedMethod(accessorDefinition, substitution));
}
/// <summary>
/// Gets the substitution belonging to this specialized member.
/// </summary>
public TypeParameterSubstitution Substitution {
get { return substitution; }
}
public IType DeclaringType {
get { return declaringType; }
get {
var result = LazyInit.VolatileRead(ref this.declaringType);
if (result != null)
return result;
IType definitionDeclaringType = memberDefinition.DeclaringType;
ITypeDefinition definitionDeclaringTypeDef = definitionDeclaringType as ITypeDefinition;
if (definitionDeclaringTypeDef != null && definitionDeclaringType.TypeParameterCount > 0) {
if (substitution.ClassTypeArguments != null && substitution.ClassTypeArguments.Count == definitionDeclaringType.TypeParameterCount) {
result = new ParameterizedType(definitionDeclaringTypeDef, substitution.ClassTypeArguments);
} else {
result = new ParameterizedType(definitionDeclaringTypeDef, definitionDeclaringTypeDef.TypeParameters).AcceptVisitor(substitution);
}
} else {
result = definitionDeclaringType.AcceptVisitor(substitution);
}
return LazyInit.GetOrSet(ref this.declaringType, result);
}
internal set {
// This setter is used as an optimization when the code constructing
// the SpecializedMember already knows the declaring type.
Debug.Assert(this.declaringType == null);
Debug.Assert(value != null);
// As this setter is used only during construction before the member is published
// to other threads, we don't need a volatile write.
this.declaringType = value;
}
}
public IMember MemberDefinition {
@ -94,8 +152,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -94,8 +152,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
public IType ReturnType {
get { return returnType; }
protected set { returnType = value; }
get {
var result = LazyInit.VolatileRead(ref this.returnType);
if (result != null)
return result;
else
return LazyInit.GetOrSet(ref this.returnType, memberDefinition.ReturnType.AcceptVisitor(substitution));
}
protected set {
// This setter is used for LiftedUserDefinedOperator, a special case of specialized member
// (not a normal type parameter substitution).
// As this setter is used only during construction before the member is published
// to other threads, we don't need a volatile write.
this.returnType = value;
}
}
public bool IsVirtual {
@ -143,19 +214,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -143,19 +214,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
var definitionImplementations = memberDefinition.ImplementedInterfaceMembers;
IMember[] result = new IMember[definitionImplementations.Count];
for (int i = 0; i < result.Length; i++) {
result[i] = Specialize(definitionImplementations[i]);
result[i] = SpecializedMember.Create(definitionImplementations[i], substitution);
}
return result;
}
/// <summary>
/// Specialize another member using the same type arguments as this member.
/// </summary>
protected virtual IMember Specialize(IMember otherMember)
{
return SpecializingMemberReference.CreateSpecializedMember(declaringType, memberDefinition, null);
}
public bool IsExplicitInterfaceImplementation {
get { return memberDefinition.IsExplicitInterfaceImplementation; }
}
@ -241,13 +304,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -241,13 +304,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
SpecializedMember other = obj as SpecializedMember;
if (other == null)
return false;
return this.declaringType.Equals(other.declaringType) && this.memberDefinition.Equals(other.memberDefinition);
return this.memberDefinition.Equals(other.memberDefinition) && this.substitution.Equals(other.substitution);
}
public override int GetHashCode()
{
unchecked {
return 1000000007 * declaringType.GetHashCode() + 1000000009 * memberDefinition.GetHashCode();
return 1000000007 * memberDefinition.GetHashCode() + 1000000009 * substitution.GetHashCode();
}
}
@ -256,11 +319,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -256,11 +319,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
StringBuilder b = new StringBuilder("[");
b.Append(GetType().Name);
b.Append(' ');
b.Append(declaringType.ToString());
b.Append(this.DeclaringType.ToString());
b.Append('.');
b.Append(this.Name);
b.Append(':');
b.Append(returnType.ToString());
b.Append(this.ReturnType.ToString());
b.Append(']');
return b.ToString();
}
@ -270,36 +333,48 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -270,36 +333,48 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
IList<IParameter> parameters;
protected SpecializedParameterizedMember(IType declaringType, IParameterizedMember memberDefinition)
: base(declaringType, memberDefinition)
protected SpecializedParameterizedMember(IParameterizedMember memberDefinition)
: base(memberDefinition)
{
}
protected override void Initialize(TypeVisitor substitution)
public IList<IParameter> Parameters {
get {
var result = LazyInit.VolatileRead(ref this.parameters);
if (result != null)
return result;
else
return LazyInit.GetOrSet(ref this.parameters, CreateParameters(this.Substitution));
}
protected set {
// This setter is used for LiftedUserDefinedOperator, a special case of specialized member
// (not a normal type parameter substitution).
// As this setter is used only during construction before the member is published
// to other threads, we don't need a volatile write.
this.parameters = value;
}
}
protected IList<IParameter> CreateParameters(TypeVisitor substitution)
{
base.Initialize(substitution);
var paramDefs = ((IParameterizedMember)this.MemberDefinition).Parameters;
if (paramDefs.Count == 0) {
this.parameters = EmptyList<IParameter>.Instance;
return EmptyList<IParameter>.Instance;
} else {
var parameters = new IParameter[paramDefs.Count];
for (int i = 0; i < parameters.Length; i++) {
IType newType = Substitute(paramDefs[i].Type, substitution);
IType newType = paramDefs[i].Type.AcceptVisitor(substitution);
if (newType != paramDefs[i].Type) {
parameters[i] = new SpecializedParameter(paramDefs[i], newType);
} else {
parameters[i] = paramDefs[i];
}
}
this.parameters = Array.AsReadOnly(parameters);
return Array.AsReadOnly(parameters);
}
}
public IList<IParameter> Parameters {
get { return parameters; }
}
public override string ToString()
{
StringBuilder b = new StringBuilder("[");
@ -309,9 +384,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -309,9 +384,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
b.Append('.');
b.Append(this.Name);
b.Append('(');
for (int i = 0; i < parameters.Count; i++) {
for (int i = 0; i < this.Parameters.Count; i++) {
if (i > 0) b.Append(", ");
b.Append(parameters[i].ToString());
b.Append(this.Parameters[i].ToString());
}
b.Append("):");
b.Append(this.ReturnType.ToString());
@ -326,7 +401,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -326,7 +401,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public SpecializedParameter(IParameter originalParameter, IType newType)
{
this.originalParameter = originalParameter;
if (originalParameter is SpecializedParameter)
this.originalParameter = ((SpecializedParameter)originalParameter).originalParameter;
else
this.originalParameter = originalParameter;
this.newType = newType;
}

103
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs

@ -32,50 +32,36 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -32,50 +32,36 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public class SpecializedMethod : SpecializedParameterizedMember, IMethod
{
readonly IMethod methodDefinition;
readonly IList<IType> typeArguments;
readonly IList<ITypeParameter> specializedTypeParameters;
readonly ITypeParameter[] specializedTypeParameters;
public SpecializedMethod(IType declaringType, IMethod methodDefinition, IList<IType> typeArguments = null)
: this(declaringType, methodDefinition, typeArguments, GetSubstitution(declaringType, typeArguments))
public SpecializedMethod(IMethod methodDefinition, TypeParameterSubstitution substitution)
: base(methodDefinition)
{
}
internal protected SpecializedMethod(IType declaringType, IMethod methodDefinition, IList<IType> typeArguments, TypeVisitor substitution)
: base(declaringType, methodDefinition)
{
if (declaringType == null)
throw new ArgumentNullException("declaringType");
if (methodDefinition == null)
throw new ArgumentNullException("methodDefinition");
// The base ctor might have unpacked a SpecializedMember
// (in case we are specializing an already-specialized method)
methodDefinition = (IMethod)base.MemberDefinition;
this.methodDefinition = methodDefinition;
this.typeArguments = typeArguments ?? EmptyList<IType>.Instance;
if (methodDefinition.TypeParameters.Any(ConstraintNeedsSpecialization)) {
// The method is generic, and we need to specialize the type parameters
specializedTypeParameters = new ITypeParameter[methodDefinition.TypeParameters.Count];
for (int i = 0; i < specializedTypeParameters.Count; i++) {
for (int i = 0; i < specializedTypeParameters.Length; i++) {
ITypeParameter tp = methodDefinition.TypeParameters[i];
if (ConstraintNeedsSpecialization(tp))
tp = new SpecializedTypeParameter(tp, this, substitution);
tp = new SpecializedTypeParameter(tp, this);
specializedTypeParameters[i] = tp;
}
// add substitution that replaces the base method's type parameters with our specialized version
AddSubstitution(new TypeParameterSubstitution(null, specializedTypeParameters));
}
if (typeArguments != null && typeArguments.Count > 0) {
if (typeArguments.Count != methodDefinition.TypeParameters.Count)
throw new ArgumentException("Incorrect number of type arguments");
} else if (specializedTypeParameters != null) {
// No type arguments were specified, but the method is generic.
// -> substitute original type parameters with the specialized ones
substitution = GetSubstitution(declaringType, specializedTypeParameters.ToArray<IType>());
for (int i = 0; i < specializedTypeParameters.Count; i++) {
if (ConstraintNeedsSpecialization(methodDefinition.TypeParameters[i])) {
((SpecializedTypeParameter)specializedTypeParameters[i]).substitution = substitution;
}
// Add the main substitution after the method type parameter specialization.
AddSubstitution(substitution);
if (specializedTypeParameters != null) {
// Set the substitution on the type parameters to the final composed substitution
foreach (var tp in specializedTypeParameters.OfType<SpecializedTypeParameter>()) {
if (tp.Owner == this)
tp.substitution = base.Substitution;
}
}
Initialize(substitution);
}
static bool ConstraintNeedsSpecialization(ITypeParameter tp)
@ -95,53 +81,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -95,53 +81,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return null;
}
public override IMemberReference ToMemberReference()
{
return new SpecializingMemberReference(
this.DeclaringType.ToTypeReference(),
this.MemberDefinition.ToMemberReference(),
typeArguments.Select(ta => ta.ToTypeReference()).ToList()
);
}
protected override IMember Specialize(IMember otherMember)
{
return SpecializingMemberReference.CreateSpecializedMember(this.DeclaringType, this.MemberDefinition, typeArguments);
}
/// <summary>
/// Gets the type arguments passed to this method.
/// If only the type parameters for the class were specified and the generic method
/// itself is not specialized yet, this property will return an empty list.
/// </summary>
public IList<IType> TypeArguments {
get { return typeArguments; }
}
public override int GetHashCode()
{
int hashCode = base.GetHashCode();
unchecked {
for (int i = 0; i < typeArguments.Count; i++) {
hashCode *= 362631391;
hashCode += typeArguments[i].GetHashCode();
}
}
return hashCode;
}
public override bool Equals(object obj)
{
SpecializedMethod other = obj as SpecializedMethod;
if (!base.Equals(other))
return false;
if (typeArguments.Count != other.typeArguments.Count)
return false;
for (int i = 0; i < typeArguments.Count; i++) {
if (!typeArguments[i].Equals(other.typeArguments[i]))
return false;
}
return true;
get { return this.Substitution.MethodTypeArguments ?? EmptyList<IType>.Instance; }
}
public IList<IUnresolvedMethod> Parts {
@ -182,11 +128,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -182,11 +128,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
b.Append(this.DeclaringType.ToString());
b.Append('.');
b.Append(this.Name);
if (typeArguments.Count > 0) {
if (this.TypeArguments.Count > 0) {
b.Append('[');
for (int i = 0; i < typeArguments.Count; i++) {
for (int i = 0; i < this.TypeArguments.Count; i++) {
if (i > 0) b.Append(", ");
b.Append(typeArguments[i].ToString());
b.Append(this.TypeArguments[i].ToString());
}
b.Append(']');
}
@ -205,14 +151,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -205,14 +151,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
readonly ITypeParameter baseTp;
// not readonly: The substition may be replaced at the end of SpecializedMethod constructor
// The substition is set at the end of SpecializedMethod constructor
internal TypeVisitor substitution;
public SpecializedTypeParameter(ITypeParameter baseTp, IMethod specializedOwner, TypeVisitor substitution)
public SpecializedTypeParameter(ITypeParameter baseTp, IMethod specializedOwner)
: base(specializedOwner, baseTp.Index, baseTp.Name, baseTp.Variance, baseTp.Attributes, baseTp.Region)
{
// We don't have to consider already-specialized baseTps because
// we read the baseTp directly from the unpacked memberDefinition.
this.baseTp = baseTp;
this.substitution = substitution;
}
public override int GetHashCode()

21
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs

@ -27,18 +27,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -27,18 +27,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
readonly IProperty propertyDefinition;
public SpecializedProperty(IType declaringType, IProperty propertyDefinition)
: base(declaringType, propertyDefinition)
public SpecializedProperty(IProperty propertyDefinition, TypeParameterSubstitution substitution)
: base(propertyDefinition)
{
this.propertyDefinition = propertyDefinition;
Initialize(GetSubstitution(declaringType));
}
internal SpecializedProperty(IType declaringType, IProperty propertyDefinition, TypeVisitor substitution)
: base(declaringType, propertyDefinition)
{
this.propertyDefinition = propertyDefinition;
Initialize(substitution);
AddSubstitution(substitution);
this.propertyDefinition = (IProperty)base.MemberDefinition;
}
public bool CanGet {
@ -49,12 +42,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -49,12 +42,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return propertyDefinition.CanSet; }
}
IMethod getter, setter;
public IMethod Getter {
get { return WrapAccessor(propertyDefinition.Getter); }
get { return WrapAccessor(ref this.getter, propertyDefinition.Getter); }
}
public IMethod Setter {
get { return WrapAccessor(propertyDefinition.Setter); }
get { return WrapAccessor(ref this.setter, propertyDefinition.Setter); }
}
public bool IsIndexer {

45
ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializingMemberReference.cs

@ -24,50 +24,29 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -24,50 +24,29 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
[Serializable]
public sealed class SpecializingMemberReference : IMemberReference
{
ITypeReference declaringTypeReference;
IMemberReference memberDefinitionReference;
IList<ITypeReference> typeArgumentReferences;
IList<ITypeReference> classTypeArgumentReferences;
IList<ITypeReference> methodTypeArgumentReferences;
public SpecializingMemberReference(ITypeReference declaringTypeReference, IMemberReference memberDefinitionReference, IList<ITypeReference> typeArgumentReferences = null)
public SpecializingMemberReference(IMemberReference memberDefinitionReference, IList<ITypeReference> classTypeArgumentReferences = null, IList<ITypeReference> methodTypeArgumentReferences = null)
{
if (declaringTypeReference == null)
throw new ArgumentNullException("declaringTypeReference");
if (memberDefinitionReference == null)
throw new ArgumentNullException("memberDefinitionReference");
this.declaringTypeReference = declaringTypeReference;
this.memberDefinitionReference = memberDefinitionReference;
this.typeArgumentReferences = typeArgumentReferences;
this.classTypeArgumentReferences = classTypeArgumentReferences;
this.methodTypeArgumentReferences = methodTypeArgumentReferences;
}
public IMember Resolve(ITypeResolveContext context)
{
var declaringType = declaringTypeReference.Resolve(context);
var memberDefinition = memberDefinitionReference.Resolve(context);
IType[] typeArguments = null;
if (typeArgumentReferences != null) {
typeArguments = new IType[typeArgumentReferences.Count];
for (int i = 0; i < typeArguments.Length; i++) {
typeArguments[i] = typeArgumentReferences[i].Resolve(context);
}
}
return CreateSpecializedMember(declaringType, memberDefinition, typeArguments);
}
internal static IMember CreateSpecializedMember(IType declaringType, IMember memberDefinition, IList<IType> typeArguments)
{
if (memberDefinition == null) {
return null;
} else if (memberDefinition is IMethod) {
return new SpecializedMethod(declaringType, (IMethod)memberDefinition, typeArguments);
} else if (memberDefinition is IProperty) {
return new SpecializedProperty(declaringType, (IProperty)memberDefinition);
} else if (memberDefinition is IField) {
return new SpecializedField(declaringType, (IField)memberDefinition);
} else if (memberDefinition is IEvent) {
return new SpecializedEvent(declaringType, (IEvent)memberDefinition);
} else {
throw new NotSupportedException("Unknown IMember: " + memberDefinition);
}
return SpecializedMember.Create(
memberDefinition,
new TypeParameterSubstitution(
classTypeArgumentReferences != null ? classTypeArgumentReferences.Resolve(context) : null,
methodTypeArgumentReferences != null ? methodTypeArgumentReferences.Resolve(context) : null
)
);
}
}
}

94
ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs

@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -27,6 +27,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// </summary>
public class TypeParameterSubstitution : TypeVisitor
{
/// <summary>
/// The identity function.
/// </summary>
public static readonly TypeParameterSubstitution Identity = new TypeParameterSubstitution(null, null);
readonly IList<IType> classTypeArguments;
readonly IList<IType> methodTypeArguments;
@ -47,6 +52,95 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -47,6 +52,95 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
this.methodTypeArguments = methodTypeArguments;
}
/// <summary>
/// Gets the list of class type arguments.
/// Returns <c>null</c> if this substitution keeps class type parameter unmodified.
/// </summary>
public IList<IType> ClassTypeArguments {
get { return classTypeArguments; }
}
public IList<IType> MethodTypeArguments {
get { return methodTypeArguments; }
}
#region Compose
/// <summary>
/// Computes a single TypeParameterSubstitution so that for all types <c>t</c>:
/// <c>t.AcceptVisitor(Compose(g, f)) equals t.AcceptVisitor(f).AcceptVisitor(g)</c>
/// </summary>
/// <remarks>If you consider type parameter substitution to be a function, this is function composition.</remarks>
public static TypeParameterSubstitution Compose(TypeParameterSubstitution g, TypeParameterSubstitution f)
{
if (g == null)
return f;
if (f == null || (f.classTypeArguments == null && f.methodTypeArguments == null))
return g;
// The composition is a copy of 'f', with 'g' applied on the array elements.
// If 'f' has a null list (keeps type parameters unmodified), we have to treat it as
// the identity function, and thus use the list from 'g'.
var classTypeArguments = f.classTypeArguments != null ? GetComposedTypeArguments(f.classTypeArguments, g) : g.classTypeArguments;
var methodTypeArguments = f.methodTypeArguments != null ? GetComposedTypeArguments(f.methodTypeArguments, g) : g.methodTypeArguments;
return new TypeParameterSubstitution(classTypeArguments, methodTypeArguments);
}
static IList<IType> GetComposedTypeArguments(IList<IType> input, TypeParameterSubstitution substitution)
{
IType[] result = new IType[input.Count];
for (int i = 0; i < result.Length; i++) {
result[i] = input[i].AcceptVisitor(substitution);
}
return result;
}
#endregion
#region Equals and GetHashCode implementation
public override bool Equals(object obj)
{
TypeParameterSubstitution other = obj as TypeParameterSubstitution;
if (other == null)
return false;
return TypeListEquals(classTypeArguments, other.classTypeArguments)
&& TypeListEquals(methodTypeArguments, other.methodTypeArguments);
}
public override int GetHashCode()
{
unchecked {
return 1124131 * TypeListHashCode(classTypeArguments) + 1821779 * TypeListHashCode(methodTypeArguments);
}
}
static bool TypeListEquals(IList<IType> a, IList<IType> b)
{
if (a == b)
return true;
if (a == null || b == null)
return false;
if (a.Count != b.Count)
return false;
for (int i = 0; i < a.Count; i++) {
if (!a[i].Equals(b[i]))
return false;
}
return true;
}
static int TypeListHashCode(IList<IType> obj)
{
if (obj == null)
return 0;
unchecked {
int hashCode = 1;
foreach (var element in obj) {
hashCode *= 27;
hashCode += element.GetHashCode();
}
return hashCode;
}
}
#endregion
public override IType VisitTypeParameter(ITypeParameter type)
{
int index = type.Index;

17
ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.TypeSystem
{
@ -50,13 +51,15 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -50,13 +51,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (member == null)
throw new ArgumentNullException("member");
member = member.MemberDefinition;
if (member.IsExplicitInterfaceImplementation && member.ImplementedInterfaceMembers.Count == 1) {
// C#-style explicit interface implementation
yield return member.ImplementedInterfaceMembers[0];
member = member.ImplementedInterfaceMembers[0].MemberDefinition;
member = member.ImplementedInterfaceMembers[0];
yield return member;
}
SpecializedMember specializedMember = member as SpecializedMember;
member = member.MemberDefinition;
IEnumerable<IType> allBaseTypes;
if (includeImplementedInterfaces) {
allBaseTypes = member.DeclaringTypeDefinition.GetAllBaseTypes();
@ -68,8 +71,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -68,8 +71,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
continue;
foreach (IMember baseMember in baseType.GetMembers(m => m.Name == member.Name, GetMemberOptions.IgnoreInheritedMembers)) {
if (SignatureComparer.Ordinal.Equals(member, baseMember))
yield return baseMember;
if (SignatureComparer.Ordinal.Equals(member, baseMember)) {
if (specializedMember != null)
yield return SpecializedMember.Create(baseMember, specializedMember.Substitution);
else
yield return baseMember;
}
}
}
}

23
ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

@ -103,6 +103,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -103,6 +103,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
IEnumeratorOfT,
/// <summary><c>System.Collections.Generic.IList{T}</c></summary>
IListOfT,
/// <summary><c>System.Collections.Generic.IReadOnlyList{T}</c></summary>
IReadOnlyListOfT,
/// <summary><c>System.Threading.Tasks.Task</c></summary>
Task,
/// <summary><c>System.Threading.Tasks.Task{T}</c></summary>
@ -157,6 +159,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -157,6 +159,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
new KnownTypeReference(KnownTypeCode.IEnumerableOfT, "System.Collections.Generic", "IEnumerable", 1),
new KnownTypeReference(KnownTypeCode.IEnumeratorOfT, "System.Collections.Generic", "IEnumerator", 1),
new KnownTypeReference(KnownTypeCode.IListOfT, "System.Collections.Generic", "IList", 1),
new KnownTypeReference(KnownTypeCode.IReadOnlyListOfT, "System.Collections.Generic", "IReadOnlyList", 1),
new KnownTypeReference(KnownTypeCode.Task, "System.Threading.Tasks", "Task"),
new KnownTypeReference(KnownTypeCode.TaskOfT, "System.Threading.Tasks", "Task", 1, baseType: KnownTypeCode.Task),
new KnownTypeReference(KnownTypeCode.NullableOfT, "System", "Nullable", 1, baseType: KnownTypeCode.ValueType),
@ -312,16 +315,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -312,16 +315,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary>
public static readonly KnownTypeReference UIntPtr = Get(KnownTypeCode.UIntPtr);
/// <summary>
/// Gets a type reference pointing to the <c>System.Collections.Generic.IList{T}</c> type.
/// </summary>
public static readonly KnownTypeReference GenericIList = Get(KnownTypeCode.IListOfT);
/// <summary>
/// Gets a type reference pointing to the <c>System.Nullable{T}</c> type.
/// </summary>
public static readonly KnownTypeReference NullableOfT = Get(KnownTypeCode.NullableOfT);
/// <summary>
/// Gets a type reference pointing to the <c>System.Collections.IEnumerable</c> type.
/// </summary>
@ -347,6 +340,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -347,6 +340,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary>
public static readonly KnownTypeReference IListOfT = Get(KnownTypeCode.IListOfT);
/// <summary>
/// Gets a type reference pointing to the <c>System.Collections.Generic.IReadOnlyList{T}</c> type.
/// </summary>
public static readonly KnownTypeReference IReadOnlyListOfT = Get(KnownTypeCode.IReadOnlyListOfT);
/// <summary>
/// Gets a type reference pointing to the <c>System.Threading.Tasks.Task</c> type.
/// </summary>
@ -357,6 +355,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -357,6 +355,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary>
public static readonly KnownTypeReference TaskOfT = Get(KnownTypeCode.TaskOfT);
/// <summary>
/// Gets a type reference pointing to the <c>System.Nullable{T}</c> type.
/// </summary>
public static readonly KnownTypeReference NullableOfT = Get(KnownTypeCode.NullableOfT);
/// <summary>
/// Gets a type reference pointing to the <c>System.IDisposable</c> type.
/// </summary>

7
ICSharpCode.NRefactory/Utils/EmptyList.cs

@ -25,17 +25,20 @@ namespace ICSharpCode.NRefactory @@ -25,17 +25,20 @@ namespace ICSharpCode.NRefactory
{
[Serializable]
public sealed class EmptyList<T> : IList<T>, IEnumerator<T>
#if NET45
, IReadOnlyList<T>
#endif
{
public static readonly EmptyList<T> Instance = new EmptyList<T>();
private EmptyList() {}
T IList<T>.this[int index] {
public T this[int index] {
get { throw new ArgumentOutOfRangeException("index"); }
set { throw new ArgumentOutOfRangeException("index"); }
}
int ICollection<T>.Count {
public int Count {
get { return 0; }
}

14
ICSharpCode.NRefactory/Utils/LazyInit.cs

@ -26,13 +26,15 @@ namespace ICSharpCode.NRefactory.Utils @@ -26,13 +26,15 @@ namespace ICSharpCode.NRefactory.Utils
{
public static class LazyInit
{
static volatile object barrier = null;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "tmp",
Justification = "The volatile read is important to cause a read barrier.")]
public static void ReadBarrier()
public static T VolatileRead<T>(ref T location) where T : class
{
object tmp = barrier;
#if NET45
return Volatile.Read(ref location);
#else
T result = location;
Thread.MemoryBarrier();
return result;
#endif
}
/// <summary>

6
ICSharpCode.NRefactory/Utils/ProjectedList.cs

@ -40,9 +40,8 @@ namespace ICSharpCode.NRefactory.Utils @@ -40,9 +40,8 @@ namespace ICSharpCode.NRefactory.Utils
public TOutput this[int index] {
get {
TOutput output = items[index];
TOutput output = LazyInit.VolatileRead(ref items[index]);
if (output != null) {
LazyInit.ReadBarrier();
return output;
}
return LazyInit.GetOrSet(ref items[index], projection(input[index]));
@ -150,9 +149,8 @@ namespace ICSharpCode.NRefactory.Utils @@ -150,9 +149,8 @@ namespace ICSharpCode.NRefactory.Utils
public TOutput this[int index] {
get {
TOutput output = items[index];
TOutput output = LazyInit.VolatileRead(ref items[index]);
if (output != null) {
LazyInit.ReadBarrier();
return output;
}
return LazyInit.GetOrSet(ref items[index], projection(context, input[index]));

Loading…
Cancel
Save