Browse Source

Phase 2: Merge ICSharpCode.NRefactory into ICSharpCode.Decompiler

pull/728/merge
Siegfried Pammer 9 years ago
parent
commit
284ddfadf1
  1. 96
      ICSharpCode.Decompiler/CSharp/Analysis/ControlFlow.cs
  2. 4
      ICSharpCode.Decompiler/CSharp/Analysis/DefiniteAssignmentAnalysis.cs
  3. 252
      ICSharpCode.Decompiler/CSharp/Ast/IAnnotatable.cs
  4. 47
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/AnyNode.cs
  5. 58
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/AnyNodeOrNull.cs
  6. 50
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/Backreference.cs
  7. 32
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/BacktrackingInfo.cs
  8. 68
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/Choice.cs
  9. 69
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/INode.cs
  10. 100
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/Match.cs
  11. 53
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/NamedNode.cs
  12. 58
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/OptionalNode.cs
  13. 114
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/Pattern.cs
  14. 74
      ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/Repeat.cs
  15. 113
      ICSharpCode.Decompiler/CSharp/Ast/Role.cs
  16. 223
      ICSharpCode.Decompiler/CSharp/Ast/TextLocation.cs
  17. 95
      ICSharpCode.Decompiler/Documentation/DocumentationComment.cs
  18. 71
      ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs
  19. 51
      ICSharpCode.Decompiler/Documentation/IDocumentationProvider.cs
  20. 77
      ICSharpCode.Decompiler/Documentation/IdStringMemberReference.cs
  21. 393
      ICSharpCode.Decompiler/Documentation/IdStringProvider.cs
  22. 422
      ICSharpCode.Decompiler/Documentation/XmlDocumentationProvider.cs
  23. 205
      ICSharpCode.Decompiler/Editor/IDocument.cs
  24. 60
      ICSharpCode.Decompiler/Editor/IDocumentLine.cs
  25. 71
      ICSharpCode.Decompiler/Editor/ISegment.cs
  26. 139
      ICSharpCode.Decompiler/Editor/ITextAnchor.cs
  27. 51
      ICSharpCode.Decompiler/Editor/ITextPasteHandler.cs
  28. 218
      ICSharpCode.Decompiler/Editor/ITextSource.cs
  29. 447
      ICSharpCode.Decompiler/Editor/ReadOnlyDocument.cs
  30. 493
      ICSharpCode.Decompiler/Editor/StringBuilderDocument.cs
  31. 160
      ICSharpCode.Decompiler/Editor/StringTextSource.cs
  32. 118
      ICSharpCode.Decompiler/Editor/TextChangeEventArgs.cs
  33. 130
      ICSharpCode.Decompiler/Editor/TextSourceVersionProvider.cs
  34. 365
      ICSharpCode.Decompiler/Editor/UnicodeNewline.cs
  35. 58
      ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs
  36. 203
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  37. 51
      ICSharpCode.Decompiler/Semantics/AmbiguousResolveResult.cs
  38. 50
      ICSharpCode.Decompiler/Semantics/ArrayAccessResolveResult.cs
  39. 60
      ICSharpCode.Decompiler/Semantics/ArrayCreateResolveResult.cs
  40. 66
      ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs
  41. 55
      ICSharpCode.Decompiler/Semantics/ConstantResolveResult.cs
  42. 568
      ICSharpCode.Decompiler/Semantics/Conversion.cs
  43. 68
      ICSharpCode.Decompiler/Semantics/ConversionResolveResult.cs
  44. 56
      ICSharpCode.Decompiler/Semantics/ErrorResolveResult.cs
  45. 90
      ICSharpCode.Decompiler/Semantics/ForEachResolveResult.cs
  46. 34
      ICSharpCode.Decompiler/Semantics/InitializedObjectResolveResult.cs
  47. 75
      ICSharpCode.Decompiler/Semantics/InvocationResolveResult.cs
  48. 77
      ICSharpCode.Decompiler/Semantics/LocalResolveResult.cs
  49. 148
      ICSharpCode.Decompiler/Semantics/MemberResolveResult.cs
  50. 81
      ICSharpCode.Decompiler/Semantics/NamedArgumentResolveResult.cs
  51. 50
      ICSharpCode.Decompiler/Semantics/NamespaceResolveResult.cs
  52. 90
      ICSharpCode.Decompiler/Semantics/OperatorResolveResult.cs
  53. 78
      ICSharpCode.Decompiler/Semantics/ResolveResult.cs
  54. 66
      ICSharpCode.Decompiler/Semantics/SizeOfResolveResult.cs
  55. 44
      ICSharpCode.Decompiler/Semantics/ThisResolveResult.cs
  56. 47
      ICSharpCode.Decompiler/Semantics/TypeIsResolveResult.cs
  57. 46
      ICSharpCode.Decompiler/Semantics/TypeOfResolveResult.cs
  58. 47
      ICSharpCode.Decompiler/Semantics/TypeResolveResult.cs
  59. 122
      ICSharpCode.Decompiler/Semantics/UnknownMemberResolveResult.cs
  60. 4
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  61. 117
      ICSharpCode.Decompiler/TypeSystem/Accessibility.cs
  62. 221
      ICSharpCode.Decompiler/TypeSystem/AnonymousType.cs
  63. 200
      ICSharpCode.Decompiler/TypeSystem/ArrayType.cs
  64. 94
      ICSharpCode.Decompiler/TypeSystem/AssemblyLoader.cs
  65. 79
      ICSharpCode.Decompiler/TypeSystem/AssemblyQualifiedTypeName.cs
  66. 112
      ICSharpCode.Decompiler/TypeSystem/ByReferenceType.cs
  67. 63
      ICSharpCode.Decompiler/TypeSystem/ComHelper.cs
  68. 86
      ICSharpCode.Decompiler/TypeSystem/DefaultSolutionSnapshot.cs
  69. 230
      ICSharpCode.Decompiler/TypeSystem/DomRegion.cs
  70. 63
      ICSharpCode.Decompiler/TypeSystem/EntityType.cs
  71. 139
      ICSharpCode.Decompiler/TypeSystem/Error.cs
  72. 315
      ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs
  73. 107
      ICSharpCode.Decompiler/TypeSystem/IAmbience.cs
  74. 128
      ICSharpCode.Decompiler/TypeSystem/IAssembly.cs
  75. 75
      ICSharpCode.Decompiler/TypeSystem/IAttribute.cs
  76. 38
      ICSharpCode.Decompiler/TypeSystem/ICodeContext.cs
  77. 91
      ICSharpCode.Decompiler/TypeSystem/ICompilation.cs
  78. 38
      ICSharpCode.Decompiler/TypeSystem/IConstantValue.cs
  79. 178
      ICSharpCode.Decompiler/TypeSystem/IEntity.cs
  80. 58
      ICSharpCode.Decompiler/TypeSystem/IEvent.cs
  81. 99
      ICSharpCode.Decompiler/TypeSystem/IField.cs
  82. 35
      ICSharpCode.Decompiler/TypeSystem/IFreezable.cs
  83. 102
      ICSharpCode.Decompiler/TypeSystem/IInterningProvider.cs
  84. 196
      ICSharpCode.Decompiler/TypeSystem/IMember.cs
  85. 168
      ICSharpCode.Decompiler/TypeSystem/IMethod.cs
  86. 66
      ICSharpCode.Decompiler/TypeSystem/INamedElement.cs
  87. 88
      ICSharpCode.Decompiler/TypeSystem/INamespace.cs
  88. 104
      ICSharpCode.Decompiler/TypeSystem/IParameter.cs
  89. 40
      ICSharpCode.Decompiler/TypeSystem/IParameterizedMember.cs
  90. 159
      ICSharpCode.Decompiler/TypeSystem/IProjectContent.cs
  91. 62
      ICSharpCode.Decompiler/TypeSystem/IProperty.cs
  92. 43
      ICSharpCode.Decompiler/TypeSystem/ISolutionSnapshot.cs
  93. 39
      ICSharpCode.Decompiler/TypeSystem/ISupportsInterning.cs
  94. 100
      ICSharpCode.Decompiler/TypeSystem/ISymbol.cs
  95. 350
      ICSharpCode.Decompiler/TypeSystem/IType.cs
  96. 170
      ICSharpCode.Decompiler/TypeSystem/ITypeDefinition.cs
  97. 151
      ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs
  98. 73
      ICSharpCode.Decompiler/TypeSystem/ITypeReference.cs
  99. 80
      ICSharpCode.Decompiler/TypeSystem/IUnresolvedFile.cs
  100. 54
      ICSharpCode.Decompiler/TypeSystem/IVariable.cs
  101. Some files were not shown because too many files have changed in this diff Show More

96
ICSharpCode.Decompiler/CSharp/Analysis/ControlFlow.cs

@ -734,53 +734,53 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -734,53 +734,53 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
/// <summary>
/// Debugging helper that exports a control flow graph.
/// </summary>
public static GraphVizGraph ExportGraph(IList<ControlFlowNode> nodes)
{
GraphVizGraph g = new GraphVizGraph();
GraphVizNode[] n = new GraphVizNode[nodes.Count];
Dictionary<ControlFlowNode, int> dict = new Dictionary<ControlFlowNode, int>();
for (int i = 0; i < n.Length; i++) {
dict.Add(nodes[i], i);
n[i] = new GraphVizNode(i);
string name = "#" + i + " = ";
switch (nodes[i].Type) {
case ControlFlowNodeType.StartNode:
case ControlFlowNodeType.BetweenStatements:
name += nodes[i].NextStatement.DebugToString();
break;
case ControlFlowNodeType.EndNode:
name += "End of " + nodes[i].PreviousStatement.DebugToString();
break;
case ControlFlowNodeType.LoopCondition:
name += "Condition in " + nodes[i].NextStatement.DebugToString();
break;
default:
name += "?";
break;
}
n[i].label = name;
g.AddNode(n[i]);
}
for (int i = 0; i < n.Length; i++) {
foreach (ControlFlowEdge edge in nodes[i].Outgoing) {
GraphVizEdge ge = new GraphVizEdge(i, dict[edge.To]);
if (edge.IsLeavingTryFinally)
ge.style = "dashed";
switch (edge.Type) {
case ControlFlowEdgeType.ConditionTrue:
ge.color = "green";
break;
case ControlFlowEdgeType.ConditionFalse:
ge.color = "red";
break;
case ControlFlowEdgeType.Jump:
ge.color = "blue";
break;
}
g.AddEdge(ge);
}
}
return g;
}
//public static GraphVizGraph ExportGraph(IList<ControlFlowNode> nodes)
//{
// GraphVizGraph g = new GraphVizGraph();
// GraphVizNode[] n = new GraphVizNode[nodes.Count];
// Dictionary<ControlFlowNode, int> dict = new Dictionary<ControlFlowNode, int>();
// for (int i = 0; i < n.Length; i++) {
// dict.Add(nodes[i], i);
// n[i] = new GraphVizNode(i);
// string name = "#" + i + " = ";
// switch (nodes[i].Type) {
// case ControlFlowNodeType.StartNode:
// case ControlFlowNodeType.BetweenStatements:
// name += nodes[i].NextStatement.DebugToString();
// break;
// case ControlFlowNodeType.EndNode:
// name += "End of " + nodes[i].PreviousStatement.DebugToString();
// break;
// case ControlFlowNodeType.LoopCondition:
// name += "Condition in " + nodes[i].NextStatement.DebugToString();
// break;
// default:
// name += "?";
// break;
// }
// n[i].label = name;
// g.AddNode(n[i]);
// }
// for (int i = 0; i < n.Length; i++) {
// foreach (ControlFlowEdge edge in nodes[i].Outgoing) {
// GraphVizEdge ge = new GraphVizEdge(i, dict[edge.To]);
// if (edge.IsLeavingTryFinally)
// ge.style = "dashed";
// switch (edge.Type) {
// case ControlFlowEdgeType.ConditionTrue:
// ge.color = "green";
// break;
// case ControlFlowEdgeType.ConditionFalse:
// ge.color = "red";
// break;
// case ControlFlowEdgeType.Jump:
// ge.color = "blue";
// break;
// }
// g.AddEdge(ge);
// }
// }
// return g;
//}
}
}

4
ICSharpCode.Decompiler/CSharp/Analysis/DefiniteAssignmentAnalysis.cs

@ -233,7 +233,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -233,7 +233,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
return conditionNodeDict[statement].NodeStatus;
}
/// <summary>
/*/// <summary>
/// Exports the CFG. This method is intended to help debugging issues related to definite assignment.
/// </summary>
public GraphVizGraph ExportGraph()
@ -279,7 +279,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -279,7 +279,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
}
}
return g;
}
}*/
static DefiniteAssignmentStatus MergeStatus(DefiniteAssignmentStatus a, DefiniteAssignmentStatus b)
{

252
ICSharpCode.Decompiler/CSharp/Ast/IAnnotatable.cs

@ -0,0 +1,252 @@ @@ -0,0 +1,252 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace ICSharpCode.NRefactory
{
/// <summary>
/// Provides an interface to handle annotations in an object.
/// </summary>
public interface IAnnotatable
{
/// <summary>
/// Gets all annotations stored on this IAnnotatable.
/// </summary>
IEnumerable<object> Annotations {
get;
}
/// <summary>
/// Gets the first annotation of the specified type.
/// Returns null if no matching annotation exists.
/// </summary>
/// <typeparam name='T'>
/// The type of the annotation.
/// </typeparam>
T Annotation<T> () where T: class;
/// <summary>
/// Gets the first annotation of the specified type.
/// Returns null if no matching annotation exists.
/// </summary>
/// <param name='type'>
/// The type of the annotation.
/// </param>
object Annotation (Type type);
/// <summary>
/// Adds an annotation to this instance.
/// </summary>
/// <param name='annotation'>
/// The annotation to add.
/// </param>
void AddAnnotation (object annotation);
/// <summary>
/// Removes all annotations of the specified type.
/// </summary>
/// <typeparam name='T'>
/// The type of the annotations to remove.
/// </typeparam>
void RemoveAnnotations<T> () where T : class;
/// <summary>
/// Removes all annotations of the specified type.
/// </summary>
/// <param name='type'>
/// The type of the annotations to remove.
/// </param>
void RemoveAnnotations(Type type);
}
/// <summary>
/// Base class used to implement the IAnnotatable interface.
/// This implementation is thread-safe.
/// </summary>
[Serializable]
public abstract class AbstractAnnotatable : IAnnotatable
{
// Annotations: points either null (no annotations), to the single annotation,
// or to an AnnotationList.
// Once it is pointed at an AnnotationList, it will never change (this allows thread-safety support by locking the list)
object annotations;
/// <summary>
/// Clones all annotations.
/// This method is intended to be called by Clone() implementations in derived classes.
/// <code>
/// AstNode copy = (AstNode)MemberwiseClone();
/// copy.CloneAnnotations();
/// </code>
/// </summary>
protected void CloneAnnotations()
{
ICloneable cloneable = annotations as ICloneable;
if (cloneable != null)
annotations = cloneable.Clone();
}
sealed class AnnotationList : List<object>, ICloneable
{
// There are two uses for this custom list type:
// 1) it's private, and thus (unlike List<object>) cannot be confused with real annotations
// 2) It allows us to simplify the cloning logic by making the list behave the same as a clonable annotation.
public AnnotationList (int initialCapacity) : base(initialCapacity)
{
}
public object Clone ()
{
lock (this) {
AnnotationList copy = new AnnotationList (this.Count);
for (int i = 0; i < this.Count; i++) {
object obj = this [i];
ICloneable c = obj as ICloneable;
copy.Add (c != null ? c.Clone () : obj);
}
return copy;
}
}
}
public virtual void AddAnnotation (object annotation)
{
if (annotation == null)
throw new ArgumentNullException ("annotation");
retry: // Retry until successful
object oldAnnotation = Interlocked.CompareExchange (ref this.annotations, annotation, null);
if (oldAnnotation == null) {
return; // we successfully added a single annotation
}
AnnotationList list = oldAnnotation as AnnotationList;
if (list == null) {
// we need to transform the old annotation into a list
list = new AnnotationList (4);
list.Add (oldAnnotation);
list.Add (annotation);
if (Interlocked.CompareExchange (ref this.annotations, list, oldAnnotation) != oldAnnotation) {
// the transformation failed (some other thread wrote to this.annotations first)
goto retry;
}
} else {
// once there's a list, use simple locking
lock (list) {
list.Add (annotation);
}
}
}
public virtual void RemoveAnnotations<T> () where T : class
{
retry: // Retry until successful
object oldAnnotations = this.annotations;
AnnotationList list = oldAnnotations as AnnotationList;
if (list != null) {
lock (list)
list.RemoveAll (obj => obj is T);
} else if (oldAnnotations is T) {
if (Interlocked.CompareExchange (ref this.annotations, null, oldAnnotations) != oldAnnotations) {
// Operation failed (some other thread wrote to this.annotations first)
goto retry;
}
}
}
public virtual void RemoveAnnotations (Type type)
{
if (type == null)
throw new ArgumentNullException ("type");
retry: // Retry until successful
object oldAnnotations = this.annotations;
AnnotationList list = oldAnnotations as AnnotationList;
if (list != null) {
lock (list)
list.RemoveAll(type.IsInstanceOfType);
} else if (type.IsInstanceOfType (oldAnnotations)) {
if (Interlocked.CompareExchange (ref this.annotations, null, oldAnnotations) != oldAnnotations) {
// Operation failed (some other thread wrote to this.annotations first)
goto retry;
}
}
}
public T Annotation<T> () where T: class
{
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
lock (list) {
foreach (object obj in list) {
T t = obj as T;
if (t != null)
return t;
}
return null;
}
} else {
return annotations as T;
}
}
public object Annotation (Type type)
{
if (type == null)
throw new ArgumentNullException ("type");
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
lock (list) {
foreach (object obj in list) {
if (type.IsInstanceOfType (obj))
return obj;
}
}
} else {
if (type.IsInstanceOfType (annotations))
return annotations;
}
return null;
}
/// <summary>
/// Gets all annotations stored on this AstNode.
/// </summary>
public IEnumerable<object> Annotations {
get {
object annotations = this.annotations;
AnnotationList list = annotations as AnnotationList;
if (list != null) {
lock (list) {
return list.ToArray ();
}
} else {
if (annotations != null)
return new object[] { annotations };
else
return Enumerable.Empty<object> ();
}
}
}
}
}

47
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/AnyNode.cs

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
// Copyright (c) 2011-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.PatternMatching
{
/// <summary>
/// Matches any node.
/// </summary>
/// <remarks>Does not match null nodes.</remarks>
public class AnyNode : Pattern
{
readonly string groupName;
public string GroupName {
get { return groupName; }
}
public AnyNode(string groupName = null)
{
this.groupName = groupName;
}
public override bool DoMatch(INode other, Match match)
{
match.Add(this.groupName, other);
return other != null && !other.IsNull;
}
}
}

58
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/AnyNodeOrNull.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
//
// AnyNodeOrNull.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.PatternMatching
{
/// <summary>
/// Matches any node.
/// </summary>
/// <remarks>Does not match null nodes.</remarks>
public class AnyNodeOrNull : Pattern
{
readonly string groupName;
public string GroupName {
get { return groupName; }
}
public AnyNodeOrNull(string groupName = null)
{
this.groupName = groupName;
}
public override bool DoMatch(INode other, Match match)
{
if (other == null) {
match.AddNull(this.groupName);
} else {
match.Add(this.groupName, other);
}
return true;
}
}
}

50
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/Backreference.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// Copyright (c) 2011-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
namespace ICSharpCode.NRefactory.PatternMatching
{
/// <summary>
/// Matches the last entry in the specified named group.
/// </summary>
public class Backreference : Pattern
{
readonly string referencedGroupName;
public string ReferencedGroupName {
get { return referencedGroupName; }
}
public Backreference(string referencedGroupName)
{
if (referencedGroupName == null)
throw new ArgumentNullException("referencedGroupName");
this.referencedGroupName = referencedGroupName;
}
public override bool DoMatch(INode other, Match match)
{
var last = match.Get (referencedGroupName).Last ();
if (last == null && other == null)
return true;
return last.IsMatch(other);
}
}
}

32
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/BacktrackingInfo.cs

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

68
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/Choice.cs

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
// Copyright (c) 2011-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.PatternMatching
{
/// <summary>
/// Matches one of several alternatives.
/// </summary>
public class Choice : Pattern, IEnumerable<INode>
{
readonly List<INode> alternatives = new List<INode>();
public void Add(string name, INode alternative)
{
if (alternative == null)
throw new ArgumentNullException("alternative");
alternatives.Add(new NamedNode(name, alternative));
}
public void Add(INode alternative)
{
if (alternative == null)
throw new ArgumentNullException("alternative");
alternatives.Add(alternative);
}
public override bool DoMatch(INode other, Match match)
{
var checkPoint = match.CheckPoint();
foreach (INode alt in alternatives) {
if (alt.DoMatch(other, match))
return true;
else
match.RestoreCheckPoint(checkPoint);
}
return false;
}
IEnumerator<INode> IEnumerable<INode>.GetEnumerator()
{
return alternatives.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return alternatives.GetEnumerator();
}
}
}

69
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/INode.cs

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
// Copyright (c) 2011-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.PatternMatching
{
/// <summary>
/// AST node that supports pattern matching.
/// </summary>
public interface INode
{
Role Role { get; }
INode FirstChild { get; }
INode NextSibling { get; }
bool IsNull { get; }
bool DoMatch(INode other, Match match);
bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo);
}
public static class PatternExtensions
{
/// <summary>
/// Performs a pattern matching operation.
/// <c>this</c> is the pattern, <paramref name="other"/> is the AST that is being matched.
/// </summary>
/// <returns>
/// A match object. Check <see cref="PatternMatching.Match.Success"/> to see whether the match was successful.
/// </returns>
/// <remarks>
/// Patterns are ASTs that contain special pattern nodes (from the PatternMatching namespace).
/// However, it is also possible to match two ASTs without any pattern nodes -
/// doing so will produce a successful match if the two ASTs are structurally identical.
/// </remarks>
public static Match Match(this INode pattern, INode other)
{
if (pattern == null)
throw new ArgumentNullException("pattern");
Match match = PatternMatching.Match.CreateNew();
if (pattern.DoMatch(other, match))
return match;
else
return default(PatternMatching.Match);
}
public static bool IsMatch(this INode pattern, INode other)
{
if (pattern == null)
throw new ArgumentNullException("pattern");
return pattern.DoMatch(other, PatternMatching.Match.CreateNew());
}
}
}

100
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/Match.cs

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
// Copyright (c) 2011-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.NRefactory.PatternMatching
{
/// <summary>
/// Represents the result of a pattern matching operation.
/// </summary>
public struct Match
{
// TODO: maybe we should add an implicit Match->bool conversion? (implicit operator bool(Match m) { return m != null; })
List<KeyValuePair<string, INode>> results;
public bool Success {
get { return results != null; }
}
internal static Match CreateNew()
{
Match m;
m.results = new List<KeyValuePair<string, INode>>();
return m;
}
internal int CheckPoint()
{
return results.Count;
}
internal void RestoreCheckPoint(int checkPoint)
{
results.RemoveRange(checkPoint, results.Count - checkPoint);
}
public IEnumerable<INode> Get(string groupName)
{
if (results == null)
yield break;
foreach (var pair in results) {
if (pair.Key == groupName)
yield return pair.Value;
}
}
public IEnumerable<T> Get<T>(string groupName) where T : INode
{
if (results == null)
yield break;
foreach (var pair in results) {
if (pair.Key == groupName)
yield return (T)pair.Value;
}
}
public bool Has(string groupName)
{
if (results == null)
return false;
foreach (var pair in results) {
if (pair.Key == groupName)
return true;
}
return false;
}
public void Add(string groupName, INode node)
{
if (groupName != null && node != null) {
results.Add(new KeyValuePair<string, INode>(groupName, node));
}
}
internal void AddNull (string groupName)
{
if (groupName != null) {
results.Add(new KeyValuePair<string, INode>(groupName, null));
}
}
}
}

53
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/NamedNode.cs

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
// Copyright (c) 2011-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.PatternMatching
{
/// <summary>
/// Represents a named node within a pattern.
/// </summary>
public class NamedNode : Pattern
{
readonly string groupName;
readonly INode childNode;
public string GroupName {
get { return groupName; }
}
public INode ChildNode {
get { return childNode; }
}
public NamedNode(string groupName, INode childNode)
{
if (childNode == null)
throw new ArgumentNullException("childNode");
this.groupName = groupName;
this.childNode = childNode;
}
public override bool DoMatch(INode other, Match match)
{
match.Add(this.groupName, other);
return childNode.DoMatch(other, match);
}
}
}

58
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/OptionalNode.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
// Copyright (c) 2011-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ICSharpCode.NRefactory.PatternMatching
{
public class OptionalNode : Pattern
{
readonly INode childNode;
public INode ChildNode {
get { return childNode; }
}
public OptionalNode(INode childNode)
{
if (childNode == null)
throw new ArgumentNullException("childNode");
this.childNode = childNode;
}
public OptionalNode(string groupName, INode childNode) : this(new NamedNode(groupName, childNode))
{
}
public override bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo)
{
backtrackingInfo.backtrackingStack.Push(new PossibleMatch(pos, match.CheckPoint()));
return childNode.DoMatch(pos, match);
}
public override bool DoMatch(INode other, Match match)
{
if (other == null || other.IsNull)
return true;
else
return childNode.DoMatch(other, match);
}
}
}

114
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/Pattern.cs

@ -0,0 +1,114 @@ @@ -0,0 +1,114 @@
// Copyright (c) 2011-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace ICSharpCode.NRefactory.PatternMatching
{
/// <summary>
/// Base class for all patterns.
/// </summary>
public abstract class Pattern : INode
{
/// <summary>
/// Gets the string that matches any string.
/// </summary>
public static readonly string AnyString = "$any$";
public static bool MatchString(string pattern, string text)
{
return pattern == AnyString || pattern == text;
}
internal struct PossibleMatch
{
public readonly INode NextOther; // next node after the last matched node
public readonly int Checkpoint; // checkpoint
public PossibleMatch(INode nextOther, int checkpoint)
{
this.NextOther = nextOther;
this.Checkpoint = checkpoint;
}
}
bool INode.IsNull {
get { return false; }
}
Role INode.Role {
get { return null; }
}
INode INode.NextSibling {
get { return null; }
}
INode INode.FirstChild {
get { return null; }
}
public abstract bool DoMatch(INode other, Match match);
public virtual bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo)
{
return DoMatch (pos, match);
}
public static bool DoMatchCollection(Role role, INode firstPatternChild, INode firstOtherChild, Match match)
{
BacktrackingInfo backtrackingInfo = new BacktrackingInfo();
Stack<INode> patternStack = new Stack<INode>();
Stack<PossibleMatch> stack = backtrackingInfo.backtrackingStack;
patternStack.Push(firstPatternChild);
stack.Push(new PossibleMatch(firstOtherChild, match.CheckPoint()));
while (stack.Count > 0) {
INode cur1 = patternStack.Pop();
INode cur2 = stack.Peek().NextOther;
match.RestoreCheckPoint(stack.Pop().Checkpoint);
bool success = true;
while (cur1 != null && success) {
while (cur1 != null && cur1.Role != role)
cur1 = cur1.NextSibling;
while (cur2 != null && cur2.Role != role)
cur2 = cur2.NextSibling;
if (cur1 == null)
break;
Debug.Assert(stack.Count == patternStack.Count);
success = cur1.DoMatchCollection(role, cur2, match, backtrackingInfo);
Debug.Assert(stack.Count >= patternStack.Count);
while (stack.Count > patternStack.Count)
patternStack.Push(cur1.NextSibling);
cur1 = cur1.NextSibling;
if (cur2 != null)
cur2 = cur2.NextSibling;
}
while (cur2 != null && cur2.Role != role)
cur2 = cur2.NextSibling;
if (success && cur2 == null)
return true;
}
return false;
}
}
}

74
ICSharpCode.Decompiler/CSharp/Ast/PatternMatching/Repeat.cs

@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
// Copyright (c) 2011-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ICSharpCode.NRefactory.PatternMatching
{
/// <summary>
/// Represents an optional node.
/// </summary>
public class Repeat : Pattern
{
readonly INode childNode;
public int MinCount { get; set; }
public int MaxCount { get; set; }
public INode ChildNode {
get { return childNode; }
}
public Repeat(INode childNode)
{
if (childNode == null)
throw new ArgumentNullException("childNode");
this.childNode = childNode;
this.MinCount = 0;
this.MaxCount = int.MaxValue;
}
public override bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo)
{
var backtrackingStack = backtrackingInfo.backtrackingStack;
Debug.Assert(pos == null || pos.Role == role);
int matchCount = 0;
if (this.MinCount <= 0)
backtrackingStack.Push(new PossibleMatch(pos, match.CheckPoint()));
while (matchCount < this.MaxCount && pos != null && childNode.DoMatch(pos, match)) {
matchCount++;
do {
pos = pos.NextSibling;
} while (pos != null && pos.Role != role);
if (matchCount >= this.MinCount)
backtrackingStack.Push(new PossibleMatch(pos, match.CheckPoint()));
}
return false; // never do a normal (single-element) match; always make the caller look at the results on the back-tracking stack.
}
public override bool DoMatch(INode other, Match match)
{
if (other == null || other.IsNull)
return this.MinCount <= 0;
else
return this.MaxCount >= 1 && childNode.DoMatch(other, match);
}
}
}

113
ICSharpCode.Decompiler/CSharp/Ast/Role.cs

@ -0,0 +1,113 @@ @@ -0,0 +1,113 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Threading;
namespace ICSharpCode.NRefactory
{
/// <summary>
/// Represents the role a node plays within its parent.
/// </summary>
public abstract class Role
{
public const int RoleIndexBits = 9;
static readonly Role[] roles = new Role[1 << RoleIndexBits];
static int nextRoleIndex = 0;
readonly uint index;
[CLSCompliant(false)]
public uint Index {
get { return index; }
}
// don't allow NRefactory consumers to derive from Role
internal Role()
{
this.index = (uint)Interlocked.Increment(ref nextRoleIndex);
if (this.index >= roles.Length)
throw new InvalidOperationException("Too many roles");
roles[this.index] = this;
}
/// <summary>
/// Gets whether the specified node is valid in this role.
/// </summary>
public abstract bool IsValid(object node);
/// <summary>
/// Gets the role with the specified index.
/// </summary>
[CLSCompliant(false)]
public static Role GetByIndex(uint index)
{
return roles[index];
}
}
/// <summary>
/// Represents the role a node plays within its parent.
/// All nodes with this role have type T.
/// </summary>
public class Role<T> : Role where T : class
{
readonly string name; // helps with debugging the AST
readonly T nullObject;
/// <summary>
/// Gets the null object used when there's no node with this role.
/// Not every role has a null object; this property returns null for roles without a null object.
/// </summary>
/// <remarks>
/// Roles used for non-collections should always have a null object, so that no AST property returns null.
/// However, if a role used for collections only, it may leave out the null object.
/// </remarks>
public T NullObject {
get { return nullObject; }
}
public override bool IsValid(object node)
{
return node is T;
}
public Role(string name)
{
if (name == null)
throw new ArgumentNullException("name");
this.name = name;
}
public Role(string name, T nullObject)
{
if (name == null)
throw new ArgumentNullException("name");
if (nullObject == null)
throw new ArgumentNullException ("nullObject");
this.nullObject = nullObject;
this.name = name;
}
public override string ToString()
{
return name;
}
}
}

223
ICSharpCode.Decompiler/CSharp/Ast/TextLocation.cs

@ -0,0 +1,223 @@ @@ -0,0 +1,223 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel;
using System.Globalization;
namespace ICSharpCode.NRefactory
{
/// <summary>
/// A line/column position.
/// Text editor lines/columns are counted started from one.
/// </summary>
/// <remarks>
/// The document provides the methods <see cref="Editor.IDocument.GetLocation"/> and
/// <see cref="Editor.IDocument.GetOffset(TextLocation)"/> to convert between offsets and TextLocations.
/// </remarks>
[Serializable]
[TypeConverter(typeof(TextLocationConverter))]
public struct TextLocation : IComparable<TextLocation>, IEquatable<TextLocation>
{
/// <summary>
/// Represents no text location (0, 0).
/// </summary>
public static readonly TextLocation Empty = new TextLocation(0, 0);
/// <summary>
/// Constant of the minimum line.
/// </summary>
public const int MinLine = 1;
/// <summary>
/// Constant of the minimum column.
/// </summary>
public const int MinColumn = 1;
/// <summary>
/// Creates a TextLocation instance.
/// </summary>
public TextLocation(int line, int column)
{
this.line = line;
this.column = column;
}
int column, line;
/// <summary>
/// Gets the line number.
/// </summary>
public int Line {
get { return line; }
}
/// <summary>
/// Gets the column number.
/// </summary>
public int Column {
get { return column; }
}
/// <summary>
/// Gets whether the TextLocation instance is empty.
/// </summary>
public bool IsEmpty {
get {
return column < MinLine && line < MinColumn;
}
}
/// <summary>
/// Gets a string representation for debugging purposes.
/// </summary>
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "(Line {1}, Col {0})", this.column, this.line);
}
/// <summary>
/// Gets a hash code.
/// </summary>
public override int GetHashCode()
{
return unchecked (191 * column.GetHashCode() ^ line.GetHashCode());
}
/// <summary>
/// Equality test.
/// </summary>
public override bool Equals(object obj)
{
if (!(obj is TextLocation)) return false;
return (TextLocation)obj == this;
}
/// <summary>
/// Equality test.
/// </summary>
public bool Equals(TextLocation other)
{
return this == other;
}
/// <summary>
/// Equality test.
/// </summary>
public static bool operator ==(TextLocation left, TextLocation right)
{
return left.column == right.column && left.line == right.line;
}
/// <summary>
/// Inequality test.
/// </summary>
public static bool operator !=(TextLocation left, TextLocation right)
{
return left.column != right.column || left.line != right.line;
}
/// <summary>
/// Compares two text locations.
/// </summary>
public static bool operator <(TextLocation left, TextLocation right)
{
if (left.line < right.line)
return true;
else if (left.line == right.line)
return left.column < right.column;
else
return false;
}
/// <summary>
/// Compares two text locations.
/// </summary>
public static bool operator >(TextLocation left, TextLocation right)
{
if (left.line > right.line)
return true;
else if (left.line == right.line)
return left.column > right.column;
else
return false;
}
/// <summary>
/// Compares two text locations.
/// </summary>
public static bool operator <=(TextLocation left, TextLocation right)
{
return !(left > right);
}
/// <summary>
/// Compares two text locations.
/// </summary>
public static bool operator >=(TextLocation left, TextLocation right)
{
return !(left < right);
}
/// <summary>
/// Compares two text locations.
/// </summary>
public int CompareTo(TextLocation other)
{
if (this == other)
return 0;
if (this < other)
return -1;
else
return 1;
}
}
public class TextLocationConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(TextLocation) || base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string) {
string[] parts = ((string)value).Split(';', ',');
if (parts.Length == 2) {
return new TextLocation(int.Parse(parts[0]), int.Parse(parts[1]));
}
}
return base.ConvertFrom(context, culture, value);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (value is TextLocation) {
var loc = (TextLocation)value;
return loc.Line + ";" + loc.Column;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}

95
ICSharpCode.Decompiler/Documentation/DocumentationComment.cs

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Documentation
{
/// <summary>
/// Represents a documentation comment.
/// </summary>
public class DocumentationComment
{
ITextSource xml;
protected readonly ITypeResolveContext context;
/// <summary>
/// Gets the XML code for this documentation comment.
/// </summary>
public ITextSource Xml {
get { return xml; }
}
/// <summary>
/// Creates a new DocumentationComment.
/// </summary>
/// <param name="xml">The XML text.</param>
/// <param name="context">Context for resolving cref attributes.</param>
public DocumentationComment(ITextSource xml, ITypeResolveContext context)
{
if (xml == null)
throw new ArgumentNullException("xml");
if (context == null)
throw new ArgumentNullException("context");
this.xml = xml;
this.context = context;
}
/// <summary>
/// Creates a new DocumentationComment.
/// </summary>
/// <param name="xml">The XML text.</param>
/// <param name="context">Context for resolving cref attributes.</param>
public DocumentationComment(string xml, ITypeResolveContext context)
{
if (xml == null)
throw new ArgumentNullException("xml");
if (context == null)
throw new ArgumentNullException("context");
this.xml = new StringTextSource(xml);
this.context = context;
}
/// <summary>
/// Resolves the given cref value to an entity.
/// Returns null if the entity is not found, or if the cref attribute is syntactically invalid.
/// </summary>
public virtual IEntity ResolveCref(string cref)
{
try {
return IdStringProvider.FindEntity(cref, context);
} catch (ReflectionNameParseException) {
return null;
}
}
public override string ToString ()
{
return Xml.Text;
}
public static implicit operator string (DocumentationComment documentationComment)
{
if (documentationComment != null)
return documentationComment.ToString ();
return null;
}
}
}

71
ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.Documentation
{
/// <summary>
/// A type reference of the form 'Some.Namespace.TopLevelType.NestedType`n'.
/// We do not know the boundary between namespace name and top level type, so we have to try
/// all possibilities.
/// The type parameter count only applies to the innermost type, all outer types must be non-generic.
/// </summary>
[Serializable]
class GetPotentiallyNestedClassTypeReference : ITypeReference
{
readonly string typeName;
readonly int typeParameterCount;
public GetPotentiallyNestedClassTypeReference(string typeName, int typeParameterCount)
{
this.typeName = typeName;
this.typeParameterCount = typeParameterCount;
}
public IType Resolve(ITypeResolveContext context)
{
string[] parts = typeName.Split('.');
var assemblies = new [] { context.CurrentAssembly }.Concat(context.Compilation.Assemblies);
for (int i = parts.Length - 1; i >= 0; i--) {
string ns = string.Join(".", parts, 0, i);
string name = parts[i];
int topLevelTPC = (i == parts.Length - 1 ? typeParameterCount : 0);
foreach (var asm in assemblies) {
if (asm == null)
continue;
ITypeDefinition typeDef = asm.GetTypeDefinition(new TopLevelTypeName(ns, name, topLevelTPC));
for (int j = i + 1; j < parts.Length && typeDef != null; j++) {
int tpc = (j == parts.Length - 1 ? typeParameterCount : 0);
typeDef = typeDef.NestedTypes.FirstOrDefault(n => n.Name == parts[j] && n.TypeParameterCount == tpc);
}
if (typeDef != null)
return typeDef;
}
}
int idx = typeName.LastIndexOf('.');
if (idx < 0)
return new UnknownType("", typeName, typeParameterCount);
// give back a guessed namespace/type name
return new UnknownType(typeName.Substring(0, idx), typeName.Substring(idx + 1), typeParameterCount);
}
}
}

51
ICSharpCode.Decompiler/Documentation/IDocumentationProvider.cs

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Documentation
{
/// <summary>
/// Provides XML documentation for entities.
/// </summary>
public interface IDocumentationProvider
{
/// <summary>
/// Gets the XML documentation for the specified entity.
/// </summary>
DocumentationComment GetDocumentation(IEntity entity);
}
/// <summary>
/// Provides XML documentation for entities.
/// </summary>
public interface IUnresolvedDocumentationProvider
{
/// <summary>
/// Gets the XML documentation for the specified entity.
/// </summary>
string GetDocumentation(IUnresolvedEntity entity);
/// <summary>
/// Gets the XML documentation for the specified entity.
/// </summary>
DocumentationComment GetDocumentation(IUnresolvedEntity entity, IEntity resolvedEntity);
}
}

77
ICSharpCode.Decompiler/Documentation/IdStringMemberReference.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Documentation
{
[Serializable]
class IdStringMemberReference : IMemberReference
{
readonly ITypeReference declaringTypeReference;
readonly char memberType;
readonly string memberIdString;
public IdStringMemberReference(ITypeReference declaringTypeReference, char memberType, string memberIdString)
{
this.declaringTypeReference = declaringTypeReference;
this.memberType = memberType;
this.memberIdString = memberIdString;
}
bool CanMatch(IUnresolvedMember member)
{
switch (member.SymbolKind) {
case SymbolKind.Field:
return memberType == 'F';
case SymbolKind.Property:
case SymbolKind.Indexer:
return memberType == 'P';
case SymbolKind.Event:
return memberType == 'E';
case SymbolKind.Method:
case SymbolKind.Operator:
case SymbolKind.Constructor:
case SymbolKind.Destructor:
return memberType == 'M';
default:
throw new NotSupportedException(member.SymbolKind.ToString());
}
}
public ITypeReference DeclaringTypeReference {
get { return declaringTypeReference; }
}
public IMember Resolve(ITypeResolveContext context)
{
IType declaringType = declaringTypeReference.Resolve(context);
foreach (var member in declaringType.GetMembers(CanMatch, GetMemberOptions.IgnoreInheritedMembers)) {
if (IdStringProvider.GetIdString(member) == memberIdString)
return member;
}
return null;
}
ISymbol ISymbolReference.Resolve(ITypeResolveContext context)
{
return Resolve(context);
}
}
}

393
ICSharpCode.Decompiler/Documentation/IdStringProvider.cs

@ -0,0 +1,393 @@ @@ -0,0 +1,393 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.Documentation
{
/// <summary>
/// Provides ID strings for entities. (C# 4.0 spec, §A.3.1)
/// ID strings are used to identify members in XML documentation files.
/// </summary>
public static class IdStringProvider
{
#region GetIdString
/// <summary>
/// Gets the ID string (C# 4.0 spec, §A.3.1) for the specified entity.
/// </summary>
public static string GetIdString(this IEntity entity)
{
StringBuilder b = new StringBuilder();
switch (entity.SymbolKind) {
case SymbolKind.TypeDefinition:
b.Append("T:");
AppendTypeName(b, (ITypeDefinition)entity, false);
return b.ToString();
case SymbolKind.Field:
b.Append("F:");
break;
case SymbolKind.Property:
case SymbolKind.Indexer:
b.Append("P:");
break;
case SymbolKind.Event:
b.Append("E:");
break;
default:
b.Append("M:");
break;
}
IMember member = (IMember)entity;
if (member.DeclaringType != null) {
AppendTypeName(b, member.DeclaringType, false);
b.Append('.');
}
if (member.IsExplicitInterfaceImplementation && member.Name.IndexOf('.') < 0 && member.ImplementedInterfaceMembers.Count == 1) {
AppendTypeName(b, member.ImplementedInterfaceMembers[0].DeclaringType, true);
b.Append('#');
}
b.Append(member.Name.Replace('.', '#'));
IMethod method = member as IMethod;
if (method != null && method.TypeParameters.Count > 0) {
b.Append("``");
b.Append(method.TypeParameters.Count);
}
IParameterizedMember parameterizedMember = member as IParameterizedMember;
if (parameterizedMember != null && parameterizedMember.Parameters.Count > 0) {
b.Append('(');
var parameters = parameterizedMember.Parameters;
for (int i = 0; i < parameters.Count; i++) {
if (i > 0) b.Append(',');
AppendTypeName(b, parameters[i].Type, false);
}
b.Append(')');
}
if (member.SymbolKind == SymbolKind.Operator && (member.Name == "op_Implicit" || member.Name == "op_Explicit")) {
b.Append('~');
AppendTypeName(b, member.ReturnType, false);
}
return b.ToString();
}
#endregion
#region GetTypeName
public static string GetTypeName(IType type)
{
if (type == null)
throw new ArgumentNullException("type");
StringBuilder b = new StringBuilder();
AppendTypeName(b, type, false);
return b.ToString();
}
static void AppendTypeName(StringBuilder b, IType type, bool explicitInterfaceImpl)
{
switch (type.Kind) {
case TypeKind.Dynamic:
b.Append(explicitInterfaceImpl ? "System#Object" : "System.Object");
break;
case TypeKind.TypeParameter:
ITypeParameter tp = (ITypeParameter)type;
if (explicitInterfaceImpl) {
b.Append(tp.Name);
} else {
b.Append('`');
if (tp.OwnerType == SymbolKind.Method)
b.Append('`');
b.Append(tp.Index);
}
break;
case TypeKind.Array:
ArrayType array = (ArrayType)type;
AppendTypeName(b, array.ElementType, explicitInterfaceImpl);
b.Append('[');
if (array.Dimensions > 1) {
for (int i = 0; i < array.Dimensions; i++) {
if (i > 0)
b.Append(explicitInterfaceImpl ? '@' : ',');
if (!explicitInterfaceImpl)
b.Append("0:");
}
}
b.Append(']');
break;
case TypeKind.Pointer:
AppendTypeName(b, ((PointerType)type).ElementType, explicitInterfaceImpl);
b.Append('*');
break;
case TypeKind.ByReference:
AppendTypeName(b, ((ByReferenceType)type).ElementType, explicitInterfaceImpl);
b.Append('@');
break;
default:
IType declType = type.DeclaringType;
if (declType != null) {
AppendTypeName(b, declType, explicitInterfaceImpl);
b.Append(explicitInterfaceImpl ? '#' : '.');
b.Append(type.Name);
AppendTypeParameters(b, type, declType.TypeParameterCount, explicitInterfaceImpl);
} else {
if (explicitInterfaceImpl)
b.Append(type.FullName.Replace('.', '#'));
else
b.Append(type.FullName);
AppendTypeParameters(b, type, 0, explicitInterfaceImpl);
}
break;
}
}
static void AppendTypeParameters(StringBuilder b, IType type, int outerTypeParameterCount, bool explicitInterfaceImpl)
{
int tpc = type.TypeParameterCount - outerTypeParameterCount;
if (tpc > 0) {
ParameterizedType pt = type as ParameterizedType;
if (pt != null) {
b.Append('{');
var ta = pt.TypeArguments;
for (int i = outerTypeParameterCount; i < ta.Count; i++) {
if (i > outerTypeParameterCount)
b.Append(explicitInterfaceImpl ? '@' : ',');
AppendTypeName(b, ta[i], explicitInterfaceImpl);
}
b.Append('}');
} else {
b.Append('`');
b.Append(tpc);
}
}
}
#endregion
#region ParseMemberName
/// <summary>
/// Parse the ID string into a member reference.
/// </summary>
/// <param name="memberIdString">The ID string representing the member (with "M:", "F:", "P:" or "E:" prefix).</param>
/// <returns>A member reference that represents the ID string.</returns>
/// <exception cref="ReflectionNameParseException">The syntax of the ID string is invalid</exception>
/// <remarks>
/// The member reference will look in <see cref="ITypeResolveContext.CurrentAssembly"/> first,
/// and if the member is not found there,
/// it will look in all other assemblies of the compilation.
/// </remarks>
public static IMemberReference ParseMemberIdString(string memberIdString)
{
if (memberIdString == null)
throw new ArgumentNullException("memberIdString");
if (memberIdString.Length < 2 || memberIdString[1] != ':')
throw new ReflectionNameParseException(0, "Missing type tag");
char typeChar = memberIdString[0];
int parenPos = memberIdString.IndexOf('(');
if (parenPos < 0)
parenPos = memberIdString.LastIndexOf('~');
if (parenPos < 0)
parenPos = memberIdString.Length;
int dotPos = memberIdString.LastIndexOf('.', parenPos - 1);
if (dotPos < 0)
throw new ReflectionNameParseException(0, "Could not find '.' separating type name from member name");
string typeName = memberIdString.Substring(0, dotPos);
int pos = 2;
ITypeReference typeReference = ParseTypeName(typeName, ref pos);
if (pos != typeName.Length)
throw new ReflectionNameParseException(pos, "Expected end of type name");
// string memberName = memberIDString.Substring(dotPos + 1, parenPos - (dotPos + 1));
// pos = memberName.LastIndexOf("``");
// if (pos > 0)
// memberName = memberName.Substring(0, pos);
// memberName = memberName.Replace('#', '.');
return new IdStringMemberReference(typeReference, typeChar, memberIdString);
}
#endregion
#region ParseTypeName
/// <summary>
/// Parse the ID string type name into a type reference.
/// </summary>
/// <param name="typeName">The ID string representing the type (the "T:" prefix is optional).</param>
/// <returns>A type reference that represents the ID string.</returns>
/// <exception cref="ReflectionNameParseException">The syntax of the ID string is invalid</exception>
/// <remarks>
/// <para>
/// The type reference will look in <see cref="ITypeResolveContext.CurrentAssembly"/> first,
/// and if the type is not found there,
/// it will look in all other assemblies of the compilation.
/// </para>
/// <para>
/// If the type is open (contains type parameters '`0' or '``0'),
/// an <see cref="ITypeResolveContext"/> with the appropriate CurrentTypeDefinition/CurrentMember is required
/// to resolve the reference to the ITypeParameter.
/// </para>
/// </remarks>
public static ITypeReference ParseTypeName(string typeName)
{
if (typeName == null)
throw new ArgumentNullException("typeName");
int pos = 0;
if (typeName.StartsWith("T:", StringComparison.Ordinal))
pos = 2;
ITypeReference r = ParseTypeName(typeName, ref pos);
if (pos < typeName.Length)
throw new ReflectionNameParseException(pos, "Expected end of type name");
return r;
}
static bool IsIDStringSpecialCharacter(char c)
{
switch (c) {
case ':':
case '{':
case '}':
case '[':
case ']':
case '(':
case ')':
case '`':
case '*':
case '@':
case ',':
return true;
default:
return false;
}
}
static ITypeReference ParseTypeName(string typeName, ref int pos)
{
string reflectionTypeName = typeName;
if (pos == typeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
ITypeReference result;
if (reflectionTypeName[pos] == '`') {
// type parameter reference
pos++;
if (pos == reflectionTypeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
if (reflectionTypeName[pos] == '`') {
// method type parameter reference
pos++;
int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos);
result = TypeParameterReference.Create(SymbolKind.Method, index);
} else {
// class type parameter reference
int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos);
result = TypeParameterReference.Create(SymbolKind.TypeDefinition, index);
}
} else {
// not a type parameter reference: read the actual type name
List<ITypeReference> typeArguments = new List<ITypeReference>();
int typeParameterCount;
string typeNameWithoutSuffix = ReadTypeName(typeName, ref pos, true, out typeParameterCount, typeArguments);
result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount);
while (pos < typeName.Length && typeName[pos] == '.') {
pos++;
string nestedTypeName = ReadTypeName(typeName, ref pos, false, out typeParameterCount, typeArguments);
result = new NestedTypeReference(result, nestedTypeName, typeParameterCount);
}
if (typeArguments.Count > 0) {
result = new ParameterizedTypeReference(result, typeArguments);
}
}
while (pos < typeName.Length) {
switch (typeName[pos]) {
case '[':
int dimensions = 1;
do {
pos++;
if (pos == typeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
if (typeName[pos] == ',')
dimensions++;
} while (typeName[pos] != ']');
result = new ArrayTypeReference(result, dimensions);
break;
case '*':
result = new PointerTypeReference(result);
break;
case '@':
result = new ByReferenceTypeReference(result);
break;
default:
return result;
}
pos++;
}
return result;
}
static string ReadTypeName(string typeName, ref int pos, bool allowDottedName, out int typeParameterCount, List<ITypeReference> typeArguments)
{
int startPos = pos;
// skip the simple name portion:
while (pos < typeName.Length && !IsIDStringSpecialCharacter(typeName[pos]) && (allowDottedName || typeName[pos] != '.'))
pos++;
if (pos == startPos)
throw new ReflectionNameParseException(pos, "Expected type name");
string shortTypeName = typeName.Substring(startPos, pos - startPos);
// read type arguments:
typeParameterCount = 0;
if (pos < typeName.Length && typeName[pos] == '`') {
// unbound generic type
pos++;
typeParameterCount = ReflectionHelper.ReadTypeParameterCount(typeName, ref pos);
} else if (pos < typeName.Length && typeName[pos] == '{') {
// bound generic type
typeArguments = new List<ITypeReference>();
do {
pos++;
typeArguments.Add(ParseTypeName(typeName, ref pos));
typeParameterCount++;
if (pos == typeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
} while (typeName[pos] == ',');
if (typeName[pos] != '}')
throw new ReflectionNameParseException(pos, "Expected '}'");
pos++;
}
return shortTypeName;
}
#endregion
#region FindEntity
/// <summary>
/// Finds the entity in the given type resolve context.
/// </summary>
/// <param name="idString">ID string of the entity.</param>
/// <param name="context">Type resolve context</param>
/// <returns>Returns the entity, or null if it is not found.</returns>
/// <exception cref="ReflectionNameParseException">The syntax of the ID string is invalid</exception>
public static IEntity FindEntity(string idString, ITypeResolveContext context)
{
if (idString == null)
throw new ArgumentNullException("idString");
if (context == null)
throw new ArgumentNullException("context");
if (idString.StartsWith("T:", StringComparison.Ordinal)) {
return ParseTypeName(idString.Substring(2)).Resolve(context).GetDefinition();
} else {
return ParseMemberIdString(idString).Resolve(context);
}
}
#endregion
}
}

422
ICSharpCode.Decompiler/Documentation/XmlDocumentationProvider.cs

@ -0,0 +1,422 @@ @@ -0,0 +1,422 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Documentation
{
/// <summary>
/// Provides documentation from an .xml file (as generated by the Microsoft C# compiler).
/// </summary>
/// <remarks>
/// This class first creates an in-memory index of the .xml file, and then uses that to read only the requested members.
/// This way, we avoid keeping all the documentation in memory.
/// The .xml file is only opened when necessary, the file handle is not kept open all the time.
/// If the .xml file is changed, the index will automatically be recreated.
/// </remarks>
[Serializable]
public class XmlDocumentationProvider : IDocumentationProvider, IDeserializationCallback
{
#region Cache
sealed class XmlDocumentationCache
{
readonly KeyValuePair<string, string>[] entries;
int pos;
public XmlDocumentationCache(int size = 50)
{
if (size <= 0)
throw new ArgumentOutOfRangeException("size", size, "Value must be positive");
this.entries = new KeyValuePair<string, string>[size];
}
internal bool TryGet(string key, out string value)
{
foreach (var pair in entries) {
if (pair.Key == key) {
value = pair.Value;
return true;
}
}
value = null;
return false;
}
internal void Add(string key, string value)
{
entries[pos++] = new KeyValuePair<string, string>(key, value);
if (pos == entries.Length)
pos = 0;
}
}
#endregion
[Serializable]
struct IndexEntry : IComparable<IndexEntry>
{
/// <summary>
/// Hash code of the documentation tag
/// </summary>
internal readonly int HashCode;
/// <summary>
/// Position in the .xml file where the documentation starts
/// </summary>
internal readonly int PositionInFile;
internal IndexEntry(int hashCode, int positionInFile)
{
this.HashCode = hashCode;
this.PositionInFile = positionInFile;
}
public int CompareTo(IndexEntry other)
{
return this.HashCode.CompareTo(other.HashCode);
}
}
[NonSerialized]
XmlDocumentationCache cache = new XmlDocumentationCache();
readonly string fileName;
readonly Encoding encoding;
volatile IndexEntry[] index; // SORTED array of index entries
#region Constructor / Redirection support
/// <summary>
/// Creates a new XmlDocumentationProvider.
/// </summary>
/// <param name="fileName">Name of the .xml file.</param>
/// <exception cref="IOException">Error reading from XML file (or from redirected file)</exception>
/// <exception cref="XmlException">Invalid XML file</exception>
public XmlDocumentationProvider(string fileName)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) {
using (XmlTextReader xmlReader = new XmlTextReader(fs)) {
xmlReader.XmlResolver = null; // no DTD resolving
xmlReader.MoveToContent();
if (string.IsNullOrEmpty(xmlReader.GetAttribute("redirect"))) {
this.fileName = fileName;
this.encoding = xmlReader.Encoding;
ReadXmlDoc(xmlReader);
} else {
string redirectionTarget = GetRedirectionTarget(fileName, xmlReader.GetAttribute("redirect"));
if (redirectionTarget != null) {
Debug.WriteLine("XmlDoc " + fileName + " is redirecting to " + redirectionTarget);
using (FileStream redirectedFs = new FileStream(redirectionTarget, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) {
using (XmlTextReader redirectedXmlReader = new XmlTextReader(redirectedFs)) {
redirectedXmlReader.XmlResolver = null; // no DTD resolving
redirectedXmlReader.MoveToContent();
this.fileName = redirectionTarget;
this.encoding = redirectedXmlReader.Encoding;
ReadXmlDoc(redirectedXmlReader);
}
}
} else {
throw new XmlException("XmlDoc " + fileName + " is redirecting to " + xmlReader.GetAttribute("redirect") + ", but that file was not found.");
}
}
}
}
}
static string GetRedirectionTarget(string xmlFileName, string target)
{
string programFilesDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
programFilesDir = AppendDirectorySeparator(programFilesDir);
string corSysDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
corSysDir = AppendDirectorySeparator(corSysDir);
var fileName = target.Replace ("%PROGRAMFILESDIR%", programFilesDir)
.Replace ("%CORSYSDIR%", corSysDir);
if (!Path.IsPathRooted (fileName))
fileName = Path.Combine (Path.GetDirectoryName (xmlFileName), fileName);
return LookupLocalizedXmlDoc(fileName);
}
static string AppendDirectorySeparator(string dir)
{
if (dir.EndsWith("\\", StringComparison.Ordinal) || dir.EndsWith("/", StringComparison.Ordinal))
return dir;
else
return dir + Path.DirectorySeparatorChar;
}
/// <summary>
/// Given the assembly file name, looks up the XML documentation file name.
/// Returns null if no XML documentation file is found.
/// </summary>
public static string LookupLocalizedXmlDoc(string fileName)
{
string xmlFileName = Path.ChangeExtension(fileName, ".xml");
string currentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName;
string localizedXmlDocFile = GetLocalizedName(xmlFileName, currentCulture);
Debug.WriteLine("Try find XMLDoc @" + localizedXmlDocFile);
if (File.Exists(localizedXmlDocFile)) {
return localizedXmlDocFile;
}
Debug.WriteLine("Try find XMLDoc @" + xmlFileName);
if (File.Exists(xmlFileName)) {
return xmlFileName;
}
if (currentCulture != "en") {
string englishXmlDocFile = GetLocalizedName(xmlFileName, "en");
Debug.WriteLine("Try find XMLDoc @" + englishXmlDocFile);
if (File.Exists(englishXmlDocFile)) {
return englishXmlDocFile;
}
}
return null;
}
static string GetLocalizedName(string fileName, string language)
{
string localizedXmlDocFile = Path.GetDirectoryName(fileName);
localizedXmlDocFile = Path.Combine(localizedXmlDocFile, language);
localizedXmlDocFile = Path.Combine(localizedXmlDocFile, Path.GetFileName(fileName));
return localizedXmlDocFile;
}
#endregion
#region Load / Create Index
void ReadXmlDoc(XmlTextReader reader)
{
//lastWriteDate = File.GetLastWriteTimeUtc(fileName);
// Open up a second file stream for the line<->position mapping
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) {
LinePositionMapper linePosMapper = new LinePositionMapper(fs, encoding);
List<IndexEntry> indexList = new List<IndexEntry>();
while (reader.Read()) {
if (reader.IsStartElement()) {
switch (reader.LocalName) {
case "members":
ReadMembersSection(reader, linePosMapper, indexList);
break;
}
}
}
indexList.Sort();
this.index = indexList.ToArray(); // volatile write
}
}
sealed class LinePositionMapper
{
readonly FileStream fs;
readonly Decoder decoder;
int currentLine = 1;
// buffers for use with Decoder:
byte[] input = new byte[1];
char[] output = new char[1];
public LinePositionMapper(FileStream fs, Encoding encoding)
{
this.decoder = encoding.GetDecoder();
this.fs = fs;
}
public int GetPositionForLine(int line)
{
Debug.Assert(line >= currentLine);
while (line > currentLine) {
int b = fs.ReadByte();
if (b < 0)
throw new EndOfStreamException();
int bytesUsed, charsUsed;
bool completed;
input[0] = (byte)b;
decoder.Convert(input, 0, 1, output, 0, 1, false, out bytesUsed, out charsUsed, out completed);
Debug.Assert(bytesUsed == 1);
if (charsUsed == 1 && output[0] == '\n') {
currentLine++;
}
}
return checked((int)fs.Position);
}
}
static void ReadMembersSection(XmlTextReader reader, LinePositionMapper linePosMapper, List<IndexEntry> indexList)
{
while (reader.Read()) {
switch (reader.NodeType) {
case XmlNodeType.EndElement:
if (reader.LocalName == "members") {
return;
}
break;
case XmlNodeType.Element:
if (reader.LocalName == "member") {
int pos = linePosMapper.GetPositionForLine(reader.LineNumber) + Math.Max(reader.LinePosition - 2, 0);
string memberAttr = reader.GetAttribute("name");
if (memberAttr != null)
indexList.Add(new IndexEntry(GetHashCode(memberAttr), pos));
reader.Skip();
}
break;
}
}
}
/// <summary>
/// Hash algorithm used for the index.
/// This is a custom implementation so that old index files work correctly
/// even when the .NET string.GetHashCode implementation changes
/// (e.g. due to .NET 4.5 hash randomization)
/// </summary>
static int GetHashCode(string key)
{
unchecked {
int h = 0;
foreach (char c in key) {
h = (h << 5) - h + c;
}
return h;
}
}
#endregion
#region GetDocumentation
/// <summary>
/// Get the documentation for the member with the specified documentation key.
/// </summary>
public string GetDocumentation(string key)
{
if (key == null)
throw new ArgumentNullException("key");
return GetDocumentation(key, true);
}
string GetDocumentation(string key, bool allowReload)
{
int hashcode = GetHashCode(key);
var index = this.index; // read volatile field
// index is sorted, so we can use binary search
int m = Array.BinarySearch(index, new IndexEntry(hashcode, 0));
if (m < 0)
return null;
// correct hash code found.
// possibly there are multiple items with the same hash, so go to the first.
while (--m >= 0 && index[m].HashCode == hashcode);
// m is now 1 before the first item with the correct hash
XmlDocumentationCache cache = this.cache;
lock (cache) {
string val;
if (!cache.TryGet(key, out val)) {
try {
// go through all items that have the correct hash
while (++m < index.Length && index[m].HashCode == hashcode) {
val = LoadDocumentation(key, index[m].PositionInFile);
if (val != null)
break;
}
// cache the result (even if it is null)
cache.Add(key, val);
} catch (IOException) {
// may happen if the documentation file was deleted/is inaccessible/changed (EndOfStreamException)
return allowReload ? ReloadAndGetDocumentation(key) : null;
} catch (XmlException) {
// may happen if the documentation file was changed so that the file position no longer starts on a valid XML element
return allowReload ? ReloadAndGetDocumentation(key) : null;
}
}
return val;
}
}
string ReloadAndGetDocumentation(string key)
{
try {
// Reload the index
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) {
using (XmlTextReader xmlReader = new XmlTextReader(fs)) {
xmlReader.XmlResolver = null; // no DTD resolving
xmlReader.MoveToContent();
ReadXmlDoc(xmlReader);
}
}
} catch (IOException) {
// Ignore errors on reload; IEntity.Documentation callers aren't prepared to handle exceptions
this.index = new IndexEntry[0]; // clear index to avoid future load attempts
return null;
} catch (XmlException) {
this.index = new IndexEntry[0]; // clear index to avoid future load attempts
return null;
}
return GetDocumentation(key, allowReload: false); // prevent infinite reload loops
}
#endregion
#region GetDocumentation for entity
/// <inheritdoc/>
public DocumentationComment GetDocumentation(IEntity entity)
{
string xmlDoc = GetDocumentation(IdStringProvider.GetIdString(entity));
if (xmlDoc != null) {
return new DocumentationComment(new StringTextSource(xmlDoc), new SimpleTypeResolveContext(entity));
} else {
return null;
}
}
#endregion
#region Load / Read XML
string LoadDocumentation(string key, int positionInFile)
{
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) {
fs.Position = positionInFile;
var context = new XmlParserContext(null, null, null, XmlSpace.None) { Encoding = encoding };
using (XmlTextReader r = new XmlTextReader(fs, XmlNodeType.Element, context)) {
r.XmlResolver = null; // no DTD resolving
while (r.Read()) {
if (r.NodeType == XmlNodeType.Element) {
string memberAttr = r.GetAttribute("name");
if (memberAttr == key) {
return r.ReadInnerXml();
} else {
return null;
}
}
}
return null;
}
}
}
#endregion
public virtual void OnDeserialization(object sender)
{
cache = new XmlDocumentationCache();
}
}
}

205
ICSharpCode.Decompiler/Editor/IDocument.cs

@ -0,0 +1,205 @@ @@ -0,0 +1,205 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// A document representing a source code file for refactoring.
/// Line and column counting starts at 1.
/// Offset counting starts at 0.
/// </summary>
public interface IDocument : ITextSource, IServiceProvider
{
/// <summary>
/// Creates an immutable snapshot of this document.
/// </summary>
IDocument CreateDocumentSnapshot();
/// <summary>
/// Gets/Sets the text of the whole document..
/// </summary>
new string Text { get; set; } // hides ITextSource.Text to add the setter
/// <summary>
/// This event is called directly before a change is applied to the document.
/// </summary>
/// <remarks>
/// It is invalid to modify the document within this event handler.
/// Aborting the change (by throwing an exception) is likely to cause corruption of data structures
/// that listen to the Changing and Changed events.
/// </remarks>
event EventHandler<TextChangeEventArgs> TextChanging;
/// <summary>
/// This event is called directly after a change is applied to the document.
/// </summary>
/// <remarks>
/// It is invalid to modify the document within this event handler.
/// Aborting the event handler (by throwing an exception) is likely to cause corruption of data structures
/// that listen to the Changing and Changed events.
/// </remarks>
event EventHandler<TextChangeEventArgs> TextChanged;
/// <summary>
/// This event is called after a group of changes is completed.
/// </summary>
/// <seealso cref="EndUndoableAction"/>
event EventHandler ChangeCompleted;
/// <summary>
/// Gets the number of lines in the document.
/// </summary>
int LineCount { get; }
/// <summary>
/// Gets the document line with the specified number.
/// </summary>
/// <param name="lineNumber">The number of the line to retrieve. The first line has number 1.</param>
IDocumentLine GetLineByNumber(int lineNumber);
/// <summary>
/// Gets the document line that contains the specified offset.
/// </summary>
IDocumentLine GetLineByOffset(int offset);
/// <summary>
/// Gets the offset from a text location.
/// </summary>
/// <seealso cref="GetLocation"/>
int GetOffset(int line, int column);
/// <summary>
/// Gets the offset from a text location.
/// </summary>
/// <seealso cref="GetLocation"/>
int GetOffset(TextLocation location);
/// <summary>
/// Gets the location from an offset.
/// </summary>
/// <seealso cref="GetOffset(TextLocation)"/>
TextLocation GetLocation(int offset);
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <remarks>
/// Anchors positioned exactly at the insertion offset will move according to their movement type.
/// For AnchorMovementType.Default, they will move behind the inserted text.
/// The caret will also move behind the inserted text.
/// </remarks>
void Insert(int offset, string text);
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <remarks>
/// Anchors positioned exactly at the insertion offset will move according to their movement type.
/// For AnchorMovementType.Default, they will move behind the inserted text.
/// The caret will also move behind the inserted text.
/// </remarks>
void Insert(int offset, ITextSource text);
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <param name="defaultAnchorMovementType">
/// Anchors positioned exactly at the insertion offset will move according to the anchor's movement type.
/// For AnchorMovementType.Default, they will move according to the movement type specified by this parameter.
/// The caret will also move according to the <paramref name="defaultAnchorMovementType"/> parameter.
/// </param>
void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType);
/// <summary>
/// Inserts text.
/// </summary>
/// <param name="offset">The offset at which the text is inserted.</param>
/// <param name="text">The new text.</param>
/// <param name="defaultAnchorMovementType">
/// Anchors positioned exactly at the insertion offset will move according to the anchor's movement type.
/// For AnchorMovementType.Default, they will move according to the movement type specified by this parameter.
/// The caret will also move according to the <paramref name="defaultAnchorMovementType"/> parameter.
/// </param>
void Insert(int offset, ITextSource text, AnchorMovementType defaultAnchorMovementType);
/// <summary>
/// Removes text.
/// </summary>
/// <param name="offset">Starting offset of the text to be removed.</param>
/// <param name="length">Length of the text to be removed.</param>
void Remove(int offset, int length);
/// <summary>
/// Replaces text.
/// </summary>
/// <param name="offset">The starting offset of the text to be replaced.</param>
/// <param name="length">The length of the text to be replaced.</param>
/// <param name="newText">The new text.</param>
void Replace(int offset, int length, string newText);
/// <summary>
/// Replaces text.
/// </summary>
/// <param name="offset">The starting offset of the text to be replaced.</param>
/// <param name="length">The length of the text to be replaced.</param>
/// <param name="newText">The new text.</param>
void Replace(int offset, int length, ITextSource newText);
/// <summary>
/// Make the document combine the following actions into a single
/// action for undo purposes.
/// </summary>
void StartUndoableAction();
/// <summary>
/// Ends the undoable action started with <see cref="StartUndoableAction"/>.
/// </summary>
void EndUndoableAction();
/// <summary>
/// Creates an undo group. Dispose the returned value to close the undo group.
/// </summary>
/// <returns>An object that closes the undo group when Dispose() is called.</returns>
IDisposable OpenUndoGroup();
/// <summary>
/// Creates a new <see cref="ITextAnchor"/> at the specified offset.
/// </summary>
/// <inheritdoc cref="ITextAnchor" select="remarks|example"/>
ITextAnchor CreateAnchor(int offset);
/// <summary>
/// Gets the name of the file the document is stored in.
/// Could also be a non-existent dummy file name or null if no name has been set.
/// </summary>
string FileName { get; }
/// <summary>
/// Fired when the file name of the document changes.
/// </summary>
event EventHandler FileNameChanged;
}
}

60
ICSharpCode.Decompiler/Editor/IDocumentLine.cs

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// A line inside a <see cref="IDocument"/>.
/// </summary>
public interface IDocumentLine : ISegment
{
/// <summary>
/// Gets the length of this line, including the line delimiter.
/// </summary>
int TotalLength { get; }
/// <summary>
/// Gets the length of the line terminator.
/// Returns 1 or 2; or 0 at the end of the document.
/// </summary>
int DelimiterLength { get; }
/// <summary>
/// Gets the number of this line.
/// The first line has the number 1.
/// </summary>
int LineNumber { get; }
/// <summary>
/// Gets the previous line. Returns null if this is the first line in the document.
/// </summary>
IDocumentLine PreviousLine { get; }
/// <summary>
/// Gets the next line. Returns null if this is the last line in the document.
/// </summary>
IDocumentLine NextLine { get; }
/// <summary>
/// Gets whether the line was deleted.
/// </summary>
bool IsDeleted { get; }
}
}

71
ICSharpCode.Decompiler/Editor/ISegment.cs

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// An (Offset,Length)-pair.
/// </summary>
public interface ISegment
{
/// <summary>
/// Gets the start offset of the segment.
/// </summary>
int Offset { get; }
/// <summary>
/// Gets the length of the segment.
/// </summary>
/// <remarks>For line segments (IDocumentLine), the length does not include the line delimeter.</remarks>
int Length { get; }
/// <summary>
/// Gets the end offset of the segment.
/// </summary>
/// <remarks>EndOffset = Offset + Length;</remarks>
int EndOffset { get; }
}
/// <summary>
/// Extension methods for <see cref="ISegment"/>.
/// </summary>
public static class ISegmentExtensions
{
/// <summary>
/// Gets whether <paramref name="segment"/> fully contains the specified segment.
/// </summary>
/// <remarks>
/// Use <c>segment.Contains(offset, 0)</c> to detect whether a segment (end inclusive) contains offset;
/// use <c>segment.Contains(offset, 1)</c> to detect whether a segment (end exclusive) contains offset.
/// </remarks>
public static bool Contains (this ISegment segment, int offset, int length)
{
return segment.Offset <= offset && offset + length <= segment.EndOffset;
}
/// <summary>
/// Gets whether <paramref name="thisSegment"/> fully contains the specified segment.
/// </summary>
public static bool Contains (this ISegment thisSegment, ISegment segment)
{
return segment != null && thisSegment.Offset <= segment.Offset && segment.EndOffset <= thisSegment.EndOffset;
}
}
}

139
ICSharpCode.Decompiler/Editor/ITextAnchor.cs

@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// The TextAnchor class references an offset (a position between two characters).
/// It automatically updates the offset when text is inserted/removed in front of the anchor.
/// </summary>
/// <remarks>
/// <para>Use the <see cref="ITextAnchor.Offset"/> property to get the offset from a text anchor.
/// Use the <see cref="IDocument.CreateAnchor"/> method to create an anchor from an offset.
/// </para>
/// <para>
/// The document will automatically update all text anchors; and because it uses weak references to do so,
/// the garbage collector can simply collect the anchor object when you don't need it anymore.
/// </para>
/// <para>Moreover, the document is able to efficiently update a large number of anchors without having to look
/// at each anchor object individually. Updating the offsets of all anchors usually only takes time logarithmic
/// to the number of anchors. Retrieving the <see cref="ITextAnchor.Offset"/> property also runs in O(lg N).</para>
/// </remarks>
/// <example>
/// Usage:
/// <code>TextAnchor anchor = document.CreateAnchor(offset);
/// ChangeMyDocument();
/// int newOffset = anchor.Offset;
/// </code>
/// </example>
public interface ITextAnchor
{
/// <summary>
/// Gets the text location of this anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
TextLocation Location { get; }
/// <summary>
/// Gets the offset of the text anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
int Offset { get; }
/// <summary>
/// Controls how the anchor moves.
/// </summary>
/// <remarks>Anchor movement is ambiguous if text is inserted exactly at the anchor's location.
/// Does the anchor stay before the inserted text, or does it move after it?
/// The property <see cref="MovementType"/> will be used to determine which of these two options the anchor will choose.
/// The default value is <see cref="AnchorMovementType.Default"/>.</remarks>
AnchorMovementType MovementType { get; set; }
/// <summary>
/// <para>
/// Specifies whether the anchor survives deletion of the text containing it.
/// </para><para>
/// <c>false</c>: The anchor is deleted when the a selection that includes the anchor is deleted.
/// <c>true</c>: The anchor is not deleted.
/// </para>
/// </summary>
/// <remarks><inheritdoc cref="IsDeleted" /></remarks>
bool SurviveDeletion { get; set; }
/// <summary>
/// Gets whether the anchor was deleted.
/// </summary>
/// <remarks>
/// <para>When a piece of text containing an anchor is removed, then that anchor will be deleted.
/// First, the <see cref="IsDeleted"/> property is set to true on all deleted anchors,
/// then the <see cref="Deleted"/> events are raised.
/// You cannot retrieve the offset from an anchor that has been deleted.</para>
/// <para>This deletion behavior might be useful when using anchors for building a bookmark feature,
/// but in other cases you want to still be able to use the anchor. For those cases, set <c><see cref="SurviveDeletion"/> = true</c>.</para>
/// </remarks>
bool IsDeleted { get; }
/// <summary>
/// Occurs after the anchor was deleted.
/// </summary>
/// <remarks>
/// <inheritdoc cref="IsDeleted" />
/// <para>Due to the 'weak reference' nature of text anchors, you will receive
/// the Deleted event only while your code holds a reference to the TextAnchor object.
/// </para>
/// </remarks>
event EventHandler Deleted;
/// <summary>
/// Gets the line number of the anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
int Line { get; }
/// <summary>
/// Gets the column number of this anchor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when trying to get the Offset from a deleted anchor.</exception>
int Column { get; }
}
/// <summary>
/// Defines how a text anchor moves.
/// </summary>
public enum AnchorMovementType
{
/// <summary>
/// When text is inserted at the anchor position, the type of the insertion
/// determines where the caret moves to. For normal insertions, the anchor will move
/// after the inserted text.
/// </summary>
Default,
/// <summary>
/// Behaves like a start marker - when text is inserted at the anchor position, the anchor will stay
/// before the inserted text.
/// </summary>
BeforeInsertion,
/// <summary>
/// Behave like an end marker - when text is insered at the anchor position, the anchor will move
/// after the inserted text.
/// </summary>
AfterInsertion
}
}

51
ICSharpCode.Decompiler/Editor/ITextPasteHandler.cs

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
// ITextPasteHandler.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2008 Novell, Inc (http://www.novell.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.
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// The text paste handler can do formattings to a text that is about to be pasted
/// into the text document.
/// </summary>
public interface ITextPasteHandler
{
/// <summary>
/// Formats plain text that is inserted at a specified offset.
/// </summary>
/// <returns>
/// The text that will get inserted at that position.
/// </returns>
/// <param name="offset">The offset where the text will be inserted.</param>
/// <param name="text">The text to be inserted.</param>
/// <param name="copyData">Additional data in case the text was copied from a Mono.TextEditor.</param>
string FormatPlainText(int offset, string text, byte[] copyData);
/// <summary>
/// Gets the copy data for a specific segment inside the document. This can contain additional information.
/// </summary>
/// <param name="segment">The text segment that is about to be copied.</param>
byte[] GetCopyData(ISegment segment);
}
}

218
ICSharpCode.Decompiler/Editor/ITextSource.cs

@ -0,0 +1,218 @@ @@ -0,0 +1,218 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// A read-only view on a (potentially mutable) text source.
/// The IDocument interface derives from this interface.
/// </summary>
public interface ITextSource
{
/// <summary>
/// Gets a version identifier for this text source.
/// Returns null for unversioned text sources.
/// </summary>
ITextSourceVersion Version { get; }
/// <summary>
/// Creates an immutable snapshot of this text source.
/// Unlike all other methods in this interface, this method is thread-safe.
/// </summary>
ITextSource CreateSnapshot();
/// <summary>
/// Creates an immutable snapshot of a part of this text source.
/// Unlike all other methods in this interface, this method is thread-safe.
/// </summary>
ITextSource CreateSnapshot(int offset, int length);
/// <summary>
/// Creates a new TextReader to read from this text source.
/// </summary>
TextReader CreateReader();
/// <summary>
/// Creates a new TextReader to read from this text source.
/// </summary>
TextReader CreateReader(int offset, int length);
/// <summary>
/// Gets the total text length.
/// </summary>
/// <returns>The length of the text, in characters.</returns>
/// <remarks>This is the same as Text.Length, but is more efficient because
/// it doesn't require creating a String object.</remarks>
int TextLength { get; }
/// <summary>
/// Gets the whole text as string.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
string Text { get; }
/// <summary>
/// Gets a character at the specified position in the document.
/// </summary>
/// <paramref name="offset">The index of the character to get.</paramref>
/// <exception cref="ArgumentOutOfRangeException">Offset is outside the valid range (0 to TextLength-1).</exception>
/// <returns>The character at the specified position.</returns>
/// <remarks>This is the same as Text[offset], but is more efficient because
/// it doesn't require creating a String object.</remarks>
char GetCharAt(int offset);
/// <summary>
/// Retrieves the text for a portion of the document.
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">offset or length is outside the valid range.</exception>
/// <remarks>This is the same as Text.Substring, but is more efficient because
/// it doesn't require creating a String object for the whole document.</remarks>
string GetText(int offset, int length);
/// <summary>
/// Retrieves the text for a portion of the document.
/// </summary>
/// <exception cref="ArgumentOutOfRangeException">offset or length is outside the valid range.</exception>
string GetText(ISegment segment);
/// <summary>
/// Writes the text from this document into the TextWriter.
/// </summary>
void WriteTextTo(TextWriter writer);
/// <summary>
/// Writes the text from this document into the TextWriter.
/// </summary>
void WriteTextTo(TextWriter writer, int offset, int length);
/// <summary>
/// Gets the index of the first occurrence of the character in the specified array.
/// </summary>
/// <param name="c">Character to search for</param>
/// <param name="startIndex">Start index of the area to search.</param>
/// <param name="count">Length of the area to search.</param>
/// <returns>The first index where the character was found; or -1 if no occurrence was found.</returns>
int IndexOf(char c, int startIndex, int count);
/// <summary>
/// Gets the index of the first occurrence of any character in the specified array.
/// </summary>
/// <param name="anyOf">Characters to search for</param>
/// <param name="startIndex">Start index of the area to search.</param>
/// <param name="count">Length of the area to search.</param>
/// <returns>The first index where any character was found; or -1 if no occurrence was found.</returns>
int IndexOfAny(char[] anyOf, int startIndex, int count);
/// <summary>
/// Gets the index of the first occurrence of the specified search text in this text source.
/// </summary>
/// <param name="searchText">The search text</param>
/// <param name="startIndex">Start index of the area to search.</param>
/// <param name="count">Length of the area to search.</param>
/// <param name="comparisonType">String comparison to use.</param>
/// <returns>The first index where the search term was found; or -1 if no occurrence was found.</returns>
int IndexOf(string searchText, int startIndex, int count, StringComparison comparisonType);
/// <summary>
/// Gets the index of the last occurrence of the specified character in this text source.
/// </summary>
/// <param name="c">The search character</param>
/// <param name="startIndex">Start index of the area to search.</param>
/// <param name="count">Length of the area to search.</param>
/// <returns>The last index where the search term was found; or -1 if no occurrence was found.</returns>
/// <remarks>The search proceeds backwards from (startIndex+count) to startIndex.
/// This is different than the meaning of the parameters on string.LastIndexOf!</remarks>
int LastIndexOf(char c, int startIndex, int count);
/// <summary>
/// Gets the index of the last occurrence of the specified search text in this text source.
/// </summary>
/// <param name="searchText">The search text</param>
/// <param name="startIndex">Start index of the area to search.</param>
/// <param name="count">Length of the area to search.</param>
/// <param name="comparisonType">String comparison to use.</param>
/// <returns>The last index where the search term was found; or -1 if no occurrence was found.</returns>
/// <remarks>The search proceeds backwards from (startIndex+count) to startIndex.
/// This is different than the meaning of the parameters on string.LastIndexOf!</remarks>
int LastIndexOf(string searchText, int startIndex, int count, StringComparison comparisonType);
/* What about:
void Insert (int offset, string value);
void Remove (int offset, int count);
void Remove (ISegment segment);
void Replace (int offset, int count, string value);
Or more search operations:
IEnumerable<int> SearchForward (string pattern, int startIndex);
IEnumerable<int> SearchForwardIgnoreCase (string pattern, int startIndex);
IEnumerable<int> SearchBackward (string pattern, int startIndex);
IEnumerable<int> SearchBackwardIgnoreCase (string pattern, int startIndex);
*/
}
/// <summary>
/// Represents a version identifier for a text source.
/// </summary>
/// <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 ITextSource to allow the GC to collect the text source while
/// the version checkpoint is still in use.
/// </remarks>
public interface ITextSourceVersion
{
/// <summary>
/// Gets whether this checkpoint belongs to the same document as the other checkpoint.
/// </summary>
/// <remarks>
/// Returns false when given <c>null</c>.
/// </remarks>
bool BelongsToSameDocumentAs(ITextSourceVersion other);
/// <summary>
/// Compares the age of this checkpoint to the other checkpoint.
/// </summary>
/// <remarks>This method is thread-safe.</remarks>
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this version.</exception>
/// <returns>-1 if this version is older than <paramref name="other"/>.
/// 0 if <c>this</c> version instance represents the same version as <paramref name="other"/>.
/// 1 if this version is newer than <paramref name="other"/>.</returns>
int CompareAge(ITextSourceVersion other);
/// <summary>
/// Gets the changes from this checkpoint to the other checkpoint.
/// If 'other' is older than this checkpoint, reverse changes are calculated.
/// </summary>
/// <remarks>This method is thread-safe.</remarks>
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint.</exception>
IEnumerable<TextChangeEventArgs> GetChangesTo(ITextSourceVersion other);
/// <summary>
/// Calculates where the offset has moved in the other buffer version.
/// </summary>
/// <exception cref="ArgumentException">Raised if 'other' belongs to a different document than this checkpoint.</exception>
int MoveOffsetTo(ITextSourceVersion other, int oldOffset, AnchorMovementType movement = AnchorMovementType.Default);
}
}

447
ICSharpCode.Decompiler/Editor/ReadOnlyDocument.cs

@ -0,0 +1,447 @@ @@ -0,0 +1,447 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// Read-only implementation of <see cref="IDocument"/>.
/// </summary>
[Serializable]
public sealed class ReadOnlyDocument : IDocument
{
readonly ITextSource textSource;
readonly string fileName;
int[] lines;
static readonly char[] newline = { '\r', '\n' };
/// <summary>
/// Creates a new ReadOnlyDocument from the given text source.
/// </summary>
public ReadOnlyDocument(ITextSource textSource)
{
if (textSource == null)
throw new ArgumentNullException("textSource");
// ensure that underlying buffer is immutable
this.textSource = textSource.CreateSnapshot();
List<int> lines = new List<int>();
lines.Add(0);
int offset = 0;
int textLength = textSource.TextLength;
while ((offset = textSource.IndexOfAny(newline, offset, textLength - offset)) >= 0) {
offset++;
if (textSource.GetCharAt(offset - 1) == '\r' && offset < textLength && textSource.GetCharAt(offset) == '\n') {
offset++;
}
lines.Add(offset);
}
this.lines = lines.ToArray();
}
/// <summary>
/// Creates a new ReadOnlyDocument from the given string.
/// </summary>
public ReadOnlyDocument(string text)
: this(new StringTextSource(text))
{
}
/// <summary>
/// Creates a new ReadOnlyDocument from the given text source;
/// and sets IDocument.FileName to the specified file name.
/// </summary>
public ReadOnlyDocument(ITextSource textSource, string fileName)
: this(textSource)
{
this.fileName = fileName;
}
/// <inheritdoc/>
public IDocumentLine GetLineByNumber(int lineNumber)
{
if (lineNumber < 1 || lineNumber > lines.Length)
throw new ArgumentOutOfRangeException("lineNumber", lineNumber, "Value must be between 1 and " + lines.Length);
return new ReadOnlyDocumentLine(this, lineNumber);
}
sealed class ReadOnlyDocumentLine : IDocumentLine
{
readonly ReadOnlyDocument doc;
readonly int lineNumber;
readonly int offset, endOffset;
public ReadOnlyDocumentLine(ReadOnlyDocument doc, int lineNumber)
{
this.doc = doc;
this.lineNumber = lineNumber;
this.offset = doc.GetStartOffset(lineNumber);
this.endOffset = doc.GetEndOffset(lineNumber);
}
public override int GetHashCode()
{
return doc.GetHashCode() ^ lineNumber;
}
public override bool Equals(object obj)
{
ReadOnlyDocumentLine other = obj as ReadOnlyDocumentLine;
return other != null && doc == other.doc && lineNumber == other.lineNumber;
}
public int Offset {
get { return offset; }
}
public int Length {
get { return endOffset - offset; }
}
public int EndOffset {
get { return endOffset; }
}
public int TotalLength {
get {
return doc.GetTotalEndOffset(lineNumber) - offset;
}
}
public int DelimiterLength {
get {
return doc.GetTotalEndOffset(lineNumber) - endOffset;
}
}
public int LineNumber {
get { return lineNumber; }
}
public IDocumentLine PreviousLine {
get {
if (lineNumber == 1)
return null;
else
return new ReadOnlyDocumentLine(doc, lineNumber - 1);
}
}
public IDocumentLine NextLine {
get {
if (lineNumber == doc.LineCount)
return null;
else
return new ReadOnlyDocumentLine(doc, lineNumber + 1);
}
}
public bool IsDeleted {
get { return false; }
}
}
int GetStartOffset(int lineNumber)
{
return lines[lineNumber-1];
}
int GetTotalEndOffset(int lineNumber)
{
return lineNumber < lines.Length ? lines[lineNumber] : textSource.TextLength;
}
int GetEndOffset(int lineNumber)
{
if (lineNumber == lines.Length)
return textSource.TextLength;
int off = lines[lineNumber] - 1;
if (off > 0 && textSource.GetCharAt(off - 1) == '\r' && textSource.GetCharAt(off) == '\n')
off--;
return off;
}
/// <inheritdoc/>
public IDocumentLine GetLineByOffset(int offset)
{
return GetLineByNumber(GetLineNumberForOffset(offset));
}
int GetLineNumberForOffset(int offset)
{
int r = Array.BinarySearch(lines, offset);
return r < 0 ? ~r : r + 1;
}
/// <inheritdoc/>
public int GetOffset(int line, int column)
{
if (line < 1 || line > lines.Length)
throw new ArgumentOutOfRangeException("line", line, "Value must be between 1 and " + lines.Length);
int lineStart = GetStartOffset(line);
if (column <= 1)
return lineStart;
int lineEnd = GetEndOffset(line);
if (column - 1 >= lineEnd - lineStart)
return lineEnd;
return lineStart + column - 1;
}
/// <inheritdoc/>
public int GetOffset(TextLocation location)
{
return GetOffset(location.Line, location.Column);
}
/// <inheritdoc/>
public TextLocation GetLocation(int offset)
{
if (offset < 0 || offset > textSource.TextLength)
throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + textSource.TextLength);
int line = GetLineNumberForOffset(offset);
return new TextLocation(line, offset-GetStartOffset(line)+1);
}
/// <inheritdoc/>
public string Text {
get { return textSource.Text; }
set {
throw new NotSupportedException();
}
}
/// <inheritdoc/>
public int LineCount {
get { return lines.Length; }
}
/// <inheritdoc/>
public ITextSourceVersion Version {
get { return textSource.Version; }
}
/// <inheritdoc/>
public int TextLength {
get { return textSource.TextLength; }
}
event EventHandler<TextChangeEventArgs> IDocument.TextChanging { add {} remove {} }
event EventHandler<TextChangeEventArgs> IDocument.TextChanged { add {} remove {} }
event EventHandler IDocument.ChangeCompleted { add {} remove {} }
void IDocument.Insert(int offset, string text)
{
throw new NotSupportedException();
}
void IDocument.Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType)
{
throw new NotSupportedException();
}
void IDocument.Remove(int offset, int length)
{
throw new NotSupportedException();
}
void IDocument.Replace(int offset, int length, string newText)
{
throw new NotSupportedException();
}
void IDocument.Insert(int offset, ITextSource text)
{
throw new NotSupportedException();
}
void IDocument.Insert(int offset, ITextSource text, AnchorMovementType defaultAnchorMovementType)
{
throw new NotSupportedException();
}
void IDocument.Replace(int offset, int length, ITextSource newText)
{
throw new NotSupportedException();
}
void IDocument.StartUndoableAction()
{
}
void IDocument.EndUndoableAction()
{
}
IDisposable IDocument.OpenUndoGroup()
{
return null;
}
/// <inheritdoc/>
public ITextAnchor CreateAnchor(int offset)
{
return new ReadOnlyDocumentTextAnchor(GetLocation(offset), offset);
}
sealed class ReadOnlyDocumentTextAnchor : ITextAnchor
{
readonly TextLocation location;
readonly int offset;
public ReadOnlyDocumentTextAnchor(TextLocation location, int offset)
{
this.location = location;
this.offset = offset;
}
public event EventHandler Deleted { add {} remove {} }
public TextLocation Location {
get { return location; }
}
public int Offset {
get { return offset; }
}
public AnchorMovementType MovementType { get; set; }
public bool SurviveDeletion { get; set; }
public bool IsDeleted {
get { return false; }
}
public int Line {
get { return location.Line; }
}
public int Column {
get { return location.Column; }
}
}
/// <inheritdoc/>
public ITextSource CreateSnapshot()
{
return textSource; // textBuffer is immutable
}
/// <inheritdoc/>
public ITextSource CreateSnapshot(int offset, int length)
{
return textSource.CreateSnapshot(offset, length);
}
/// <inheritdoc/>
public IDocument CreateDocumentSnapshot()
{
return this; // ReadOnlyDocument is immutable
}
/// <inheritdoc/>
public System.IO.TextReader CreateReader()
{
return textSource.CreateReader();
}
/// <inheritdoc/>
public System.IO.TextReader CreateReader(int offset, int length)
{
return textSource.CreateReader(offset, length);
}
/// <inheritdoc/>
public void WriteTextTo(System.IO.TextWriter writer)
{
textSource.WriteTextTo(writer);
}
/// <inheritdoc/>
public void WriteTextTo(System.IO.TextWriter writer, int offset, int length)
{
textSource.WriteTextTo(writer, offset, length);
}
/// <inheritdoc/>
public char GetCharAt(int offset)
{
return textSource.GetCharAt(offset);
}
/// <inheritdoc/>
public string GetText(int offset, int length)
{
return textSource.GetText(offset, length);
}
/// <inheritdoc/>
public string GetText(ISegment segment)
{
return textSource.GetText(segment);
}
/// <inheritdoc/>
public int IndexOf(char c, int startIndex, int count)
{
return textSource.IndexOf(c, startIndex, count);
}
/// <inheritdoc/>
public int IndexOfAny(char[] anyOf, int startIndex, int count)
{
return textSource.IndexOfAny(anyOf, startIndex, count);
}
/// <inheritdoc/>
public int IndexOf(string searchText, int startIndex, int count, StringComparison comparisonType)
{
return textSource.IndexOf(searchText, startIndex, count, comparisonType);
}
/// <inheritdoc/>
public int LastIndexOf(char c, int startIndex, int count)
{
return textSource.LastIndexOf(c, startIndex, count);
}
/// <inheritdoc/>
public int LastIndexOf(string searchText, int startIndex, int count, StringComparison comparisonType)
{
return textSource.LastIndexOf(searchText, startIndex, count, comparisonType);
}
object IServiceProvider.GetService(Type serviceType)
{
return null;
}
/// <inheritdoc/>
/// <remarks>Will never be raised on <see cref="ReadOnlyDocument" />.</remarks>
public event EventHandler FileNameChanged { add {} remove {} }
/// <inheritdoc/>
public string FileName {
get { return fileName; }
}
}
}

493
ICSharpCode.Decompiler/Editor/StringBuilderDocument.cs

@ -0,0 +1,493 @@ @@ -0,0 +1,493 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// Document based on a string builder.
/// This class serves as a reference implementation for the IDocument interface.
/// </summary>
public class StringBuilderDocument : IDocument
{
readonly StringBuilder b;
readonly TextSourceVersionProvider versionProvider = new TextSourceVersionProvider();
/// <summary>
/// Creates a new StringBuilderDocument.
/// </summary>
public StringBuilderDocument()
{
b = new StringBuilder();
}
/// <summary>
/// Creates a new StringBuilderDocument with the specified initial text.
/// </summary>
public StringBuilderDocument(string text)
{
if (text == null)
throw new ArgumentNullException("text");
b = new StringBuilder(text);
}
/// <summary>
/// Creates a new StringBuilderDocument with the initial text copied from the specified text source.
/// </summary>
public StringBuilderDocument(ITextSource textSource)
{
if (textSource == null)
throw new ArgumentNullException("textSource");
b = new StringBuilder(textSource.TextLength);
textSource.WriteTextTo(new StringWriter(b));
}
/// <inheritdoc/>
public event EventHandler<TextChangeEventArgs> TextChanging;
/// <inheritdoc/>
public event EventHandler<TextChangeEventArgs> TextChanged;
/// <inheritdoc/>
public event EventHandler ChangeCompleted;
/// <inheritdoc/>
public ITextSourceVersion Version {
get { return versionProvider.CurrentVersion; }
}
#region Line<->Offset
/// <inheritdoc/>
public int LineCount {
get { return CreateDocumentSnapshot().LineCount; }
}
/// <inheritdoc/>
public IDocumentLine GetLineByNumber(int lineNumber)
{
return CreateDocumentSnapshot().GetLineByNumber(lineNumber);
}
/// <inheritdoc/>
public IDocumentLine GetLineByOffset(int offset)
{
return CreateDocumentSnapshot().GetLineByOffset(offset);
}
/// <inheritdoc/>
public int GetOffset(int line, int column)
{
return CreateDocumentSnapshot().GetOffset(line, column);
}
/// <inheritdoc/>
public int GetOffset(TextLocation location)
{
return CreateDocumentSnapshot().GetOffset(location);
}
/// <inheritdoc/>
public TextLocation GetLocation(int offset)
{
return CreateDocumentSnapshot().GetLocation(offset);
}
#endregion
#region Insert/Remove/Replace
/// <inheritdoc/>
public void Insert(int offset, string text)
{
Replace(offset, 0, text);
}
/// <inheritdoc/>
public void Insert(int offset, ITextSource text)
{
if (text == null)
throw new ArgumentNullException("text");
Replace(offset, 0, text.Text);
}
/// <inheritdoc/>
public void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType)
{
if (offset < 0 || offset > this.TextLength)
throw new ArgumentOutOfRangeException("offset");
if (text == null)
throw new ArgumentNullException("text");
if (defaultAnchorMovementType == AnchorMovementType.BeforeInsertion)
PerformChange(new InsertionWithMovementBefore(offset, text));
else
Replace(offset, 0, text);
}
/// <inheritdoc/>
public void Insert(int offset, ITextSource text, AnchorMovementType defaultAnchorMovementType)
{
if (text == null)
throw new ArgumentNullException("text");
Insert(offset, text.Text, defaultAnchorMovementType);
}
[Serializable]
sealed class InsertionWithMovementBefore : TextChangeEventArgs
{
public InsertionWithMovementBefore(int offset, string newText) : base(offset, string.Empty, newText)
{
}
public override int GetNewOffset(int offset, AnchorMovementType movementType)
{
if (offset == this.Offset && movementType == AnchorMovementType.Default)
return offset;
else
return base.GetNewOffset(offset, movementType);
}
}
/// <inheritdoc/>
public void Remove(int offset, int length)
{
Replace(offset, length, string.Empty);
}
/// <inheritdoc/>
public void Replace(int offset, int length, string newText)
{
if (offset < 0 || offset > this.TextLength)
throw new ArgumentOutOfRangeException("offset");
if (length < 0 || length > this.TextLength - offset)
throw new ArgumentOutOfRangeException("length");
if (newText == null)
throw new ArgumentNullException("newText");
PerformChange(new TextChangeEventArgs(offset, b.ToString(offset, length), newText));
}
/// <inheritdoc/>
public void Replace(int offset, int length, ITextSource newText)
{
if (newText == null)
throw new ArgumentNullException("newText");
Replace(offset, length, newText.Text);
}
bool isInChange;
void PerformChange(TextChangeEventArgs change)
{
// Ensure that all changes take place inside an update group.
// Will also take care of throwing an exception if isInChange is set.
StartUndoableAction();
try {
isInChange = true;
try {
if (TextChanging != null)
TextChanging(this, change);
// Perform changes to document and Version property
documentSnapshot = null;
cachedText = null;
b.Remove(change.Offset, change.RemovalLength);
b.Insert(change.Offset, change.InsertedText.Text);
versionProvider.AppendChange(change);
// Update anchors and fire Deleted events
UpdateAnchors(change);
if (TextChanged != null)
TextChanged(this, change);
} finally {
isInChange = false;
}
} finally {
EndUndoableAction();
}
}
#endregion
#region Undo
int undoGroupNesting = 0;
/// <inheritdoc/>
public void StartUndoableAction()
{
// prevent changes from within the TextChanging/TextChanged event handlers
if (isInChange)
throw new InvalidOperationException();
undoGroupNesting++;
}
/// <inheritdoc/>
public void EndUndoableAction()
{
undoGroupNesting--;
if (undoGroupNesting == 0) {
if (ChangeCompleted != null)
ChangeCompleted(this, EventArgs.Empty);
}
}
/// <inheritdoc/>
public IDisposable OpenUndoGroup()
{
StartUndoableAction();
return new CallbackOnDispose(EndUndoableAction);
}
#endregion
#region CreateSnapshot/CreateReader
ReadOnlyDocument documentSnapshot;
/// <inheritdoc/>
public IDocument CreateDocumentSnapshot()
{
if (documentSnapshot == null)
documentSnapshot = new ReadOnlyDocument(this, this.FileName);
return documentSnapshot;
}
/// <inheritdoc/>
public ITextSource CreateSnapshot()
{
return new StringTextSource(this.Text, versionProvider.CurrentVersion);
}
/// <inheritdoc/>
public ITextSource CreateSnapshot(int offset, int length)
{
return new StringTextSource(GetText(offset, length));
}
/// <inheritdoc/>
public TextReader CreateReader()
{
return new StringReader(this.Text);
}
/// <inheritdoc/>
public TextReader CreateReader(int offset, int length)
{
return new StringReader(GetText(offset, length));
}
/// <inheritdoc/>
public void WriteTextTo(TextWriter writer)
{
if (writer == null)
throw new ArgumentNullException("writer");
writer.Write(this.Text);
}
/// <inheritdoc/>
public void WriteTextTo(TextWriter writer, int offset, int length)
{
if (writer == null)
throw new ArgumentNullException("writer");
writer.Write(GetText(offset, length));
}
#endregion
#region GetText / IndexOf
string cachedText;
/// <inheritdoc/>
public string Text {
get {
if (cachedText == null)
cachedText = b.ToString();
return cachedText;
}
set {
Replace(0, b.Length, value);
}
}
/// <inheritdoc/>
public int TextLength {
get { return b.Length; }
}
/// <inheritdoc/>
public char GetCharAt(int offset)
{
return b[offset];
}
/// <inheritdoc/>
public string GetText(int offset, int length)
{
return b.ToString(offset, length);
}
/// <inheritdoc/>
public string GetText(ISegment segment)
{
if (segment == null)
throw new ArgumentNullException("segment");
return b.ToString(segment.Offset, segment.Length);
}
/// <inheritdoc/>
public int IndexOf(char c, int startIndex, int count)
{
return this.Text.IndexOf(c, startIndex, count);
}
/// <inheritdoc/>
public int IndexOfAny(char[] anyOf, int startIndex, int count)
{
return this.Text.IndexOfAny(anyOf, startIndex, count);
}
/// <inheritdoc/>
public int IndexOf(string searchText, int startIndex, int count, StringComparison comparisonType)
{
return this.Text.IndexOf(searchText, startIndex, count, comparisonType);
}
/// <inheritdoc/>
public int LastIndexOf(char c, int startIndex, int count)
{
return this.Text.LastIndexOf(c, startIndex + count - 1, count);
}
/// <inheritdoc/>
public int LastIndexOf(string searchText, int startIndex, int count, StringComparison comparisonType)
{
return this.Text.LastIndexOf(searchText, startIndex + count - 1, count, comparisonType);
}
#endregion
#region CreateAnchor
readonly List<WeakReference> anchors = new List<WeakReference>();
/// <inheritdoc/>
public ITextAnchor CreateAnchor(int offset)
{
var newAnchor = new SimpleAnchor(this, offset);
for (int i = 0; i < anchors.Count; i++) {
if (!anchors[i].IsAlive)
anchors[i] = new WeakReference(newAnchor);
}
anchors.Add(new WeakReference(newAnchor));
return newAnchor;
}
void UpdateAnchors(TextChangeEventArgs change)
{
// First update all anchors, then fire the deleted events.
List<int> deletedAnchors = new List<int>();
for (int i = 0; i < anchors.Count; i++) {
var anchor = anchors[i].Target as SimpleAnchor;
if (anchor != null) {
anchor.Update(change);
if (anchor.IsDeleted)
deletedAnchors.Add(i);
}
}
deletedAnchors.Reverse();
foreach (var index in deletedAnchors) {
var anchor = anchors[index].Target as SimpleAnchor;
if (anchor != null)
anchor.RaiseDeletedEvent();
anchors.RemoveAt(index);
}
}
sealed class SimpleAnchor : ITextAnchor
{
readonly StringBuilderDocument document;
int offset;
public SimpleAnchor(StringBuilderDocument document, int offset)
{
this.document = document;
this.offset = offset;
}
public event EventHandler Deleted;
public TextLocation Location {
get {
if (IsDeleted)
throw new InvalidOperationException();
return document.GetLocation(offset);
}
}
public int Offset {
get {
if (IsDeleted)
throw new InvalidOperationException();
return offset;
}
}
public AnchorMovementType MovementType { get; set; }
public bool SurviveDeletion { get; set; }
public bool IsDeleted {
get { return offset < 0; }
}
public void Update(TextChangeEventArgs change)
{
if (SurviveDeletion || offset <= change.Offset || offset >= change.Offset + change.RemovalLength) {
offset = change.GetNewOffset(offset, MovementType);
} else {
offset = -1;
}
}
public void RaiseDeletedEvent()
{
if (Deleted != null)
Deleted(this, EventArgs.Empty);
}
public int Line {
get { return this.Location.Line; }
}
public int Column {
get { return this.Location.Column; }
}
}
#endregion
/// <inheritdoc/>
public virtual object GetService(Type serviceType)
{
return null;
}
/// <inheritdoc/>
public virtual event EventHandler FileNameChanged { add {} remove {} }
/// <inheritdoc/>
public virtual string FileName {
get { return string.Empty; }
}
}
}

160
ICSharpCode.Decompiler/Editor/StringTextSource.cs

@ -0,0 +1,160 @@ @@ -0,0 +1,160 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// Implements the ITextSource interface using a string.
/// </summary>
[Serializable]
public class StringTextSource : ITextSource
{
/// <summary>
/// Gets a text source containing the empty string.
/// </summary>
public static readonly StringTextSource Empty = new StringTextSource(string.Empty);
readonly string text;
readonly ITextSourceVersion version;
/// <summary>
/// Creates a new StringTextSource with the given text.
/// </summary>
public StringTextSource(string text)
{
if (text == null)
throw new ArgumentNullException("text");
this.text = text;
}
/// <summary>
/// Creates a new StringTextSource with the given text.
/// </summary>
public StringTextSource(string text, ITextSourceVersion version)
{
if (text == null)
throw new ArgumentNullException("text");
this.text = text;
this.version = version;
}
/// <inheritdoc/>
public ITextSourceVersion Version {
get { return version; }
}
/// <inheritdoc/>
public int TextLength {
get { return text.Length; }
}
/// <inheritdoc/>
public string Text {
get { return text; }
}
/// <inheritdoc/>
public ITextSource CreateSnapshot()
{
return this; // StringTextSource is immutable
}
/// <inheritdoc/>
public ITextSource CreateSnapshot(int offset, int length)
{
return new StringTextSource(text.Substring(offset, length));
}
/// <inheritdoc/>
public TextReader CreateReader()
{
return new StringReader(text);
}
/// <inheritdoc/>
public TextReader CreateReader(int offset, int length)
{
return new StringReader(text.Substring(offset, length));
}
/// <inheritdoc/>
public void WriteTextTo(TextWriter writer)
{
writer.Write(text);
}
/// <inheritdoc/>
public void WriteTextTo(TextWriter writer, int offset, int length)
{
writer.Write(text.Substring(offset, length));
}
/// <inheritdoc/>
public char GetCharAt(int offset)
{
return text[offset];
}
/// <inheritdoc/>
public string GetText(int offset, int length)
{
return text.Substring(offset, length);
}
/// <inheritdoc/>
public string GetText(ISegment segment)
{
if (segment == null)
throw new ArgumentNullException("segment");
return text.Substring(segment.Offset, segment.Length);
}
/// <inheritdoc/>
public int IndexOf(char c, int startIndex, int count)
{
return text.IndexOf(c, startIndex, count);
}
/// <inheritdoc/>
public int IndexOfAny(char[] anyOf, int startIndex, int count)
{
return text.IndexOfAny(anyOf, startIndex, count);
}
/// <inheritdoc/>
public int IndexOf(string searchText, int startIndex, int count, StringComparison comparisonType)
{
return text.IndexOf(searchText, startIndex, count, comparisonType);
}
/// <inheritdoc/>
public int LastIndexOf(char c, int startIndex, int count)
{
return text.LastIndexOf(c, startIndex + count - 1, count);
}
/// <inheritdoc/>
public int LastIndexOf(string searchText, int startIndex, int count, StringComparison comparisonType)
{
return text.LastIndexOf(searchText, startIndex + count - 1, count, comparisonType);
}
}
}

118
ICSharpCode.Decompiler/Editor/TextChangeEventArgs.cs

@ -0,0 +1,118 @@ @@ -0,0 +1,118 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// Describes a change of the document text.
/// This class is thread-safe.
/// </summary>
[Serializable]
public class TextChangeEventArgs : EventArgs
{
readonly int offset;
readonly ITextSource removedText;
readonly ITextSource insertedText;
/// <summary>
/// The offset at which the change occurs.
/// </summary>
public int Offset {
get { return offset; }
}
/// <summary>
/// The text that was removed.
/// </summary>
public ITextSource RemovedText {
get { return removedText; }
}
/// <summary>
/// The number of characters removed.
/// </summary>
public int RemovalLength {
get { return removedText.TextLength; }
}
/// <summary>
/// The text that was inserted.
/// </summary>
public ITextSource InsertedText {
get { return insertedText; }
}
/// <summary>
/// The number of characters inserted.
/// </summary>
public int InsertionLength {
get { return insertedText.TextLength; }
}
/// <summary>
/// Creates a new TextChangeEventArgs object.
/// </summary>
public TextChangeEventArgs(int offset, string removedText, string insertedText)
{
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", offset, "offset must not be negative");
this.offset = offset;
this.removedText = removedText != null ? new StringTextSource(removedText) : StringTextSource.Empty;
this.insertedText = insertedText != null ? new StringTextSource(insertedText) : StringTextSource.Empty;
}
/// <summary>
/// Creates a new TextChangeEventArgs object.
/// </summary>
public TextChangeEventArgs(int offset, ITextSource removedText, ITextSource insertedText)
{
if (offset < 0)
throw new ArgumentOutOfRangeException("offset", offset, "offset must not be negative");
this.offset = offset;
this.removedText = removedText ?? StringTextSource.Empty;
this.insertedText = insertedText ?? StringTextSource.Empty;
}
/// <summary>
/// Gets the new offset where the specified offset moves after this document change.
/// </summary>
public virtual int GetNewOffset(int offset, AnchorMovementType movementType = AnchorMovementType.Default)
{
if (offset >= this.Offset && offset <= this.Offset + this.RemovalLength) {
if (movementType == AnchorMovementType.BeforeInsertion)
return this.Offset;
else
return this.Offset + this.InsertionLength;
} else if (offset > this.Offset) {
return offset + this.InsertionLength - this.RemovalLength;
} else {
return offset;
}
}
/// <summary>
/// Creates TextChangeEventArgs for the reverse change.
/// </summary>
public virtual TextChangeEventArgs Invert()
{
return new TextChangeEventArgs(offset, insertedText, removedText);
}
}
}

130
ICSharpCode.Decompiler/Editor/TextSourceVersionProvider.cs

@ -0,0 +1,130 @@ @@ -0,0 +1,130 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ICSharpCode.NRefactory.Editor
{
/// <summary>
/// Provides ITextSourceVersion instances.
/// </summary>
public class TextSourceVersionProvider
{
Version currentVersion;
public TextSourceVersionProvider()
{
this.currentVersion = new Version(this);
}
/// <summary>
/// Gets the current version.
/// </summary>
public ITextSourceVersion CurrentVersion {
get { return currentVersion; }
}
/// <summary>
/// Replaces the current version with a new version.
/// </summary>
/// <param name="change">Change from current version to new version</param>
public void AppendChange(TextChangeEventArgs change)
{
if (change == null)
throw new ArgumentNullException("change");
currentVersion.change = change;
currentVersion.next = new Version(currentVersion);
currentVersion = currentVersion.next;
}
[DebuggerDisplay("Version #{id}")]
sealed class Version : ITextSourceVersion
{
// Reference back to the provider.
// Used to determine if two checkpoints belong to the same document.
readonly TextSourceVersionProvider provider;
// ID used for CompareAge()
readonly int id;
// the change from this version to the next version
internal TextChangeEventArgs change;
internal Version next;
internal Version(TextSourceVersionProvider provider)
{
this.provider = provider;
}
internal Version(Version prev)
{
this.provider = prev.provider;
this.id = unchecked( prev.id + 1 );
}
public bool BelongsToSameDocumentAs(ITextSourceVersion other)
{
Version o = other as Version;
return o != null && provider == o.provider;
}
public int CompareAge(ITextSourceVersion other)
{
if (other == null)
throw new ArgumentNullException("other");
Version o = other as Version;
if (o == null || provider != o.provider)
throw new ArgumentException("Versions do not belong to the same document.");
// We will allow overflows, but assume that the maximum distance between checkpoints is 2^31-1.
// This is guaranteed on x86 because so many checkpoints don't fit into memory.
return Math.Sign(unchecked( this.id - o.id ));
}
public IEnumerable<TextChangeEventArgs> GetChangesTo(ITextSourceVersion other)
{
int result = CompareAge(other);
Version o = (Version)other;
if (result < 0)
return GetForwardChanges(o);
else if (result > 0)
return o.GetForwardChanges(this).Reverse().Select(change => change.Invert());
else
return EmptyList<TextChangeEventArgs>.Instance;
}
IEnumerable<TextChangeEventArgs> GetForwardChanges(Version other)
{
// Return changes from this(inclusive) to other(exclusive).
for (Version node = this; node != other; node = node.next) {
yield return node.change;
}
}
public int MoveOffsetTo(ITextSourceVersion other, int oldOffset, AnchorMovementType movement)
{
int offset = oldOffset;
foreach (var e in GetChangesTo(other)) {
offset = e.GetNewOffset(offset, movement);
}
return offset;
}
}
}
}

365
ICSharpCode.Decompiler/Editor/UnicodeNewline.cs

@ -0,0 +1,365 @@ @@ -0,0 +1,365 @@
//
// UnicodeNewline.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory
{
public enum UnicodeNewline {
Unknown,
/// <summary>
/// Line Feed, U+000A
/// </summary>
LF = 0x0A,
CRLF = 0x0D0A,
/// <summary>
/// Carriage Return, U+000D
/// </summary>
CR = 0x0D,
/// <summary>
/// Next Line, U+0085
/// </summary>
NEL = 0x85,
/// <summary>
/// Vertical Tab, U+000B
/// </summary>
VT = 0x0B,
/// <summary>
/// Form Feed, U+000C
/// </summary>
FF = 0x0C,
/// <summary>
/// Line Separator, U+2028
/// </summary>
LS = 0x2028,
/// <summary>
/// Paragraph Separator, U+2029
/// </summary>
PS = 0x2029
}
/// <summary>
/// Defines unicode new lines according to Unicode Technical Report #13
/// http://www.unicode.org/standard/reports/tr13/tr13-5.html
/// </summary>
public static class NewLine
{
/// <summary>
/// Carriage Return, U+000D
/// </summary>
public const char CR = (char)0x0D;
/// <summary>
/// Line Feed, U+000A
/// </summary>
public const char LF = (char)0x0A;
/// <summary>
/// Next Line, U+0085
/// </summary>
public const char NEL = (char)0x85;
/// <summary>
/// Vertical Tab, U+000B
/// </summary>
public const char VT = (char)0x0B;
/// <summary>
/// Form Feed, U+000C
/// </summary>
public const char FF = (char)0x0C;
/// <summary>
/// Line Separator, U+2028
/// </summary>
public const char LS = (char)0x2028;
/// <summary>
/// Paragraph Separator, U+2029
/// </summary>
public const char PS = (char)0x2029;
/// <summary>
/// Determines if a char is a new line delimiter.
/// </summary>
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns>
/// <param name="curChar">The current character.</param>
/// <param name="nextChar">A callback getting the next character (may be null).</param>
public static int GetDelimiterLength (char curChar, Func<char> nextChar = null)
{
if (curChar == CR) {
if (nextChar != null && nextChar () == LF)
return 2;
return 1;
}
if (curChar == LF || curChar == NEL || curChar == VT || curChar == FF || curChar == LS || curChar == PS)
return 1;
return 0;
}
/// <summary>
/// Determines if a char is a new line delimiter.
/// </summary>
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns>
/// <param name="curChar">The current character.</param>
/// <param name="nextChar">The next character (if != LF then length will always be 0 or 1).</param>
public static int GetDelimiterLength (char curChar, char nextChar)
{
if (curChar == CR) {
if (nextChar == LF)
return 2;
return 1;
}
if (curChar == LF || curChar == NEL || curChar == VT || curChar == FF || curChar == LS || curChar == PS)
return 1;
return 0;
}
/// <summary>
/// Determines if a char is a new line delimiter.
/// </summary>
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns>
/// <param name="curChar">The current character.</param>
/// <param name = "length">The length of the delimiter</param>
/// <param name = "type">The type of the delimiter</param>
/// <param name="nextChar">A callback getting the next character (may be null).</param>
public static bool TryGetDelimiterLengthAndType (char curChar, out int length, out UnicodeNewline type, Func<char> nextChar = null)
{
if (curChar == CR) {
if (nextChar != null && nextChar () == LF) {
length = 2;
type = UnicodeNewline.CRLF;
} else {
length = 1;
type = UnicodeNewline.CR;
}
return true;
}
switch (curChar) {
case LF:
type = UnicodeNewline.LF;
length = 1;
return true;
case NEL:
type = UnicodeNewline.NEL;
length = 1;
return true;
case VT:
type = UnicodeNewline.VT;
length = 1;
return true;
case FF:
type = UnicodeNewline.FF;
length = 1;
return true;
case LS:
type = UnicodeNewline.LS;
length = 1;
return true;
case PS:
type = UnicodeNewline.PS;
length = 1;
return true;
}
length = -1;
type = UnicodeNewline.Unknown;
return false;
}
/// <summary>
/// Determines if a char is a new line delimiter.
/// </summary>
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns>
/// <param name="curChar">The current character.</param>
/// <param name = "length">The length of the delimiter</param>
/// <param name = "type">The type of the delimiter</param>
/// <param name="nextChar">The next character (if != LF then length will always be 0 or 1).</param>
public static bool TryGetDelimiterLengthAndType (char curChar, out int length, out UnicodeNewline type, char nextChar)
{
if (curChar == CR) {
if (nextChar == LF) {
length = 2;
type = UnicodeNewline.CRLF;
} else {
length = 1;
type = UnicodeNewline.CR;
}
return true;
}
switch (curChar) {
case LF:
type = UnicodeNewline.LF;
length = 1;
return true;
case NEL:
type = UnicodeNewline.NEL;
length = 1;
return true;
case VT:
type = UnicodeNewline.VT;
length = 1;
return true;
case FF:
type = UnicodeNewline.FF;
length = 1;
return true;
case LS:
type = UnicodeNewline.LS;
length = 1;
return true;
case PS:
type = UnicodeNewline.PS;
length = 1;
return true;
}
length = -1;
type = UnicodeNewline.Unknown;
return false;
}
/// <summary>
/// Gets the new line type of a given char/next char.
/// </summary>
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns>
/// <param name="curChar">The current character.</param>
/// <param name="nextChar">A callback getting the next character (may be null).</param>
public static UnicodeNewline GetDelimiterType (char curChar, Func<char> nextChar = null)
{
switch (curChar) {
case CR:
if (nextChar != null && nextChar () == LF)
return UnicodeNewline.CRLF;
return UnicodeNewline.CR;
case LF:
return UnicodeNewline.LF;
case NEL:
return UnicodeNewline.NEL;
case VT:
return UnicodeNewline.VT;
case FF:
return UnicodeNewline.FF;
case LS:
return UnicodeNewline.LS;
case PS:
return UnicodeNewline.PS;
}
return UnicodeNewline.Unknown;
}
/// <summary>
/// Gets the new line type of a given char/next char.
/// </summary>
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns>
/// <param name="curChar">The current character.</param>
/// <param name="nextChar">The next character (if != LF then length will always be 0 or 1).</param>
public static UnicodeNewline GetDelimiterType (char curChar, char nextChar)
{
switch (curChar) {
case CR:
if (nextChar == LF)
return UnicodeNewline.CRLF;
return UnicodeNewline.CR;
case LF:
return UnicodeNewline.LF;
case NEL:
return UnicodeNewline.NEL;
case VT:
return UnicodeNewline.VT;
case FF:
return UnicodeNewline.FF;
case LS:
return UnicodeNewline.LS;
case PS:
return UnicodeNewline.PS;
}
return UnicodeNewline.Unknown;
}
/// <summary>
/// Determines if a char is a new line delimiter.
///
/// Note that the only 2 char wide new line is CR LF and both chars are new line
/// chars on their own. For most cases GetDelimiterLength is the better choice.
/// </summary>
public static bool IsNewLine(char ch)
{
return
ch == NewLine.CR ||
ch == NewLine.LF ||
ch == NewLine.NEL ||
ch == NewLine.VT ||
ch == NewLine.FF ||
ch == NewLine.LS ||
ch == NewLine.PS;
}
/// <summary>
/// Gets the new line as a string.
/// </summary>
public static string GetString (UnicodeNewline newLine)
{
switch (newLine) {
case UnicodeNewline.Unknown:
return "";
case UnicodeNewline.LF:
return "\n";
case UnicodeNewline.CRLF:
return "\r\n";
case UnicodeNewline.CR:
return "\r";
case UnicodeNewline.NEL:
return "\u0085";
case UnicodeNewline.VT:
return "\u000B";
case UnicodeNewline.FF:
return "\u000C";
case UnicodeNewline.LS:
return "\u2028";
case UnicodeNewline.PS:
return "\u2029";
default:
throw new ArgumentOutOfRangeException ();
}
}
}
}

58
ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs

@ -121,34 +121,34 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -121,34 +121,34 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
return false;
}
public static GraphVizGraph ExportGraph(IReadOnlyList<ControlFlowNode> nodes, Func<ControlFlowNode, string> labelFunc = null)
{
if (labelFunc == null) {
labelFunc = node => {
var block = node.UserData as IL.Block;
return block != null ? block.Label : node.UserData?.ToString();
};
}
GraphVizGraph g = new GraphVizGraph();
GraphVizNode[] n = new GraphVizNode[nodes.Count];
for (int i = 0; i < n.Length; i++) {
n[i] = new GraphVizNode(nodes[i].UserIndex);
n[i].shape = "box";
n[i].label = labelFunc(nodes[i]);
g.AddNode(n[i]);
}
foreach (var source in nodes) {
foreach (var target in source.Successors) {
g.AddEdge(new GraphVizEdge(source.UserIndex, target.UserIndex));
}
if (source.ImmediateDominator != null) {
g.AddEdge(
new GraphVizEdge(source.ImmediateDominator.UserIndex, source.UserIndex) {
color = "green"
});
}
}
return g;
}
//public static GraphVizGraph ExportGraph(IReadOnlyList<ControlFlowNode> nodes, Func<ControlFlowNode, string> labelFunc = null)
//{
// if (labelFunc == null) {
// labelFunc = node => {
// var block = node.UserData as IL.Block;
// return block != null ? block.Label : node.UserData?.ToString();
// };
// }
// GraphVizGraph g = new GraphVizGraph();
// GraphVizNode[] n = new GraphVizNode[nodes.Count];
// for (int i = 0; i < n.Length; i++) {
// n[i] = new GraphVizNode(nodes[i].UserIndex);
// n[i].shape = "box";
// n[i].label = labelFunc(nodes[i]);
// g.AddNode(n[i]);
// }
// foreach (var source in nodes) {
// foreach (var target in source.Successors) {
// g.AddEdge(new GraphVizEdge(source.UserIndex, target.UserIndex));
// }
// if (source.ImmediateDominator != null) {
// g.AddEdge(
// new GraphVizEdge(source.ImmediateDominator.UserIndex, source.UserIndex) {
// color = "green"
// });
// }
// }
// return g;
//}
}
}

203
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -144,7 +144,19 @@ @@ -144,7 +144,19 @@
<Compile Include="CSharp\Ast\Modifiers.cs" />
<Compile Include="CSharp\Ast\NodeType.cs" />
<Compile Include="CSharp\Ast\ObservableAstVisitor.cs" />
<Compile Include="CSharp\Ast\PatternMatching\AnyNode.cs" />
<Compile Include="CSharp\Ast\PatternMatching\AnyNodeOrNull.cs" />
<Compile Include="CSharp\Ast\PatternMatching\Backreference.cs" />
<Compile Include="CSharp\Ast\PatternMatching\BacktrackingInfo.cs" />
<Compile Include="CSharp\Ast\PatternMatching\Choice.cs" />
<Compile Include="CSharp\Ast\PatternMatching\INode.cs" />
<Compile Include="CSharp\Ast\PatternMatching\Match.cs" />
<Compile Include="CSharp\Ast\PatternMatching\NamedNode.cs" />
<Compile Include="CSharp\Ast\PatternMatching\OptionalNode.cs" />
<Compile Include="CSharp\Ast\PatternMatching\Pattern.cs" />
<Compile Include="CSharp\Ast\PatternMatching\Repeat.cs" />
<Compile Include="CSharp\Ast\PrimitiveType.cs" />
<Compile Include="CSharp\Ast\Role.cs" />
<Compile Include="CSharp\Ast\Roles.cs" />
<Compile Include="CSharp\Ast\SimpleType.cs" />
<Compile Include="CSharp\Ast\Statements\BlockStatement.cs" />
@ -175,6 +187,7 @@ @@ -175,6 +187,7 @@
<Compile Include="CSharp\Ast\Statements\YieldReturnStatement.cs" />
<Compile Include="CSharp\Ast\SyntaxExtensions.cs" />
<Compile Include="CSharp\Ast\SyntaxTree.cs" />
<Compile Include="CSharp\Ast\TextLocation.cs" />
<Compile Include="CSharp\Ast\TokenRole.cs" />
<Compile Include="CSharp\Ast\TypeMembers\Accessor.cs" />
<Compile Include="CSharp\Ast\TypeMembers\ConstructorDeclaration.cs" />
@ -260,11 +273,30 @@ @@ -260,11 +273,30 @@
<Compile Include="CSharp\Transforms\IntroduceUnsafeModifier.cs" />
<Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" />
<Compile Include="CSharp\WholeProjectDecompiler.cs" />
<Compile Include="Documentation\DocumentationComment.cs" />
<Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" />
<Compile Include="Documentation\IDocumentationProvider.cs" />
<Compile Include="Documentation\IdStringMemberReference.cs" />
<Compile Include="Documentation\IdStringProvider.cs" />
<Compile Include="Documentation\XmlDocumentationProvider.cs" />
<Compile Include="Editor\IDocument.cs" />
<Compile Include="Editor\IDocumentLine.cs" />
<Compile Include="Editor\ISegment.cs" />
<Compile Include="Editor\ITextAnchor.cs" />
<Compile Include="Editor\ITextPasteHandler.cs" />
<Compile Include="Editor\ITextSource.cs" />
<Compile Include="Editor\ReadOnlyDocument.cs" />
<Compile Include="Editor\StringBuilderDocument.cs" />
<Compile Include="Editor\StringTextSource.cs" />
<Compile Include="Editor\TextChangeEventArgs.cs" />
<Compile Include="Editor\TextSourceVersionProvider.cs" />
<Compile Include="Editor\UnicodeNewline.cs" />
<Compile Include="FlowAnalysis\ControlFlowNode.cs" />
<Compile Include="FlowAnalysis\DataFlowVisitor.cs" />
<Compile Include="FlowAnalysis\DefiniteAssignmentVisitor.cs" />
<Compile Include="FlowAnalysis\Dominance.cs" />
<Compile Include="FlowAnalysis\ReachingDefinitionsVisitor.cs" />
<Compile Include="CSharp\Ast\IAnnotatable.cs" />
<Compile Include="IL\ControlFlow\ConditionDetection.cs" />
<Compile Include="IL\ControlFlow\ControlFlowSimplification.cs" />
<Compile Include="IL\ControlFlow\DetectPinnedRegions.cs" />
@ -340,17 +372,170 @@ @@ -340,17 +372,170 @@
<Compile Include="Output\PlainTextOutput.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Output\TextOutputWriter.cs" />
<Compile Include="Semantics\AmbiguousResolveResult.cs" />
<Compile Include="Semantics\ArrayAccessResolveResult.cs" />
<Compile Include="Semantics\ArrayCreateResolveResult.cs" />
<Compile Include="Semantics\ByReferenceResolveResult.cs" />
<Compile Include="Semantics\ConstantResolveResult.cs" />
<Compile Include="Semantics\Conversion.cs" />
<Compile Include="Semantics\ConversionResolveResult.cs" />
<Compile Include="Semantics\ErrorResolveResult.cs" />
<Compile Include="Semantics\ForEachResolveResult.cs" />
<Compile Include="Semantics\InitializedObjectResolveResult.cs" />
<Compile Include="Semantics\InvocationResolveResult.cs" />
<Compile Include="Semantics\LocalResolveResult.cs" />
<Compile Include="Semantics\MemberResolveResult.cs" />
<Compile Include="Semantics\NamedArgumentResolveResult.cs" />
<Compile Include="Semantics\NamespaceResolveResult.cs" />
<Compile Include="Semantics\OperatorResolveResult.cs" />
<Compile Include="Semantics\ResolveResult.cs" />
<Compile Include="Semantics\SizeOfResolveResult.cs" />
<Compile Include="Semantics\ThisResolveResult.cs" />
<Compile Include="Semantics\TypeIsResolveResult.cs" />
<Compile Include="Semantics\TypeOfResolveResult.cs" />
<Compile Include="Semantics\TypeResolveResult.cs" />
<Compile Include="Semantics\UnknownMemberResolveResult.cs" />
<Compile Include="TypeSystem\Accessibility.cs" />
<Compile Include="TypeSystem\AnonymousType.cs" />
<Compile Include="TypeSystem\ArrayType.cs" />
<Compile Include="TypeSystem\AssemblyLoader.cs" />
<Compile Include="TypeSystem\AssemblyQualifiedTypeName.cs" />
<Compile Include="TypeSystem\ByReferenceType.cs" />
<Compile Include="TypeSystem\CecilLoader.cs" />
<Compile Include="TypeSystem\ComHelper.cs" />
<Compile Include="TypeSystem\DecompilerTypeSystem.cs" />
<Compile Include="TypeSystem\DefaultSolutionSnapshot.cs" />
<Compile Include="TypeSystem\DomRegion.cs" />
<Compile Include="TypeSystem\EntityType.cs" />
<Compile Include="TypeSystem\Error.cs" />
<Compile Include="TypeSystem\FullTypeName.cs" />
<Compile Include="TypeSystem\IAmbience.cs" />
<Compile Include="TypeSystem\IAssembly.cs" />
<Compile Include="TypeSystem\IAttribute.cs" />
<Compile Include="TypeSystem\ICodeContext.cs" />
<Compile Include="TypeSystem\ICompilation.cs" />
<Compile Include="TypeSystem\IConstantValue.cs" />
<Compile Include="TypeSystem\IEntity.cs" />
<Compile Include="TypeSystem\IEvent.cs" />
<Compile Include="TypeSystem\IField.cs" />
<Compile Include="TypeSystem\IFreezable.cs" />
<Compile Include="TypeSystem\IInterningProvider.cs" />
<Compile Include="TypeSystem\IMember.cs" />
<Compile Include="TypeSystem\IMethod.cs" />
<Compile Include="TypeSystem\Implementation\AbstractFreezable.cs" />
<Compile Include="TypeSystem\Implementation\AbstractResolvedEntity.cs" />
<Compile Include="TypeSystem\Implementation\AbstractResolvedMember.cs" />
<Compile Include="TypeSystem\Implementation\AbstractResolvedTypeParameter.cs" />
<Compile Include="TypeSystem\Implementation\AbstractType.cs" />
<Compile Include="TypeSystem\Implementation\AbstractUnresolvedEntity.cs" />
<Compile Include="TypeSystem\Implementation\AbstractUnresolvedMember.cs" />
<Compile Include="TypeSystem\Implementation\AccessorOwnerMemberReference.cs" />
<Compile Include="TypeSystem\Implementation\BaseTypeCollector.cs" />
<Compile Include="TypeSystem\Implementation\BlobReader.cs" />
<Compile Include="TypeSystem\Implementation\DefaultAssemblyReference.cs" />
<Compile Include="TypeSystem\Implementation\DefaultAttribute.cs" />
<Compile Include="TypeSystem\Implementation\DefaultMemberReference.cs" />
<Compile Include="TypeSystem\Implementation\DefaultParameter.cs" />
<Compile Include="TypeSystem\Implementation\DefaultResolvedEvent.cs" />
<Compile Include="TypeSystem\Implementation\DefaultResolvedField.cs" />
<Compile Include="TypeSystem\Implementation\DefaultResolvedMethod.cs" />
<Compile Include="TypeSystem\Implementation\DefaultResolvedProperty.cs" />
<Compile Include="TypeSystem\Implementation\DefaultResolvedTypeDefinition.cs" />
<Compile Include="TypeSystem\Implementation\DefaultResolvedTypeParameter.cs" />
<Compile Include="TypeSystem\Implementation\DefaultUnresolvedAssembly.cs" />
<Compile Include="TypeSystem\Implementation\DefaultUnresolvedAttribute.cs" />
<Compile Include="TypeSystem\Implementation\DefaultUnresolvedEvent.cs" />
<Compile Include="TypeSystem\Implementation\DefaultUnresolvedField.cs" />
<Compile Include="TypeSystem\Implementation\DefaultUnresolvedMethod.cs" />
<Compile Include="TypeSystem\Implementation\DefaultUnresolvedParameter.cs" />
<Compile Include="TypeSystem\Implementation\DefaultUnresolvedProperty.cs" />
<Compile Include="TypeSystem\Implementation\DefaultUnresolvedTypeDefinition.cs" />
<Compile Include="TypeSystem\Implementation\DefaultUnresolvedTypeParameter.cs" />
<Compile Include="TypeSystem\Implementation\DefaultVariable.cs" />
<Compile Include="TypeSystem\Implementation\DummyTypeParameter.cs" />
<Compile Include="TypeSystem\Implementation\ExplicitInterfaceImplementationMemberReference.cs" />
<Compile Include="TypeSystem\Implementation\FullNameAndTypeParameterCount.cs" />
<Compile Include="TypeSystem\Implementation\GetClassTypeReference.cs" />
<Compile Include="TypeSystem\Implementation\GetMembersHelper.cs" />
<Compile Include="TypeSystem\Implementation\KnownTypeCache.cs" />
<Compile Include="TypeSystem\Implementation\MergedNamespace.cs" />
<Compile Include="TypeSystem\Implementation\MinimalCorlib.cs" />
<Compile Include="TypeSystem\Implementation\NestedTypeReference.cs" />
<Compile Include="TypeSystem\Implementation\ResolvedAttributeBlob.cs" />
<Compile Include="TypeSystem\Implementation\SimpleCompilation.cs" />
<Compile Include="TypeSystem\Implementation\SimpleConstantValue.cs" />
<Compile Include="TypeSystem\Implementation\SimpleInterningProvider.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedEvent.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedField.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedMember.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedMethod.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedProperty.cs" />
<Compile Include="TypeSystem\Implementation\SpecializingMemberReference.cs" />
<Compile Include="TypeSystem\Implementation\TypeParameterReference.cs" />
<Compile Include="TypeSystem\Implementation\TypeWithElementType.cs" />
<Compile Include="TypeSystem\Implementation\UnknownType.cs" />
<Compile Include="TypeSystem\Implementation\UnresolvedAttributeBlob.cs" />
<Compile Include="TypeSystem\Implementation\UnresolvedSecurityDeclarationBlob.cs" />
<Compile Include="TypeSystem\Implementation\VoidTypeDefinition.cs" />
<Compile Include="TypeSystem\INamedElement.cs" />
<Compile Include="TypeSystem\INamespace.cs" />
<Compile Include="TypeSystem\InheritanceHelper.cs" />
<Compile Include="TypeSystem\IntersectionType.cs" />
<Compile Include="TypeSystem\IParameter.cs" />
<Compile Include="TypeSystem\IParameterizedMember.cs" />
<Compile Include="TypeSystem\IProjectContent.cs" />
<Compile Include="TypeSystem\IProperty.cs" />
<Compile Include="TypeSystem\ISolutionSnapshot.cs" />
<Compile Include="TypeSystem\ISupportsInterning.cs" />
<Compile Include="TypeSystem\ISymbol.cs" />
<Compile Include="TypeSystem\IType.cs" />
<Compile Include="TypeSystem\ITypeDefinition.cs" />
<Compile Include="TypeSystem\ITypeParameter.cs" />
<Compile Include="TypeSystem\ITypeReference.cs" />
<Compile Include="TypeSystem\IUnresolvedFile.cs" />
<Compile Include="TypeSystem\IVariable.cs" />
<Compile Include="TypeSystem\KnownTypeReference.cs" />
<Compile Include="TypeSystem\NullableType.cs" />
<Compile Include="TypeSystem\ParameterizedType.cs" />
<Compile Include="TypeSystem\ParameterListComparer.cs" />
<Compile Include="TypeSystem\PointerType.cs" />
<Compile Include="TypeSystem\ProjectReference.cs" />
<Compile Include="TypeSystem\ReflectionHelper.cs" />
<Compile Include="TypeSystem\ReflectionNameParseException.cs" />
<Compile Include="TypeSystem\SimpleTypeResolveContext.cs" />
<Compile Include="TypeSystem\SpecialType.cs" />
<Compile Include="TypeSystem\TaskType.cs" />
<Compile Include="TypeSystem\TopLevelTypeName.cs" />
<Compile Include="TypeSystem\TypeKind.cs" />
<Compile Include="TypeSystem\TypeParameterSubstitution.cs" />
<Compile Include="TypeSystem\TypeSystemExtensions.cs" />
<Compile Include="TypeSystem\TypeUtils.cs" />
<Compile Include="TypeSystem\SpecializingDecompilerTypeSystem.cs" />
<Compile Include="TypeSystem\IDecompilerTypeSystem.cs" />
<Compile Include="TypeSystem\ReferenceResolvingException.cs" />
<Compile Include="TypeSystem\TypesHierarchyHelpers.cs" />
<Compile Include="TypeSystem\TypeVisitor.cs" />
<Compile Include="TypeSystem\VarArgInstanceMethod.cs" />
<Compile Include="Util\7BitEncodedInts.cs" />
<Compile Include="Util\BitVector16.cs" />
<Compile Include="Util\BusyManager.cs" />
<Compile Include="Util\CacheManager.cs" />
<Compile Include="Util\CallbackOnDispose.cs" />
<Compile Include="Util\CollectionExtensions.cs" />
<Compile Include="Util\BitSet.cs" />
<Compile Include="Util\CSharpPrimitiveCast.cs" />
<Compile Include="Util\EmptyList.cs" />
<Compile Include="Util\ExtensionMethods.cs" />
<Compile Include="Util\FastSerializer.cs" />
<Compile Include="Util\ImmutableStack.cs" />
<Compile Include="Util\Interval.cs" />
<Compile Include="Util\LazyInit.cs" />
<Compile Include="Util\LongSet.cs" />
<Compile Include="Util\MultiDictionary.cs" />
<Compile Include="Util\Platform.cs" />
<Compile Include="Util\ProjectedList.cs" />
<Compile Include="Util\ReferenceComparer.cs" />
<Compile Include="Util\TreeTraversal.cs" />
<Compile Include="Util\UnionFind.cs" />
<None Include="ICSharpCode.Decompiler.ruleset" />
<None Include="IL\ILOpCodes.tt">
@ -369,14 +554,6 @@ @@ -369,14 +554,6 @@
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory.Cecil\ICSharpCode.NRefactory.Cecil.csproj">
<Project>{2B8F4F83-C2B3-4E84-A27B-8DEE1BE0E006}</Project>
<Name>ICSharpCode.NRefactory.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
@ -384,6 +561,16 @@ @@ -384,6 +561,16 @@
<ItemGroup>
<Folder Include="ILAst\" />
</ItemGroup>
<ItemGroup>
<None Include="..\nrefactory\doc\Pattern Matching.html">
<Link>CSharp\Ast\PatternMatching\Pattern Matching.html</Link>
</None>
</ItemGroup>
<ItemGroup>
<None Include="..\nrefactory\doc\XML Documentation.html">
<Link>Documentation\XML Documentation.html</Link>
</None>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<Target Name="BeforeBuild">
<PropertyGroup>

51
ICSharpCode.Decompiler/Semantics/AmbiguousResolveResult.cs

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents an ambiguous type resolve result.
/// </summary>
public class AmbiguousTypeResolveResult : TypeResolveResult
{
public AmbiguousTypeResolveResult(IType type) : base(type)
{
}
public override bool IsError {
get { return true; }
}
}
/// <summary>
/// Represents an ambiguous field/property/event access.
/// </summary>
public class AmbiguousMemberResolveResult : MemberResolveResult
{
public AmbiguousMemberResolveResult(ResolveResult targetResult, IMember member) : base(targetResult, member)
{
}
public override bool IsError {
get { return true; }
}
}
}

50
ICSharpCode.Decompiler/Semantics/ArrayAccessResolveResult.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Resolve result representing an array access.
/// </summary>
public class ArrayAccessResolveResult : ResolveResult
{
public readonly ResolveResult Array;
public readonly IList<ResolveResult> Indexes;
public ArrayAccessResolveResult(IType elementType, ResolveResult array, IList<ResolveResult> indexes) : base(elementType)
{
if (array == null)
throw new ArgumentNullException("array");
if (indexes == null)
throw new ArgumentNullException("indexes");
this.Array = array;
this.Indexes = indexes;
}
public override IEnumerable<ResolveResult> GetChildResults()
{
return new [] { Array }.Concat(Indexes);
}
}
}

60
ICSharpCode.Decompiler/Semantics/ArrayCreateResolveResult.cs

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Resolve result representing an array creation.
/// </summary>
public class ArrayCreateResolveResult : ResolveResult
{
/// <summary>
/// Gets the size arguments.
/// </summary>
public readonly IList<ResolveResult> SizeArguments;
/// <summary>
/// Gets the initializer elements.
/// This field may be null if no initializer was specified.
/// </summary>
public readonly IList<ResolveResult> InitializerElements;
public ArrayCreateResolveResult(IType arrayType, IList<ResolveResult> sizeArguments, IList<ResolveResult> initializerElements)
: base(arrayType)
{
if (sizeArguments == null)
throw new ArgumentNullException("sizeArguments");
this.SizeArguments = sizeArguments;
this.InitializerElements = initializerElements;
}
public override IEnumerable<ResolveResult> GetChildResults()
{
if (InitializerElements != null)
return SizeArguments.Concat(InitializerElements);
else
return SizeArguments;
}
}
}

66
ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents the resolve result of an 'ref x' or 'out x' expression.
/// </summary>
public class ByReferenceResolveResult : ResolveResult
{
public bool IsOut { get; private set; }
public bool IsRef { get { return !IsOut;} }
public readonly ResolveResult ElementResult;
public ByReferenceResolveResult(ResolveResult elementResult, bool isOut)
: this(elementResult.Type, isOut)
{
this.ElementResult = elementResult;
}
public ByReferenceResolveResult(IType elementType, bool isOut)
: base(new ByReferenceType(elementType))
{
this.IsOut = isOut;
}
public IType ElementType {
get { return ((ByReferenceType)this.Type).ElementType; }
}
public override IEnumerable<ResolveResult> GetChildResults()
{
if (ElementResult != null)
return new[] { ElementResult };
else
return Enumerable.Empty<ResolveResult>();
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "[{0} {1} {2}]", GetType().Name, IsOut ? "out" : "ref", ElementType);
}
}
}

55
ICSharpCode.Decompiler/Semantics/ConstantResolveResult.cs

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Globalization;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// ResolveResult representing a compile-time constant.
/// Note: this class is mainly used for literals; there may be other ResolveResult classes
/// which are compile-time constants as well.
/// For example, a reference to a <c>const</c> field results in a <see cref="MemberResolveResult"/>.
///
/// Check <see cref="ResolveResult.IsCompileTimeConstant"/> to determine is a resolve result is a constant.
/// </summary>
public class ConstantResolveResult : ResolveResult
{
object constantValue;
public ConstantResolveResult(IType type, object constantValue) : base(type)
{
this.constantValue = constantValue;
}
public override bool IsCompileTimeConstant {
get { return true; }
}
public override object ConstantValue {
get { return constantValue; }
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "[{0} {1} = {2}]", GetType().Name, this.Type, constantValue);
}
}
}

568
ICSharpCode.Decompiler/Semantics/Conversion.cs

@ -0,0 +1,568 @@ @@ -0,0 +1,568 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Holds information about a conversion between two types.
/// </summary>
public abstract class Conversion : IEquatable<Conversion>
{
#region Conversion factory methods
/// <summary>
/// Not a valid conversion.
/// </summary>
public static readonly Conversion None = new InvalidConversion();
/// <summary>
/// Identity conversion.
/// </summary>
public static readonly Conversion IdentityConversion = new BuiltinConversion(true, 0);
public static readonly Conversion ImplicitNumericConversion = new NumericOrEnumerationConversion(true, false);
public static readonly Conversion ExplicitNumericConversion = new NumericOrEnumerationConversion(false, false);
public static readonly Conversion ImplicitLiftedNumericConversion = new NumericOrEnumerationConversion(true, true);
public static readonly Conversion ExplicitLiftedNumericConversion = new NumericOrEnumerationConversion(false, true);
public static Conversion EnumerationConversion(bool isImplicit, bool isLifted)
{
return new NumericOrEnumerationConversion(isImplicit, isLifted, true);
}
public static readonly Conversion NullLiteralConversion = new BuiltinConversion(true, 1);
/// <summary>
/// The numeric conversion of a constant expression.
/// </summary>
public static readonly Conversion ImplicitConstantExpressionConversion = new BuiltinConversion(true, 2);
public static readonly Conversion ImplicitReferenceConversion = new BuiltinConversion(true, 3);
public static readonly Conversion ExplicitReferenceConversion = new BuiltinConversion(false, 3);
public static readonly Conversion ImplicitDynamicConversion = new BuiltinConversion(true, 4);
public static readonly Conversion ExplicitDynamicConversion = new BuiltinConversion(false, 4);
public static readonly Conversion ImplicitNullableConversion = new BuiltinConversion(true, 5);
public static readonly Conversion ExplicitNullableConversion = new BuiltinConversion(false, 5);
public static readonly Conversion ImplicitPointerConversion = new BuiltinConversion(true, 6);
public static readonly Conversion ExplicitPointerConversion = new BuiltinConversion(false, 6);
public static readonly Conversion BoxingConversion = new BuiltinConversion(true, 7);
public static readonly Conversion UnboxingConversion = new BuiltinConversion(false, 8);
/// <summary>
/// C# 'as' cast.
/// </summary>
public static readonly Conversion TryCast = new BuiltinConversion(false, 9);
[Obsolete("Use UserDefinedConversion() instead")]
public static Conversion UserDefinedImplicitConversion(IMethod operatorMethod, Conversion conversionBeforeUserDefinedOperator, Conversion conversionAfterUserDefinedOperator, bool isLifted)
{
if (operatorMethod == null)
throw new ArgumentNullException("operatorMethod");
return new UserDefinedConv(true, operatorMethod, conversionBeforeUserDefinedOperator, conversionAfterUserDefinedOperator, isLifted, false);
}
[Obsolete("Use UserDefinedConversion() instead")]
public static Conversion UserDefinedExplicitConversion(IMethod operatorMethod, Conversion conversionBeforeUserDefinedOperator, Conversion conversionAfterUserDefinedOperator, bool isLifted)
{
if (operatorMethod == null)
throw new ArgumentNullException("operatorMethod");
return new UserDefinedConv(false, operatorMethod, conversionBeforeUserDefinedOperator, conversionAfterUserDefinedOperator, isLifted, false);
}
public static Conversion UserDefinedConversion(IMethod operatorMethod, bool isImplicit, Conversion conversionBeforeUserDefinedOperator, Conversion conversionAfterUserDefinedOperator, bool isLifted = false, bool isAmbiguous = false)
{
if (operatorMethod == null)
throw new ArgumentNullException("operatorMethod");
return new UserDefinedConv(isImplicit, operatorMethod, conversionBeforeUserDefinedOperator, conversionAfterUserDefinedOperator, isLifted, isAmbiguous);
}
public static Conversion MethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument)
{
if (chosenMethod == null)
throw new ArgumentNullException("chosenMethod");
return new MethodGroupConv(chosenMethod, isVirtualMethodLookup, delegateCapturesFirstArgument, isValid: true);
}
public static Conversion InvalidMethodGroupConversion(IMethod chosenMethod, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument)
{
if (chosenMethod == null)
throw new ArgumentNullException("chosenMethod");
return new MethodGroupConv(chosenMethod, isVirtualMethodLookup, delegateCapturesFirstArgument, isValid: false);
}
#endregion
#region Inner classes
sealed class InvalidConversion : Conversion
{
public override bool IsValid {
get { return false; }
}
public override string ToString()
{
return "None";
}
}
sealed class NumericOrEnumerationConversion : Conversion
{
readonly bool isImplicit;
readonly bool isLifted;
readonly bool isEnumeration;
public NumericOrEnumerationConversion(bool isImplicit, bool isLifted, bool isEnumeration = false)
{
this.isImplicit = isImplicit;
this.isLifted = isLifted;
this.isEnumeration = isEnumeration;
}
public override bool IsImplicit {
get { return isImplicit; }
}
public override bool IsExplicit {
get { return !isImplicit; }
}
public override bool IsNumericConversion {
get { return !isEnumeration; }
}
public override bool IsEnumerationConversion {
get { return isEnumeration; }
}
public override bool IsLifted {
get { return isLifted; }
}
public override string ToString()
{
return (isImplicit ? "implicit" : "explicit")
+ (isLifted ? " lifted" : "")
+ (isEnumeration ? " enumeration" : " numeric")
+ " conversion";
}
public override bool Equals(Conversion other)
{
NumericOrEnumerationConversion o = other as NumericOrEnumerationConversion;
return o != null && isImplicit == o.isImplicit && isLifted == o.isLifted && isEnumeration == o.isEnumeration;
}
public override int GetHashCode()
{
return (isImplicit ? 1 : 0) + (isLifted ? 2 : 0) + (isEnumeration ? 4 : 0);
}
}
sealed class BuiltinConversion : Conversion
{
readonly bool isImplicit;
readonly byte type;
public BuiltinConversion(bool isImplicit, byte type)
{
this.isImplicit = isImplicit;
this.type = type;
}
public override bool IsImplicit {
get { return isImplicit; }
}
public override bool IsExplicit {
get { return !isImplicit; }
}
public override bool IsIdentityConversion {
get { return type == 0; }
}
public override bool IsNullLiteralConversion {
get { return type == 1; }
}
public override bool IsConstantExpressionConversion {
get { return type == 2; }
}
public override bool IsReferenceConversion {
get { return type == 3; }
}
public override bool IsDynamicConversion {
get { return type == 4; }
}
public override bool IsNullableConversion {
get { return type == 5; }
}
public override bool IsPointerConversion {
get { return type == 6; }
}
public override bool IsBoxingConversion {
get { return type == 7; }
}
public override bool IsUnboxingConversion {
get { return type == 8; }
}
public override bool IsTryCast {
get { return type == 9; }
}
public override string ToString()
{
string name = null;
switch (type) {
case 0:
return "identity conversion";
case 1:
return "null-literal conversion";
case 2:
name = "constant-expression";
break;
case 3:
name = "reference";
break;
case 4:
name = "dynamic";
break;
case 5:
name = "nullable";
break;
case 6:
name = "pointer";
break;
case 7:
return "boxing conversion";
case 8:
return "unboxing conversion";
case 9:
return "try cast";
}
return (isImplicit ? "implicit " : "explicit ") + name + " conversion";
}
}
sealed class UserDefinedConv : Conversion
{
readonly IMethod method;
readonly bool isLifted;
readonly Conversion conversionBeforeUserDefinedOperator;
readonly Conversion conversionAfterUserDefinedOperator;
readonly bool isImplicit;
readonly bool isValid;
public UserDefinedConv(bool isImplicit, IMethod method, Conversion conversionBeforeUserDefinedOperator, Conversion conversionAfterUserDefinedOperator, bool isLifted, bool isAmbiguous)
{
this.method = method;
this.isLifted = isLifted;
this.conversionBeforeUserDefinedOperator = conversionBeforeUserDefinedOperator;
this.conversionAfterUserDefinedOperator = conversionAfterUserDefinedOperator;
this.isImplicit = isImplicit;
this.isValid = !isAmbiguous;
}
public override bool IsValid {
get { return isValid; }
}
public override bool IsImplicit {
get { return isImplicit; }
}
public override bool IsExplicit {
get { return !isImplicit; }
}
public override bool IsLifted {
get { return isLifted; }
}
public override bool IsUserDefined {
get { return true; }
}
public override Conversion ConversionBeforeUserDefinedOperator {
get { return conversionBeforeUserDefinedOperator; }
}
public override Conversion ConversionAfterUserDefinedOperator {
get { return conversionAfterUserDefinedOperator; }
}
public override IMethod Method {
get { return method; }
}
public override bool Equals(Conversion other)
{
UserDefinedConv o = other as UserDefinedConv;
return o != null && isLifted == o.isLifted && isImplicit == o.isImplicit && isValid == o.isValid && method.Equals(o.method);
}
public override int GetHashCode()
{
return unchecked(method.GetHashCode() + (isLifted ? 31 : 27) + (isImplicit ? 71 : 61) + (isValid ? 107 : 109));
}
public override string ToString()
{
return (isImplicit ? "implicit" : "explicit")
+ (isLifted ? " lifted" : "")
+ (isValid ? "" : " ambiguous")
+ "user-defined conversion (" + method + ")";
}
}
sealed class MethodGroupConv : Conversion
{
readonly IMethod method;
readonly bool isVirtualMethodLookup;
readonly bool delegateCapturesFirstArgument;
readonly bool isValid;
public MethodGroupConv(IMethod method, bool isVirtualMethodLookup, bool delegateCapturesFirstArgument, bool isValid)
{
this.method = method;
this.isVirtualMethodLookup = isVirtualMethodLookup;
this.delegateCapturesFirstArgument = delegateCapturesFirstArgument;
this.isValid = isValid;
}
public override bool IsValid {
get { return isValid; }
}
public override bool IsImplicit {
get { return true; }
}
public override bool IsMethodGroupConversion {
get { return true; }
}
public override bool IsVirtualMethodLookup {
get { return isVirtualMethodLookup; }
}
public override bool DelegateCapturesFirstArgument {
get { return delegateCapturesFirstArgument; }
}
public override IMethod Method {
get { return method; }
}
public override bool Equals(Conversion other)
{
MethodGroupConv o = other as MethodGroupConv;
return o != null && method.Equals(o.method);
}
public override int GetHashCode()
{
return method.GetHashCode();
}
}
#endregion
/// <summary>
/// Gets whether the conversion is valid.
/// </summary>
public virtual bool IsValid {
get { return true; }
}
public virtual bool IsImplicit {
get { return false; }
}
public virtual bool IsExplicit {
get { return false; }
}
/// <summary>
/// Gets whether the conversion is an '<c>as</c>' cast.
/// </summary>
public virtual bool IsTryCast {
get { return false; }
}
public virtual bool IsIdentityConversion {
get { return false; }
}
public virtual bool IsNullLiteralConversion {
get { return false; }
}
public virtual bool IsConstantExpressionConversion {
get { return false; }
}
public virtual bool IsNumericConversion {
get { return false; }
}
/// <summary>
/// Gets whether this conversion is a lifted version of another conversion.
/// </summary>
public virtual bool IsLifted {
get { return false; }
}
/// <summary>
/// Gets whether the conversion is dynamic.
/// </summary>
public virtual bool IsDynamicConversion {
get { return false; }
}
/// <summary>
/// Gets whether the conversion is a reference conversion.
/// </summary>
public virtual bool IsReferenceConversion {
get { return false; }
}
/// <summary>
/// Gets whether the conversion is an enumeration conversion.
/// </summary>
public virtual bool IsEnumerationConversion {
get { return false; }
}
/// <summary>
/// Gets whether the conversion is a nullable conversion
/// (conversion between a nullable type and the regular type).
/// </summary>
public virtual bool IsNullableConversion {
get { return false; }
}
/// <summary>
/// Gets whether this conversion is user-defined (op_Implicit or op_Explicit).
/// </summary>
public virtual bool IsUserDefined {
get { return false; }
}
/// <summary>
/// The conversion that is applied to the input before the user-defined conversion operator is invoked.
/// </summary>
public virtual Conversion ConversionBeforeUserDefinedOperator {
get { return null; }
}
/// <summary>
/// The conversion that is applied to the result of the user-defined conversion operator.
/// </summary>
public virtual Conversion ConversionAfterUserDefinedOperator {
get { return null; }
}
/// <summary>
/// Gets whether this conversion is a boxing conversion.
/// </summary>
public virtual bool IsBoxingConversion {
get { return false; }
}
/// <summary>
/// Gets whether this conversion is an unboxing conversion.
/// </summary>
public virtual bool IsUnboxingConversion {
get { return false; }
}
/// <summary>
/// Gets whether this conversion is a pointer conversion.
/// </summary>
public virtual bool IsPointerConversion {
get { return false; }
}
/// <summary>
/// Gets whether this conversion is a method group conversion.
/// </summary>
public virtual bool IsMethodGroupConversion {
get { return false; }
}
/// <summary>
/// For method-group conversions, gets whether to perform a virtual method lookup at runtime.
/// </summary>
public virtual bool IsVirtualMethodLookup {
get { return false; }
}
/// <summary>
/// For method-group conversions, gets whether the conversion captures the first argument.
///
/// For instance methods, this property always returns true for C# method-group conversions.
/// For static methods, this property returns true for method-group conversions of an extension method performed on an instance (eg. <c>Func&lt;int&gt; f = myEnumerable.Single</c>).
/// </summary>
public virtual bool DelegateCapturesFirstArgument {
get { return false; }
}
/// <summary>
/// Gets whether this conversion is an anonymous function conversion.
/// </summary>
public virtual bool IsAnonymousFunctionConversion {
get { return false; }
}
/// <summary>
/// Gets the method associated with this conversion.
/// For user-defined conversions, this is the method being called.
/// For method-group conversions, this is the method that was chosen from the group.
/// </summary>
public virtual IMethod Method {
get { return null; }
}
public override sealed bool Equals(object obj)
{
return Equals(obj as Conversion);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public virtual bool Equals(Conversion other)
{
return this == other;
}
}
}

68
ICSharpCode.Decompiler/Semantics/ConversionResolveResult.cs

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents an implicit or explicit type conversion.
/// <c>conversionResolveResult.Input.Type</c> is the source type;
/// <c>conversionResolveResult.Type</c> is the target type.
/// The <see cref="Conversion"/> property provides details about the kind of conversion.
/// </summary>
public class ConversionResolveResult : ResolveResult
{
public readonly ResolveResult Input;
public readonly Conversion Conversion;
/// <summary>
/// For numeric conversions, specifies whether overflow checking is enabled.
/// </summary>
public readonly bool CheckForOverflow;
public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion)
: base(targetType)
{
if (input == null)
throw new ArgumentNullException("input");
if (conversion == null)
throw new ArgumentNullException("conversion");
this.Input = input;
this.Conversion = conversion;
}
public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion, bool checkForOverflow)
: this(targetType, input, conversion)
{
this.CheckForOverflow = checkForOverflow;
}
public override bool IsError {
get { return !Conversion.IsValid; }
}
public override IEnumerable<ResolveResult> GetChildResults()
{
return new [] { Input };
}
}
}

56
ICSharpCode.Decompiler/Semantics/ErrorResolveResult.cs

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents a resolve error.
///
/// Note: some errors are represented by other classes; for example a <see cref="ConversionResolveResult"/> may
/// be erroneous if the conversion is invalid.
/// </summary>
/// <seealso cref="ResolveResult.IsError"/>.
public class ErrorResolveResult : ResolveResult
{
/// <summary>
/// Gets an ErrorResolveResult instance with <c>Type</c> = <c>SpecialType.UnknownType</c>.
/// </summary>
public static readonly ErrorResolveResult UnknownError = new ErrorResolveResult(SpecialType.UnknownType);
public ErrorResolveResult(IType type) : base(type)
{
}
public ErrorResolveResult(IType type, string message, TextLocation location) : base(type)
{
this.Message = message;
this.Location = location;
}
public override bool IsError {
get { return true; }
}
public string Message { get; private set; }
public TextLocation Location { get; private set; }
}
}

90
ICSharpCode.Decompiler/Semantics/ForEachResolveResult.cs

@ -0,0 +1,90 @@ @@ -0,0 +1,90 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Resolve result representing a 'foreach' loop.
/// </summary>
public class ForEachResolveResult : ResolveResult
{
/// <summary>
/// Gets the semantic tree for the call to GetEnumerator.
/// </summary>
public readonly ResolveResult GetEnumeratorCall;
/// <summary>
/// Gets the collection type.
/// </summary>
public readonly IType CollectionType;
/// <summary>
/// Gets the enumerator type.
/// </summary>
public readonly IType EnumeratorType;
/// <summary>
/// Gets the element type.
/// This is the type that would be inferred for an implicitly-typed element variable.
/// For explicitly-typed element variables, this type may differ from <c>ElementVariable.Type</c>.
/// </summary>
public readonly IType ElementType;
/// <summary>
/// Gets the element variable.
/// </summary>
public readonly IVariable ElementVariable;
/// <summary>
/// Gets the Current property on the IEnumerator.
/// Returns null if the property is not found.
/// </summary>
public readonly IProperty CurrentProperty;
/// <summary>
/// Gets the MoveNext() method on the IEnumerator.
/// Returns null if the method is not found.
/// </summary>
public readonly IMethod MoveNextMethod;
public ForEachResolveResult(ResolveResult getEnumeratorCall, IType collectionType, IType enumeratorType, IType elementType, IVariable elementVariable, IProperty currentProperty, IMethod moveNextMethod, IType voidType)
: base(voidType)
{
if (getEnumeratorCall == null)
throw new ArgumentNullException("getEnumeratorCall");
if (collectionType == null)
throw new ArgumentNullException("collectionType");
if (enumeratorType == null)
throw new ArgumentNullException("enumeratorType");
if (elementType == null)
throw new ArgumentNullException("elementType");
if (elementVariable == null)
throw new ArgumentNullException("elementVariable");
this.GetEnumeratorCall = getEnumeratorCall;
this.CollectionType = collectionType;
this.EnumeratorType = enumeratorType;
this.ElementType = elementType;
this.ElementVariable = elementVariable;
this.CurrentProperty = currentProperty;
this.MoveNextMethod = moveNextMethod;
}
}
}

34
ICSharpCode.Decompiler/Semantics/InitializedObjectResolveResult.cs

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Refers to the object that is currently being initialized.
/// Used within <see cref="InvocationResolveResult.InitializerStatements"/>.
/// </summary>
public class InitializedObjectResolveResult : ResolveResult
{
public InitializedObjectResolveResult(IType type) : base(type)
{
}
}
}

75
ICSharpCode.Decompiler/Semantics/InvocationResolveResult.cs

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents the result of a method, constructor or indexer invocation.
/// </summary>
public class InvocationResolveResult : MemberResolveResult
{
/// <summary>
/// Gets the arguments that are being passed to the method, in the order the arguments are being evaluated.
/// </summary>
public readonly IList<ResolveResult> Arguments;
/// <summary>
/// Gets the list of initializer statements that are appplied to the result of this invocation.
/// This is used to represent object and collection initializers.
/// With the initializer statements, the <see cref="InitializedObjectResolveResult"/> is used
/// to refer to the result of this invocation.
/// </summary>
public readonly IList<ResolveResult> InitializerStatements;
public InvocationResolveResult(ResolveResult targetResult, IParameterizedMember member,
IList<ResolveResult> arguments = null,
IList<ResolveResult> initializerStatements = null,
IType returnTypeOverride = null)
: base(targetResult, member, returnTypeOverride)
{
this.Arguments = arguments ?? EmptyList<ResolveResult>.Instance;
this.InitializerStatements = initializerStatements ?? EmptyList<ResolveResult>.Instance;
}
public new IParameterizedMember Member {
get { return (IParameterizedMember)base.Member; }
}
/// <summary>
/// Gets the arguments in the order they are being passed to the method.
/// For parameter arrays (params), this will return an ArrayCreateResolveResult.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
Justification = "Derived methods may be expensive and create new lists")]
public virtual IList<ResolveResult> GetArgumentsForCall()
{
return Arguments;
}
public override IEnumerable<ResolveResult> GetChildResults()
{
return base.GetChildResults().Concat(this.Arguments).Concat(this.InitializerStatements);
}
}
}

77
ICSharpCode.Decompiler/Semantics/LocalResolveResult.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Globalization;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents a local variable or parameter.
/// </summary>
public class LocalResolveResult : ResolveResult
{
readonly IVariable variable;
public LocalResolveResult(IVariable variable)
: base(UnpackTypeIfByRefParameter(variable))
{
this.variable = variable;
}
static IType UnpackTypeIfByRefParameter(IVariable variable)
{
if (variable == null)
throw new ArgumentNullException("variable");
IType type = variable.Type;
if (type.Kind == TypeKind.ByReference) {
IParameter p = variable as IParameter;
if (p != null && (p.IsRef || p.IsOut))
return ((ByReferenceType)type).ElementType;
}
return type;
}
public IVariable Variable {
get { return variable; }
}
public bool IsParameter {
get { return variable is IParameter; }
}
public override bool IsCompileTimeConstant {
get { return variable.IsConst; }
}
public override object ConstantValue {
get { return IsParameter ? null : variable.ConstantValue; }
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "[LocalResolveResult {0}]", variable);
}
public override DomRegion GetDefinitionRegion()
{
return variable.Region;
}
}
}

148
ICSharpCode.Decompiler/Semantics/MemberResolveResult.cs

@ -0,0 +1,148 @@ @@ -0,0 +1,148 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents the result of a member invocation.
/// Used for field/property/event access.
/// Also, <see cref="InvocationResolveResult"/> derives from MemberResolveResult.
/// </summary>
public class MemberResolveResult : ResolveResult
{
readonly IMember member;
readonly bool isConstant;
readonly object constantValue;
readonly ResolveResult targetResult;
readonly bool isVirtualCall;
public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnTypeOverride = null)
: base(returnTypeOverride ?? ComputeType(member))
{
this.targetResult = targetResult;
this.member = member;
var thisRR = targetResult as ThisResolveResult;
this.isVirtualCall = member.IsOverridable && !(thisRR != null && thisRR.CausesNonVirtualInvocation);
IField field = member as IField;
if (field != null) {
isConstant = field.IsConst;
if (isConstant)
constantValue = field.ConstantValue;
}
}
public MemberResolveResult(ResolveResult targetResult, IMember member, bool isVirtualCall, IType returnTypeOverride = null)
: base(returnTypeOverride ?? ComputeType(member))
{
this.targetResult = targetResult;
this.member = member;
this.isVirtualCall = isVirtualCall;
IField field = member as IField;
if (field != null) {
isConstant = field.IsConst;
if (isConstant)
constantValue = field.ConstantValue;
}
}
static IType ComputeType(IMember member)
{
switch (member.SymbolKind) {
case SymbolKind.Constructor:
return member.DeclaringType ?? SpecialType.UnknownType;
case SymbolKind.Field:
if (((IField)member).IsFixed)
return new PointerType(member.ReturnType);
break;
}
return member.ReturnType;
}
public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType, bool isConstant, object constantValue)
: base(returnType)
{
this.targetResult = targetResult;
this.member = member;
this.isConstant = isConstant;
this.constantValue = constantValue;
}
public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType, bool isConstant, object constantValue, bool isVirtualCall)
: base(returnType)
{
this.targetResult = targetResult;
this.member = member;
this.isConstant = isConstant;
this.constantValue = constantValue;
this.isVirtualCall = isVirtualCall;
}
public ResolveResult TargetResult {
get { return targetResult; }
}
/// <summary>
/// Gets the member.
/// This property never returns null.
/// </summary>
public IMember Member {
get { return member; }
}
/// <summary>
/// Gets whether this MemberResolveResult is a virtual call.
/// </summary>
public bool IsVirtualCall {
get { return isVirtualCall; }
}
public override bool IsCompileTimeConstant {
get { return isConstant; }
}
public override object ConstantValue {
get { return constantValue; }
}
public override IEnumerable<ResolveResult> GetChildResults()
{
if (targetResult != null)
return new[] { targetResult };
else
return Enumerable.Empty<ResolveResult>();
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "[{0} {1}]", GetType().Name, member);
}
public override DomRegion GetDefinitionRegion()
{
return member.Region;
}
}
}

81
ICSharpCode.Decompiler/Semantics/NamedArgumentResolveResult.cs

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents a named argument.
/// </summary>
public class NamedArgumentResolveResult : ResolveResult
{
/// <summary>
/// Gets the member to which the parameter belongs.
/// This field can be null.
/// </summary>
public readonly IParameterizedMember Member;
/// <summary>
/// Gets the parameter.
/// This field can be null.
/// </summary>
public readonly IParameter Parameter;
/// <summary>
/// Gets the parameter name.
/// </summary>
public readonly string ParameterName;
/// <summary>
/// Gets the argument passed to the parameter.
/// </summary>
public readonly ResolveResult Argument;
public NamedArgumentResolveResult(IParameter parameter, ResolveResult argument, IParameterizedMember member = null)
: base(argument.Type)
{
if (parameter == null)
throw new ArgumentNullException("parameter");
if (argument == null)
throw new ArgumentNullException("argument");
this.Member = member;
this.Parameter = parameter;
this.ParameterName = parameter.Name;
this.Argument = argument;
}
public NamedArgumentResolveResult(string parameterName, ResolveResult argument)
: base(argument.Type)
{
if (parameterName == null)
throw new ArgumentNullException("parameterName");
if (argument == null)
throw new ArgumentNullException("argument");
this.ParameterName = parameterName;
this.Argument = argument;
}
public override IEnumerable<ResolveResult> GetChildResults()
{
return new [] { Argument };
}
}
}

50
ICSharpCode.Decompiler/Semantics/NamespaceResolveResult.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Globalization;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents that an expression resolved to a namespace.
/// </summary>
public class NamespaceResolveResult : ResolveResult
{
readonly INamespace ns;
public NamespaceResolveResult(INamespace ns) : base(SpecialType.UnknownType)
{
this.ns = ns;
}
public INamespace Namespace {
get { return ns; }
}
public string NamespaceName {
get { return ns.FullName; }
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "[{0} {1}]", GetType().Name, ns);
}
}
}

90
ICSharpCode.Decompiler/Semantics/OperatorResolveResult.cs

@ -0,0 +1,90 @@ @@ -0,0 +1,90 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents a unary/binary/ternary operator invocation.
/// </summary>
public class OperatorResolveResult : ResolveResult
{
readonly ExpressionType operatorType;
readonly IMethod userDefinedOperatorMethod;
readonly IList<ResolveResult> operands;
readonly bool isLiftedOperator;
public OperatorResolveResult(IType resultType, ExpressionType operatorType, params ResolveResult[] operands)
: base(resultType)
{
if (operands == null)
throw new ArgumentNullException("operands");
this.operatorType = operatorType;
this.operands = operands;
}
public OperatorResolveResult(IType resultType, ExpressionType operatorType, IMethod userDefinedOperatorMethod, bool isLiftedOperator, IList<ResolveResult> operands)
: base(resultType)
{
if (operands == null)
throw new ArgumentNullException("operands");
this.operatorType = operatorType;
this.userDefinedOperatorMethod = userDefinedOperatorMethod;
this.isLiftedOperator = isLiftedOperator;
this.operands = operands;
}
/// <summary>
/// Gets the operator type.
/// </summary>
public ExpressionType OperatorType {
get { return operatorType; }
}
/// <summary>
/// Gets the operands.
/// </summary>
public IList<ResolveResult> Operands {
get { return operands; }
}
/// <summary>
/// Gets the user defined operator method.
/// Returns null if this is a predefined operator.
/// </summary>
public IMethod UserDefinedOperatorMethod {
get { return userDefinedOperatorMethod; }
}
/// <summary>
/// Gets whether this is a lifted operator.
/// </summary>
public bool IsLiftedOperator {
get { return isLiftedOperator; }
}
public override IEnumerable<ResolveResult> GetChildResults()
{
return operands;
}
}
}

78
ICSharpCode.Decompiler/Semantics/ResolveResult.cs

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents the result of resolving an expression.
/// </summary>
public class ResolveResult
{
readonly IType type;
public ResolveResult(IType type)
{
if (type == null)
throw new ArgumentNullException("type");
this.type = type;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods",
Justification = "Unrelated to object.GetType()")]
public IType Type {
get { return type; }
}
public virtual bool IsCompileTimeConstant {
get { return false; }
}
public virtual object ConstantValue {
get { return null; }
}
public virtual bool IsError {
get { return false; }
}
public override string ToString()
{
return "[" + GetType().Name + " " + type + "]";
}
public virtual IEnumerable<ResolveResult> GetChildResults()
{
return Enumerable.Empty<ResolveResult>();
}
public virtual DomRegion GetDefinitionRegion()
{
return DomRegion.Empty;
}
public virtual ResolveResult ShallowClone()
{
return (ResolveResult)MemberwiseClone();
}
}
}

66
ICSharpCode.Decompiler/Semantics/SizeOfResolveResult.cs

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents the 'sizeof'.
/// </summary>
public class SizeOfResolveResult : ResolveResult
{
readonly IType referencedType;
readonly int? constantValue;
public SizeOfResolveResult(IType int32, IType referencedType, int? constantValue)
: base(int32)
{
if (referencedType == null)
throw new ArgumentNullException("referencedType");
this.referencedType = referencedType;
this.constantValue = constantValue;
}
/// <summary>
/// The type referenced by the 'sizeof'.
/// </summary>
public IType ReferencedType {
get { return referencedType; }
}
public override bool IsCompileTimeConstant {
get {
return constantValue != null;
}
}
public override object ConstantValue {
get {
return constantValue;
}
}
public override bool IsError {
get {
return referencedType.IsReferenceType != false;
}
}
}
}

44
ICSharpCode.Decompiler/Semantics/ThisResolveResult.cs

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents the 'this' reference.
/// Also used for the 'base' reference.
/// </summary>
public class ThisResolveResult : ResolveResult
{
bool causesNonVirtualInvocation;
public ThisResolveResult(IType type, bool causesNonVirtualInvocation = false) : base(type)
{
this.causesNonVirtualInvocation = causesNonVirtualInvocation;
}
/// <summary>
/// Gets whether this resolve result causes member invocations to be non-virtual.
/// </summary>
public bool CausesNonVirtualInvocation {
get { return causesNonVirtualInvocation; }
}
}
}

47
ICSharpCode.Decompiler/Semantics/TypeIsResolveResult.cs

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Resolve result for a C# 'is' expression.
/// "Input is TargetType".
/// </summary>
public class TypeIsResolveResult : ResolveResult
{
public readonly ResolveResult Input;
/// <summary>
/// Type that is being compared with.
/// </summary>
public readonly IType TargetType;
public TypeIsResolveResult(ResolveResult input, IType targetType, IType booleanType)
: base(booleanType)
{
if (input == null)
throw new ArgumentNullException("input");
if (targetType == null)
throw new ArgumentNullException("targetType");
this.Input = input;
this.TargetType = targetType;
}
}
}

46
ICSharpCode.Decompiler/Semantics/TypeOfResolveResult.cs

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents the 'typeof'.
/// </summary>
public class TypeOfResolveResult : ResolveResult
{
readonly IType referencedType;
public TypeOfResolveResult(IType systemType, IType referencedType)
: base(systemType)
{
if (referencedType == null)
throw new ArgumentNullException("referencedType");
this.referencedType = referencedType;
}
/// <summary>
/// The type referenced by the 'typeof'.
/// </summary>
public IType ReferencedType {
get { return referencedType; }
}
}
}

47
ICSharpCode.Decompiler/Semantics/TypeResolveResult.cs

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// The resolved expression refers to a type name.
/// </summary>
public class TypeResolveResult : ResolveResult
{
public TypeResolveResult(IType type)
: base(type)
{
}
public override bool IsError {
get { return this.Type.Kind == TypeKind.Unknown; }
}
public override DomRegion GetDefinitionRegion()
{
ITypeDefinition def = this.Type.GetDefinition();
if (def != null)
return def.Region;
else
return DomRegion.Empty;
}
}
}

122
ICSharpCode.Decompiler/Semantics/UnknownMemberResolveResult.cs

@ -0,0 +1,122 @@ @@ -0,0 +1,122 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents an unknown member.
/// </summary>
public class UnknownMemberResolveResult : ResolveResult
{
readonly IType targetType;
readonly string memberName;
readonly ReadOnlyCollection<IType> typeArguments;
public UnknownMemberResolveResult(IType targetType, string memberName, IEnumerable<IType> typeArguments)
: base(SpecialType.UnknownType)
{
if (targetType == null)
throw new ArgumentNullException("targetType");
this.targetType = targetType;
this.memberName = memberName;
this.typeArguments = new ReadOnlyCollection<IType>(typeArguments.ToArray());
}
/// <summary>
/// The type on which the method is being called.
/// </summary>
public IType TargetType {
get { return targetType; }
}
public string MemberName {
get { return memberName; }
}
public ReadOnlyCollection<IType> TypeArguments {
get { return typeArguments; }
}
public override bool IsError {
get { return true; }
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "[{0} {1}.{2}]", GetType().Name, targetType, memberName);
}
}
/// <summary>
/// Represents an unknown method.
/// </summary>
public class UnknownMethodResolveResult : UnknownMemberResolveResult
{
readonly ReadOnlyCollection<IParameter> parameters;
public UnknownMethodResolveResult(IType targetType, string methodName, IEnumerable<IType> typeArguments, IEnumerable<IParameter> parameters)
: base(targetType, methodName, typeArguments)
{
this.parameters = new ReadOnlyCollection<IParameter>(parameters.ToArray());
}
public ReadOnlyCollection<IParameter> Parameters {
get { return parameters; }
}
}
/// <summary>
/// Represents an unknown identifier.
/// </summary>
public class UnknownIdentifierResolveResult : ResolveResult
{
readonly string identifier;
readonly int typeArgumentCount;
public UnknownIdentifierResolveResult(string identifier, int typeArgumentCount = 0)
: base(SpecialType.UnknownType)
{
this.identifier = identifier;
this.typeArgumentCount = typeArgumentCount;
}
public string Identifier {
get { return identifier; }
}
public int TypeArgumentCount {
get { return typeArgumentCount; }
}
public override bool IsError {
get { return true; }
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "[{0} {1}]", GetType().Name, identifier);
}
}
}

4
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -113,10 +113,6 @@ @@ -113,10 +113,6 @@
<Project>{d68133bd-1e63-496e-9ede-4fbdbf77b486}</Project>
<Name>Mono.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\..\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3b2a5653-ec97-4001-bb9b-d90f1af2c371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.Decompiler.csproj">
<Project>{984cc812-9470-4a13-aff9-cc44068d666c}</Project>
<Name>ICSharpCode.Decompiler</Name>

117
ICSharpCode.Decompiler/TypeSystem/Accessibility.cs

@ -0,0 +1,117 @@ @@ -0,0 +1,117 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Enum that describes the accessibility of an entity.
/// </summary>
public enum Accessibility : byte
{
// note: some code depends on the fact that these values are within the range 0-7
/// <summary>
/// The entity is completely inaccessible. This is used for C# explicit interface implementations.
/// </summary>
None,
/// <summary>
/// The entity is only accessible within the same class.
/// </summary>
Private,
/// <summary>
/// The entity is accessible everywhere.
/// </summary>
Public,
/// <summary>
/// The entity is only accessible within the same class and in derived classes.
/// </summary>
Protected,
/// <summary>
/// The entity is accessible within the same project content.
/// </summary>
Internal,
/// <summary>
/// The entity is accessible both everywhere in the project content, and in all derived classes.
/// </summary>
/// <remarks>This corresponds to C# 'protected internal'.</remarks>
ProtectedOrInternal,
/// <summary>
/// The entity is accessible in derived classes within the same project content.
/// </summary>
/// <remarks>C# does not support this accessibility.</remarks>
ProtectedAndInternal,
}
public interface IHasAccessibility
{
/// <summary>
/// Gets the accessibility of this entity.
/// </summary>
Accessibility Accessibility { get; }
/// <summary>
/// Gets a value indicating whether this instance is private.
/// </summary>
/// <value>
/// <c>true</c> if this instance is private; otherwise, <c>false</c>.
/// </value>
bool IsPrivate { get; }
/// <summary>
/// Gets a value indicating whether this instance is public.
/// </summary>
/// <value>
/// <c>true</c> if this instance is public; otherwise, <c>false</c>.
/// </value>
bool IsPublic { get; }
/// <summary>
/// Gets a value indicating whether this instance is protected.
/// </summary>
/// <value>
/// <c>true</c> if this instance is protected; otherwise, <c>false</c>.
/// </value>
bool IsProtected { get; }
/// <summary>
/// Gets a value indicating whether this instance is internal.
/// </summary>
/// <value>
/// <c>true</c> if this instance is internal; otherwise, <c>false</c>.
/// </value>
bool IsInternal { get; }
/// <summary>
/// Gets a value indicating whether this instance is protected or internal.
/// </summary>
/// <value>
/// <c>true</c> if this instance is protected or internal; otherwise, <c>false</c>.
/// </value>
bool IsProtectedOrInternal { get; }
/// <summary>
/// Gets a value indicating whether this instance is protected and internal.
/// </summary>
/// <value>
/// <c>true</c> if this instance is protected and internal; otherwise, <c>false</c>.
/// </value>
bool IsProtectedAndInternal { get; }
}
}

221
ICSharpCode.Decompiler/TypeSystem/AnonymousType.cs

@ -0,0 +1,221 @@ @@ -0,0 +1,221 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Anonymous type.
/// </summary>
public class AnonymousType : AbstractType
{
ICompilation compilation;
IUnresolvedProperty[] unresolvedProperties;
IList<IProperty> resolvedProperties;
public AnonymousType(ICompilation compilation, IList<IUnresolvedProperty> properties)
{
if (compilation == null)
throw new ArgumentNullException("compilation");
if (properties == null)
throw new ArgumentNullException("properties");
this.compilation = compilation;
this.unresolvedProperties = properties.ToArray();
var context = new SimpleTypeResolveContext(compilation.MainAssembly);
this.resolvedProperties = new ProjectedList<ITypeResolveContext, IUnresolvedProperty, IProperty>(context, unresolvedProperties, (c, p) => new AnonymousTypeProperty(p, c, this));
}
sealed class AnonymousTypeProperty : DefaultResolvedProperty
{
readonly AnonymousType declaringType;
public AnonymousTypeProperty(IUnresolvedProperty unresolved, ITypeResolveContext parentContext, AnonymousType declaringType)
: base(unresolved, parentContext)
{
this.declaringType = declaringType;
}
public override IType DeclaringType {
get { return declaringType; }
}
public override bool Equals(object obj)
{
AnonymousTypeProperty p = obj as AnonymousTypeProperty;
return p != null && this.Name == p.Name && declaringType.Equals(p.declaringType);
}
public override int GetHashCode()
{
return declaringType.GetHashCode() ^ unchecked(27 * this.Name.GetHashCode());
}
protected override IMethod CreateResolvedAccessor(IUnresolvedMethod unresolvedAccessor)
{
return new AnonymousTypeAccessor(unresolvedAccessor, context, this);
}
}
sealed class AnonymousTypeAccessor : DefaultResolvedMethod
{
readonly AnonymousTypeProperty owner;
public AnonymousTypeAccessor(IUnresolvedMethod unresolved, ITypeResolveContext parentContext, AnonymousTypeProperty owner)
: base(unresolved, parentContext, isExtensionMethod: false)
{
this.owner = owner;
}
public override IMember AccessorOwner {
get { return owner; }
}
public override IType DeclaringType {
get { return owner.DeclaringType; }
}
public override bool Equals(object obj)
{
AnonymousTypeAccessor p = obj as AnonymousTypeAccessor;
return p != null && this.Name == p.Name && owner.DeclaringType.Equals(p.owner.DeclaringType);
}
public override int GetHashCode()
{
return owner.DeclaringType.GetHashCode() ^ unchecked(27 * this.Name.GetHashCode());
}
}
public override ITypeReference ToTypeReference()
{
return new AnonymousTypeReference(unresolvedProperties);
}
public override string Name {
get { return "Anonymous Type"; }
}
public override TypeKind Kind {
get { return TypeKind.Anonymous; }
}
public override IEnumerable<IType> DirectBaseTypes {
get {
yield return compilation.FindType(KnownTypeCode.Object);
}
}
public override bool? IsReferenceType {
get { return true; }
}
public IList<IProperty> Properties {
get { return resolvedProperties; }
}
public override IEnumerable<IMethod> GetMethods(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
return EmptyList<IMethod>.Instance;
else
return compilation.FindType(KnownTypeCode.Object).GetMethods(filter, options);
}
public override IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
return EmptyList<IMethod>.Instance;
else
return compilation.FindType(KnownTypeCode.Object).GetMethods(typeArguments, filter, options);
}
public override IEnumerable<IProperty> GetProperties(Predicate<IUnresolvedProperty> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
for (int i = 0; i < unresolvedProperties.Length; i++) {
if (filter == null || filter(unresolvedProperties[i]))
yield return resolvedProperties[i];
}
}
public override IEnumerable<IMethod> GetAccessors(Predicate<IUnresolvedMethod> filter, GetMemberOptions options)
{
for (int i = 0; i < unresolvedProperties.Length; i++) {
if (unresolvedProperties[i].CanGet) {
if (filter == null || filter(unresolvedProperties[i].Getter))
yield return resolvedProperties[i].Getter;
}
if (unresolvedProperties[i].CanSet) {
if (filter == null || filter(unresolvedProperties[i].Setter))
yield return resolvedProperties[i].Setter;
}
}
}
public override int GetHashCode()
{
unchecked {
int hashCode = resolvedProperties.Count;
foreach (var p in resolvedProperties) {
hashCode *= 31;
hashCode += p.Name.GetHashCode() ^ p.ReturnType.GetHashCode();
}
return hashCode;
}
}
public override bool Equals(IType other)
{
AnonymousType o = other as AnonymousType;
if (o == null || resolvedProperties.Count != o.resolvedProperties.Count)
return false;
for (int i = 0; i < resolvedProperties.Count; i++) {
IProperty p1 = resolvedProperties[i];
IProperty p2 = o.resolvedProperties[i];
if (p1.Name != p2.Name || !p1.ReturnType.Equals(p2.ReturnType))
return false;
}
return true;
}
}
/// <summary>
/// Anonymous type reference.
/// </summary>
[Serializable]
public class AnonymousTypeReference : ITypeReference
{
readonly IUnresolvedProperty[] unresolvedProperties;
public AnonymousTypeReference(IUnresolvedProperty[] properties)
{
if (properties == null)
throw new ArgumentNullException("properties");
this.unresolvedProperties = properties;
}
public IType Resolve(ITypeResolveContext context)
{
return new AnonymousType(context.Compilation, unresolvedProperties);
}
}
}

200
ICSharpCode.Decompiler/TypeSystem/ArrayType.cs

@ -0,0 +1,200 @@ @@ -0,0 +1,200 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents an array type.
/// </summary>
public sealed class ArrayType : TypeWithElementType, ICompilationProvider
{
readonly int dimensions;
readonly ICompilation compilation;
public ArrayType(ICompilation compilation, IType elementType, int dimensions = 1) : base(elementType)
{
if (compilation == null)
throw new ArgumentNullException("compilation");
if (dimensions <= 0)
throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive");
this.compilation = compilation;
this.dimensions = dimensions;
ICompilationProvider p = elementType as ICompilationProvider;
if (p != null && p.Compilation != compilation)
throw new InvalidOperationException("Cannot create an array type using a different compilation from the element type.");
}
public override TypeKind Kind {
get { return TypeKind.Array; }
}
public ICompilation Compilation {
get { return compilation; }
}
public int Dimensions {
get { return dimensions; }
}
public override string NameSuffix {
get {
return "[" + new string(',', dimensions-1) + "]";
}
}
public override bool? IsReferenceType {
get { return true; }
}
public override int GetHashCode()
{
return unchecked(elementType.GetHashCode() * 71681 + dimensions);
}
public override bool Equals(IType other)
{
ArrayType a = other as ArrayType;
return a != null && elementType.Equals(a.elementType) && a.dimensions == dimensions;
}
public override ITypeReference ToTypeReference()
{
return new ArrayTypeReference(elementType.ToTypeReference(), dimensions);
}
public override IEnumerable<IType> DirectBaseTypes {
get {
List<IType> baseTypes = new List<IType>();
IType t = compilation.FindType(KnownTypeCode.Array);
if (t.Kind != TypeKind.Unknown)
baseTypes.Add(t);
if (dimensions == 1 && elementType.Kind != TypeKind.Pointer) {
// single-dimensional arrays implement IList<T>
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;
}
}
public override IEnumerable<IMethod> GetMethods(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
return EmptyList<IMethod>.Instance;
else
return compilation.FindType(KnownTypeCode.Array).GetMethods(filter, options);
}
public override IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
return EmptyList<IMethod>.Instance;
else
return compilation.FindType(KnownTypeCode.Array).GetMethods(typeArguments, filter, options);
}
public override IEnumerable<IMethod> GetAccessors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
return EmptyList<IMethod>.Instance;
else
return compilation.FindType(KnownTypeCode.Array).GetAccessors(filter, options);
}
public override IEnumerable<IProperty> GetProperties(Predicate<IUnresolvedProperty> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers)
return EmptyList<IProperty>.Instance;
else
return compilation.FindType(KnownTypeCode.Array).GetProperties(filter, options);
}
// NestedTypes, Events, Fields: System.Array doesn't have any; so we can use the AbstractType default implementation
// that simply returns an empty list
public override IType AcceptVisitor(TypeVisitor visitor)
{
return visitor.VisitArrayType(this);
}
public override IType VisitChildren(TypeVisitor visitor)
{
IType e = elementType.AcceptVisitor(visitor);
if (e == elementType)
return this;
else
return new ArrayType(compilation, e, dimensions);
}
}
[Serializable]
public sealed class ArrayTypeReference : ITypeReference, ISupportsInterning
{
readonly ITypeReference elementType;
readonly int dimensions;
public ArrayTypeReference(ITypeReference elementType, int dimensions = 1)
{
if (elementType == null)
throw new ArgumentNullException("elementType");
if (dimensions <= 0)
throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive");
this.elementType = elementType;
this.dimensions = dimensions;
}
public ITypeReference ElementType {
get { return elementType; }
}
public int Dimensions {
get { return dimensions; }
}
public IType Resolve(ITypeResolveContext context)
{
return new ArrayType(context.Compilation, elementType.Resolve(context), dimensions);
}
public override string ToString()
{
return elementType.ToString() + "[" + new string(',', dimensions - 1) + "]";
}
int ISupportsInterning.GetHashCodeForInterning()
{
return elementType.GetHashCode() ^ dimensions;
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ArrayTypeReference o = other as ArrayTypeReference;
return o != null && elementType == o.elementType && dimensions == o.dimensions;
}
}
}

94
ICSharpCode.Decompiler/TypeSystem/AssemblyLoader.cs

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
//
// AssemblyLoader.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Reflection;
using System.Threading;
using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.TypeSystem
{
public enum AssemblyLoaderBackend {
Auto,
Cecil,
IKVM
}
public abstract class AssemblyLoader
{
public static AssemblyLoader Create ()
{
return Create (AssemblyLoaderBackend.Auto);
}
public static AssemblyLoader Create (AssemblyLoaderBackend backend)
{
switch (backend) {
case AssemblyLoaderBackend.Auto:
case AssemblyLoaderBackend.Cecil:
return (AssemblyLoader)Assembly.Load ("ICSharpCode.NRefactory.Cecil").CreateInstance ("ICSharpCode.NRefactory.TypeSystem.CecilLoader");
case AssemblyLoaderBackend.IKVM:
return (AssemblyLoader)Assembly.Load ("ICSharpCode.NRefactory.IKVM").CreateInstance ("ICSharpCode.NRefactory.TypeSystem.IkvmLoader");
default:
throw new ArgumentOutOfRangeException ();
}
}
/// <summary>
/// Specifies whether to include internal members. The default is false.
/// </summary>
public bool IncludeInternalMembers { get; set; }
/// <summary>
/// Gets/Sets the cancellation token used by the assembly loader.
/// </summary>
public CancellationToken CancellationToken { get; set; }
/// <summary>
/// Gets/Sets the documentation provider that is used to retrieve the XML documentation for all members.
/// </summary>
public IDocumentationProvider DocumentationProvider { get; set; }
[CLSCompliant(false)]
protected InterningProvider interningProvider = new SimpleInterningProvider();
/// <summary>
/// Gets/Sets the interning provider.
/// </summary>
public InterningProvider InterningProvider {
get { return interningProvider; }
set {
if (value == null)
throw new ArgumentNullException();
interningProvider = value;
}
}
public abstract IUnresolvedAssembly LoadAssemblyFile(string fileName);
}
}

79
ICSharpCode.Decompiler/TypeSystem/AssemblyQualifiedTypeName.cs

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

112
ICSharpCode.Decompiler/TypeSystem/ByReferenceType.cs

@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.TypeSystem
{
public sealed class ByReferenceType : TypeWithElementType
{
public ByReferenceType(IType elementType) : base(elementType)
{
}
public override TypeKind Kind {
get { return TypeKind.ByReference; }
}
public override string NameSuffix {
get {
return "&";
}
}
public override bool? IsReferenceType {
get { return null; }
}
public override int GetHashCode()
{
return elementType.GetHashCode() ^ 91725813;
}
public override bool Equals(IType other)
{
ByReferenceType a = other as ByReferenceType;
return a != null && elementType.Equals(a.elementType);
}
public override IType AcceptVisitor(TypeVisitor visitor)
{
return visitor.VisitByReferenceType(this);
}
public override IType VisitChildren(TypeVisitor visitor)
{
IType e = elementType.AcceptVisitor(visitor);
if (e == elementType)
return this;
else
return new ByReferenceType(e);
}
public override ITypeReference ToTypeReference()
{
return new ByReferenceTypeReference(elementType.ToTypeReference());
}
}
[Serializable]
public sealed class ByReferenceTypeReference : ITypeReference, ISupportsInterning
{
readonly ITypeReference elementType;
public ByReferenceTypeReference(ITypeReference elementType)
{
if (elementType == null)
throw new ArgumentNullException("elementType");
this.elementType = elementType;
}
public ITypeReference ElementType {
get { return elementType; }
}
public IType Resolve(ITypeResolveContext context)
{
return new ByReferenceType(elementType.Resolve(context));
}
public override string ToString()
{
return elementType.ToString() + "&";
}
int ISupportsInterning.GetHashCodeForInterning()
{
return elementType.GetHashCode() ^ 91725814;
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ByReferenceTypeReference brt = other as ByReferenceTypeReference;
return brt != null && this.elementType == brt.elementType;
}
}
}

63
ICSharpCode.Decompiler/TypeSystem/ComHelper.cs

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Helper methods for COM.
/// </summary>
public static class ComHelper
{
static bool IsComAttribute(IAttribute attribute, string name)
{
return attribute.AttributeType.Name == name && attribute.AttributeType.Namespace == "System.Runtime.InteropServices";
}
/// <summary>
/// Gets whether the specified type is imported from COM.
/// </summary>
public static bool IsComImport(ITypeDefinition typeDefinition)
{
return typeDefinition != null
&& typeDefinition.Kind == TypeKind.Interface
&& typeDefinition.Attributes.Any(a => IsComAttribute(a, "ComImportAttribute"));
}
/// <summary>
/// Gets the CoClass of the specified COM interface.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Co",
Justification = "Consistent with CoClassAttribute")]
public static IType GetCoClass(ITypeDefinition typeDefinition)
{
if (typeDefinition == null)
return SpecialType.UnknownType;
var coClassAttribute = typeDefinition.Attributes.FirstOrDefault(a => IsComAttribute(a, "CoClassAttribute"));
if (coClassAttribute != null && coClassAttribute.PositionalArguments.Count == 1) {
var rr = coClassAttribute.PositionalArguments[0] as TypeOfResolveResult;
if (rr != null)
return rr.ReferencedType;
}
return SpecialType.UnknownType;
}
}
}

86
ICSharpCode.Decompiler/TypeSystem/DefaultSolutionSnapshot.cs

@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Default implementation of ISolutionSnapshot.
/// </summary>
public class DefaultSolutionSnapshot : ISolutionSnapshot
{
readonly Dictionary<string, IProjectContent> projectDictionary = new Dictionary<string, IProjectContent>(Platform.FileNameComparer);
ConcurrentDictionary<IProjectContent, ICompilation> dictionary = new ConcurrentDictionary<IProjectContent, ICompilation>();
/// <summary>
/// Creates a new DefaultSolutionSnapshot with the specified projects.
/// </summary>
public DefaultSolutionSnapshot(IEnumerable<IProjectContent> projects)
{
foreach (var project in projects) {
if (project.ProjectFileName != null)
projectDictionary.Add(project.ProjectFileName, project);
}
}
/// <summary>
/// Creates a new DefaultSolutionSnapshot that does not support <see cref="ProjectReference"/>s.
/// </summary>
public DefaultSolutionSnapshot()
{
}
public IProjectContent GetProjectContent(string projectFileName)
{
IProjectContent pc;
lock (projectDictionary) {
if (projectDictionary.TryGetValue(projectFileName, out pc))
return pc;
else
return null;
}
}
public ICompilation GetCompilation(IProjectContent project)
{
if (project == null)
throw new ArgumentNullException("project");
return dictionary.GetOrAdd(project, p => p.CreateCompilation(this));
}
public void AddCompilation(IProjectContent project, ICompilation compilation)
{
if (project == null)
throw new ArgumentNullException("project");
if (compilation == null)
throw new ArgumentNullException("compilation");
if (!dictionary.TryAdd(project, compilation))
throw new InvalidOperationException();
if (project.ProjectFileName != null) {
lock (projectDictionary) {
projectDictionary.Add(project.ProjectFileName, project);
}
}
}
}
}

230
ICSharpCode.Decompiler/TypeSystem/DomRegion.cs

@ -0,0 +1,230 @@ @@ -0,0 +1,230 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Globalization;
namespace ICSharpCode.NRefactory.TypeSystem
{
[Serializable]
public struct DomRegion : IEquatable<DomRegion>
{
readonly string fileName;
readonly int beginLine;
readonly int endLine;
readonly int beginColumn;
readonly int endColumn;
public readonly static DomRegion Empty = new DomRegion();
public bool IsEmpty {
get {
return BeginLine <= 0;
}
}
public string FileName {
get { return fileName; }
}
public int BeginLine {
get {
return beginLine;
}
}
/// <value>
/// if the end line is == -1 the end column is -1 too
/// this stands for an unknwon end
/// </value>
public int EndLine {
get {
return endLine;
}
}
public int BeginColumn {
get {
return beginColumn;
}
}
/// <value>
/// if the end column is == -1 the end line is -1 too
/// this stands for an unknown end
/// </value>
public int EndColumn {
get {
return endColumn;
}
}
public TextLocation Begin {
get {
return new TextLocation (beginLine, beginColumn);
}
}
public TextLocation End {
get {
return new TextLocation (endLine, endColumn);
}
}
public DomRegion (int beginLine, int beginColumn, int endLine, int endColumn) : this (null, beginLine, beginColumn, endLine, endColumn)
{
}
public DomRegion(string fileName, int beginLine, int beginColumn, int endLine, int endColumn)
{
this.fileName = fileName;
this.beginLine = beginLine;
this.beginColumn = beginColumn;
this.endLine = endLine;
this.endColumn = endColumn;
}
public DomRegion (int beginLine, int beginColumn) : this (null, beginLine, beginColumn)
{
}
public DomRegion (string fileName, int beginLine, int beginColumn)
{
this.fileName = fileName;
this.beginLine = beginLine;
this.beginColumn = beginColumn;
this.endLine = -1;
this.endColumn = -1;
}
public DomRegion (TextLocation begin, TextLocation end) : this (null, begin, end)
{
}
public DomRegion (string fileName, TextLocation begin, TextLocation end)
{
this.fileName = fileName;
this.beginLine = begin.Line;
this.beginColumn = begin.Column;
this.endLine = end.Line;
this.endColumn = end.Column;
}
public DomRegion (TextLocation begin) : this (null, begin)
{
}
public DomRegion (string fileName, TextLocation begin)
{
this.fileName = fileName;
this.beginLine = begin.Line;
this.beginColumn = begin.Column;
this.endLine = -1;
this.endColumn = -1;
}
/// <remarks>
/// Returns true, if the given coordinates (line, column) are in the region.
/// This method assumes that for an unknown end the end line is == -1
/// </remarks>
public bool IsInside(int line, int column)
{
if (IsEmpty)
return false;
return line >= BeginLine &&
(line <= EndLine || EndLine == -1) &&
(line != BeginLine || column >= BeginColumn) &&
(line != EndLine || column <= EndColumn);
}
public bool IsInside(TextLocation location)
{
return IsInside(location.Line, location.Column);
}
/// <remarks>
/// Returns true, if the given coordinates (line, column) are in the region.
/// This method assumes that for an unknown end the end line is == -1
/// </remarks>
public bool Contains(int line, int column)
{
if (IsEmpty)
return false;
return line >= BeginLine &&
(line <= EndLine || EndLine == -1) &&
(line != BeginLine || column >= BeginColumn) &&
(line != EndLine || column < EndColumn);
}
public bool Contains(TextLocation location)
{
return Contains(location.Line, location.Column);
}
public bool IntersectsWith (DomRegion region)
{
return region.Begin <= End && region.End >= Begin;
}
public bool OverlapsWith (DomRegion region)
{
var maxBegin = Begin > region.Begin ? Begin : region.Begin;
var minEnd = End < region.End ? End : region.End;
return maxBegin < minEnd;
}
public override string ToString()
{
return string.Format(
CultureInfo.InvariantCulture,
"[DomRegion FileName={0}, Begin=({1}, {2}), End=({3}, {4})]",
fileName, beginLine, beginColumn, endLine, endColumn);
}
public override bool Equals(object obj)
{
return obj is DomRegion && Equals((DomRegion)obj);
}
public override int GetHashCode()
{
unchecked {
int hashCode = fileName != null ? fileName.GetHashCode() : 0;
hashCode ^= beginColumn + 1100009 * beginLine + 1200007 * endLine + 1300021 * endColumn;
return hashCode;
}
}
public bool Equals(DomRegion other)
{
return beginLine == other.beginLine && beginColumn == other.beginColumn
&& endLine == other.endLine && endColumn == other.endColumn
&& fileName == other.fileName;
}
public static bool operator ==(DomRegion left, DomRegion right)
{
return left.Equals(right);
}
public static bool operator !=(DomRegion left, DomRegion right)
{
return !left.Equals(right);
}
}
}

63
ICSharpCode.Decompiler/TypeSystem/EntityType.cs

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
[Obsolete("Use SymbolKind instead")]
public enum EntityType : byte
{
None = SymbolKind.None,
/// <seealso cref="ITypeDefinition"/>
TypeDefinition = SymbolKind.TypeDefinition,
/// <seealso cref="IField"/>
Field = SymbolKind.Field,
/// <summary>
/// The symbol is a property, but not an indexer.
/// </summary>
/// <seealso cref="IProperty"/>
Property = SymbolKind.Property,
/// <summary>
/// The symbol is an indexer, not a regular property.
/// </summary>
/// <seealso cref="IProperty"/>
Indexer = SymbolKind.Indexer,
/// <seealso cref="IEvent"/>
Event = SymbolKind.Event,
/// <summary>
/// The symbol is a method which is not an operator/constructor/destructor or accessor.
/// </summary>
/// <seealso cref="IMethod"/>
Method = SymbolKind.Method,
/// <summary>
/// The symbol is a user-defined operator.
/// </summary>
/// <seealso cref="IMethod"/>
Operator = SymbolKind.Operator,
/// <seealso cref="IMethod"/>
Constructor = SymbolKind.Constructor,
/// <seealso cref="IMethod"/>
Destructor = SymbolKind.Destructor,
/// <summary>
/// The accessor method for a property getter/setter or event add/remove.
/// </summary>
/// <seealso cref="IMethod"/>
Accessor = SymbolKind.Accessor,
}
}

139
ICSharpCode.Decompiler/TypeSystem/Error.cs

@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
//
// Error.cs
//
// Author:
// Mike Krüger <mike@icsharpcode.net>
//
// Copyright (c) 2011 Mike Krüger <mike@icsharpcode.net>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Enum that describes the type of an error.
/// </summary>
public enum ErrorType
{
Unknown,
Error,
Warning
}
/// <summary>
/// Descibes an error during parsing.
/// </summary>
[Serializable]
public class Error
{
readonly ErrorType errorType;
readonly string message;
readonly DomRegion region;
/// <summary>
/// The type of the error.
/// </summary>
public ErrorType ErrorType { get { return errorType; } }
/// <summary>
/// The error description.
/// </summary>
public string Message { get { return message; } }
/// <summary>
/// The region of the error.
/// </summary>
public DomRegion Region { get { return region; } }
/// <summary>
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
/// </summary>
/// <param name='errorType'>
/// The error type.
/// </param>
/// <param name='message'>
/// The description of the error.
/// </param>
/// <param name='region'>
/// The region of the error.
/// </param>
public Error (ErrorType errorType, string message, DomRegion region)
{
this.errorType = errorType;
this.message = message;
this.region = region;
}
/// <summary>
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
/// </summary>
/// <param name='errorType'>
/// The error type.
/// </param>
/// <param name='message'>
/// The description of the error.
/// </param>
/// <param name='location'>
/// The location of the error.
/// </param>
public Error (ErrorType errorType, string message, TextLocation location)
{
this.errorType = errorType;
this.message = message;
this.region = new DomRegion (location, location);
}
/// <summary>
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
/// </summary>
/// <param name='errorType'>
/// The error type.
/// </param>
/// <param name='message'>
/// The description of the error.
/// </param>
/// <param name='line'>
/// The line of the error.
/// </param>
/// <param name='col'>
/// The column of the error.
/// </param>
public Error (ErrorType errorType, string message, int line, int col) : this (errorType, message, new TextLocation (line, col))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ICSharpCode.NRefactory.TypeSystem.Error"/> class.
/// </summary>
/// <param name='errorType'>
/// The error type.
/// </param>
/// <param name='message'>
/// The description of the error.
/// </param>
public Error (ErrorType errorType, string message)
{
this.errorType = errorType;
this.message = message;
this.region = DomRegion.Empty;
}
}
}

315
ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs

@ -0,0 +1,315 @@ @@ -0,0 +1,315 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Holds the full name of a type definition.
/// A full type name uniquely identifies a type definition within a single assembly.
/// </summary>
/// <remarks>
/// A full type name can only represent type definitions, not arbitrary types.
/// It does not include any type arguments, and can not refer to array or pointer types.
///
/// A full type name represented as reflection name has the syntax:
/// <c>NamespaceName '.' TopLevelTypeName ['`'#] { '+' NestedTypeName ['`'#] }</c>
/// </remarks>
[Serializable]
public struct FullTypeName : IEquatable<FullTypeName>
{
[Serializable]
struct NestedTypeName
{
public readonly string Name;
public readonly int AdditionalTypeParameterCount;
public NestedTypeName(string name, int additionalTypeParameterCount)
{
if (name == null)
throw new ArgumentNullException("name");
this.Name = name;
this.AdditionalTypeParameterCount = additionalTypeParameterCount;
}
}
readonly TopLevelTypeName topLevelType;
readonly NestedTypeName[] nestedTypes;
FullTypeName(TopLevelTypeName topLevelTypeName, NestedTypeName[] nestedTypes)
{
this.topLevelType = topLevelTypeName;
this.nestedTypes = nestedTypes;
}
/// <summary>
/// Constructs a FullTypeName representing the given top-level type.
/// </summary>
/// <remarks>
/// FullTypeName has an implicit conversion operator from TopLevelTypeName,
/// so you can simply write:
/// <c>FullTypeName f = new TopLevelTypeName(...);</c>
/// </remarks>
public FullTypeName(TopLevelTypeName topLevelTypeName)
{
this.topLevelType = topLevelTypeName;
this.nestedTypes = null;
}
/// <summary>
/// Constructs a FullTypeName by parsing the given reflection name.
/// Note that FullTypeName can only represent type definition names. If the reflection name
/// might refer to a parameterized type or array etc., use
/// <see cref="ReflectionHelper.ParseReflectionName(string)"/> instead.
/// </summary>
/// <remarks>
/// Expected syntax: <c>NamespaceName '.' TopLevelTypeName ['`'#] { '+' NestedTypeName ['`'#] }</c>
/// where # are type parameter counts
/// </remarks>
public FullTypeName(string reflectionName)
{
int pos = reflectionName.IndexOf('+');
if (pos < 0) {
// top-level type
this.topLevelType = new TopLevelTypeName(reflectionName);
this.nestedTypes = null;
} else {
// nested type
string[] parts = reflectionName.Split('+');
this.topLevelType = new TopLevelTypeName(parts[0]);
this.nestedTypes = new NestedTypeName[parts.Length - 1];
for (int i = 0; i < nestedTypes.Length; i++) {
int tpc;
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(parts[i + 1], out tpc);
nestedTypes[i] = new NestedTypeName(name, tpc);
}
}
}
/// <summary>
/// Gets the top-level type name.
/// </summary>
public TopLevelTypeName TopLevelTypeName {
get { return topLevelType; }
}
/// <summary>
/// Gets whether this is a nested type.
/// </summary>
public bool IsNested {
get {
return nestedTypes != null;
}
}
/// <summary>
/// Gets the nesting level.
/// </summary>
public int NestingLevel {
get {
return nestedTypes != null ? nestedTypes.Length : 0;
}
}
/// <summary>
/// Gets the name of the type.
/// For nested types, this is the name of the innermost type.
/// </summary>
public string Name {
get {
if (nestedTypes != null)
return nestedTypes[nestedTypes.Length - 1].Name;
else
return topLevelType.Name;
}
}
public string ReflectionName {
get {
if (nestedTypes == null)
return topLevelType.ReflectionName;
StringBuilder b = new StringBuilder(topLevelType.ReflectionName);
foreach (NestedTypeName nt in nestedTypes) {
b.Append('+');
b.Append(nt.Name);
if (nt.AdditionalTypeParameterCount > 0) {
b.Append('`');
b.Append(nt.AdditionalTypeParameterCount);
}
}
return b.ToString();
}
}
/// <summary>
/// Gets the total type parameter count.
/// </summary>
public int TypeParameterCount {
get {
int tpc = topLevelType.TypeParameterCount;
if (nestedTypes != null) {
foreach (var nt in nestedTypes) {
tpc += nt.AdditionalTypeParameterCount;
}
}
return tpc;
}
}
/// <summary>
/// Gets the name of the nested type at the given level.
/// </summary>
public string GetNestedTypeName(int nestingLevel)
{
if (nestedTypes == null)
throw new InvalidOperationException();
return nestedTypes[nestingLevel].Name;
}
/// <summary>
/// Gets the number of additional type parameters of the nested type at the given level.
/// </summary>
public int GetNestedTypeAdditionalTypeParameterCount(int nestingLevel)
{
if (nestedTypes == null)
throw new InvalidOperationException();
return nestedTypes[nestingLevel].AdditionalTypeParameterCount;
}
/// <summary>
/// Gets the declaring type name.
/// </summary>
/// <exception cref="InvalidOperationException">This is a top-level type name.</exception>
/// <example><c>new FullTypeName("NS.A+B+C").GetDeclaringType()</c> will return <c>new FullTypeName("NS.A+B")</c></example>
public FullTypeName GetDeclaringType()
{
if (nestedTypes == null)
throw new InvalidOperationException();
if (nestedTypes.Length == 1)
return topLevelType;
NestedTypeName[] outerNestedTypeNames = new NestedTypeName[nestedTypes.Length - 1];
Array.Copy(nestedTypes, 0, outerNestedTypeNames, 0, outerNestedTypeNames.Length);
return new FullTypeName(topLevelType, nestedTypes);
}
/// <summary>
/// Creates a nested type name.
/// </summary>
/// <example><c>new FullTypeName("NS.A+B").NestedType("C", 1)</c> will return <c>new FullTypeName("NS.A+B+C`1")</c></example>
public FullTypeName NestedType(string name, int additionalTypeParameterCount)
{
if (name == null)
throw new ArgumentNullException("name");
var newNestedType = new NestedTypeName(name, additionalTypeParameterCount);
if (nestedTypes == null)
return new FullTypeName(topLevelType, new[] { newNestedType });
NestedTypeName[] newNestedTypeNames = new NestedTypeName[nestedTypes.Length + 1];
nestedTypes.CopyTo(newNestedTypeNames, 0);
newNestedTypeNames[newNestedTypeNames.Length - 1] = newNestedType;
return new FullTypeName(topLevelType, newNestedTypeNames);
}
public static implicit operator FullTypeName(TopLevelTypeName topLevelTypeName)
{
return new FullTypeName(topLevelTypeName);
}
public override string ToString()
{
return this.ReflectionName;
}
#region Equals and GetHashCode implementation
public override bool Equals(object obj)
{
return obj is FullTypeName && Equals((FullTypeName)obj);
}
public bool Equals(FullTypeName other)
{
return FullTypeNameComparer.Ordinal.Equals(this, other);
}
public override int GetHashCode()
{
return FullTypeNameComparer.Ordinal.GetHashCode(this);
}
public static bool operator ==(FullTypeName left, FullTypeName right)
{
return left.Equals(right);
}
public static bool operator !=(FullTypeName left, FullTypeName right)
{
return !left.Equals(right);
}
#endregion
}
[Serializable]
public sealed class FullTypeNameComparer : IEqualityComparer<FullTypeName>
{
public static readonly FullTypeNameComparer Ordinal = new FullTypeNameComparer(StringComparer.Ordinal);
public static readonly FullTypeNameComparer OrdinalIgnoreCase = new FullTypeNameComparer(StringComparer.OrdinalIgnoreCase);
public readonly StringComparer NameComparer;
public FullTypeNameComparer(StringComparer nameComparer)
{
this.NameComparer = nameComparer;
}
public bool Equals(FullTypeName x, FullTypeName y)
{
if (x.NestingLevel != y.NestingLevel)
return false;
TopLevelTypeName topX = x.TopLevelTypeName;
TopLevelTypeName topY = y.TopLevelTypeName;
if (topX.TypeParameterCount == topY.TypeParameterCount
&& NameComparer.Equals(topX.Name, topY.Name)
&& NameComparer.Equals(topX.Namespace, topY.Namespace))
{
for (int i = 0; i < x.NestingLevel; i++) {
if (x.GetNestedTypeAdditionalTypeParameterCount(i) != y.GetNestedTypeAdditionalTypeParameterCount(i))
return false;
if (!NameComparer.Equals(x.GetNestedTypeName(i), y.GetNestedTypeName(i)))
return false;
}
return true;
}
return false;
}
public int GetHashCode(FullTypeName obj)
{
TopLevelTypeName top = obj.TopLevelTypeName;
int hash = NameComparer.GetHashCode(top.Name) ^ NameComparer.GetHashCode(top.Namespace) ^ top.TypeParameterCount;
unchecked {
for (int i = 0; i < obj.NestingLevel; i++) {
hash *= 31;
hash += NameComparer.GetHashCode(obj.Name) ^ obj.TypeParameterCount;
}
}
return hash;
}
}
}

107
ICSharpCode.Decompiler/TypeSystem/IAmbience.cs

@ -0,0 +1,107 @@ @@ -0,0 +1,107 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
[Flags]
public enum ConversionFlags
{
/// <summary>
/// Convert only the name.
/// </summary>
None = 0,
/// <summary>
/// Show the parameter list
/// </summary>
ShowParameterList = 1,
/// <summary>
/// Show names for parameters
/// </summary>
ShowParameterNames = 2,
/// <summary>
/// Show the accessibility (private, public, etc.)
/// </summary>
ShowAccessibility = 4,
/// <summary>
/// Show the definition key word (class, struct, Sub, Function, etc.)
/// </summary>
ShowDefinitionKeyword = 8,
/// <summary>
/// Show the declaring type for the member
/// </summary>
ShowDeclaringType = 0x10,
/// <summary>
/// Show modifiers (virtual, override, etc.)
/// </summary>
ShowModifiers = 0x20,
/// <summary>
/// Show the return type
/// </summary>
ShowReturnType = 0x40,
/// <summary>
/// Use fully qualified names for types.
/// </summary>
UseFullyQualifiedTypeNames = 0x80,
/// <summary>
/// Show the list of type parameters on method and class declarations.
/// Type arguments for parameter/return types are always shown.
/// </summary>
ShowTypeParameterList = 0x100,
/// <summary>
/// For fields, events and methods: adds a semicolon at the end.
/// For properties: shows "{ get; }" or similar.
/// </summary>
ShowBody = 0x200,
/// <summary>
/// Use fully qualified names for members.
/// </summary>
UseFullyQualifiedEntityNames = 0x400,
StandardConversionFlags = ShowParameterNames |
ShowAccessibility |
ShowParameterList |
ShowReturnType |
ShowModifiers |
ShowTypeParameterList |
ShowDefinitionKeyword |
ShowBody,
All = 0x7ff,
}
/// <summary>
/// Ambiences are used to convert type system symbols to text (usually for displaying the symbol to the user; e.g. in editor tooltips).
/// </summary>
public interface IAmbience
{
ConversionFlags ConversionFlags { get; set; }
[Obsolete("Use ConvertSymbol() instead")]
string ConvertEntity(IEntity entity);
string ConvertSymbol(ISymbol symbol);
string ConvertType(IType type);
[Obsolete("Use ConvertSymbol() instead")]
string ConvertVariable(IVariable variable);
string ConvertConstantValue(object constantValue);
string WrapComment(string comment);
}
}

128
ICSharpCode.Decompiler/TypeSystem/IAssembly.cs

@ -0,0 +1,128 @@ @@ -0,0 +1,128 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents an unresolved assembly.
/// </summary>
public interface IUnresolvedAssembly : IAssemblyReference
{
/// <summary>
/// Gets the assembly name (short name).
/// </summary>
string AssemblyName { get; }
/// <summary>
/// Gets the full assembly name (including public key token etc.)
/// </summary>
string FullAssemblyName { get; }
/// <summary>
/// Gets the path to the assembly location.
/// For projects it is the same as the output path.
/// </summary>
string Location { get; }
/// <summary>
/// Gets the list of all assembly attributes in the project.
/// </summary>
IEnumerable<IUnresolvedAttribute> AssemblyAttributes { get; }
/// <summary>
/// Gets the list of all module attributes in the project.
/// </summary>
IEnumerable<IUnresolvedAttribute> ModuleAttributes { get; }
/// <summary>
/// Gets all non-nested types in the assembly.
/// </summary>
IEnumerable<IUnresolvedTypeDefinition> TopLevelTypeDefinitions { get; }
}
public interface IAssemblyReference
{
/// <summary>
/// Resolves this assembly.
/// </summary>
IAssembly Resolve(ITypeResolveContext context);
}
/// <summary>
/// Represents an assembly.
/// </summary>
public interface IAssembly : ICompilationProvider
{
/// <summary>
/// Gets the original unresolved assembly.
/// </summary>
IUnresolvedAssembly UnresolvedAssembly { get; }
/// <summary>
/// Gets whether this assembly is the main assembly of the compilation.
/// </summary>
bool IsMainAssembly { get; }
/// <summary>
/// Gets the assembly name (short name).
/// </summary>
string AssemblyName { get; }
/// <summary>
/// Gets the full assembly name (including public key token etc.)
/// </summary>
string FullAssemblyName { get; }
/// <summary>
/// Gets the list of all assembly attributes in the project.
/// </summary>
IList<IAttribute> AssemblyAttributes { get; }
/// <summary>
/// Gets the list of all module attributes in the project.
/// </summary>
IList<IAttribute> ModuleAttributes { get; }
/// <summary>
/// Gets whether the internals of this assembly are visible in the specified assembly.
/// </summary>
bool InternalsVisibleTo(IAssembly assembly);
/// <summary>
/// Gets the root namespace for this assembly.
/// </summary>
/// <remarks>
/// This always is the namespace without a name - it's unrelated to the 'root namespace' project setting.
/// </remarks>
INamespace RootNamespace { get; }
/// <summary>
/// Gets the type definition for a top-level type.
/// </summary>
/// <remarks>This method uses ordinal name comparison, not the compilation's name comparer.</remarks>
ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName);
/// <summary>
/// Gets all non-nested types in the assembly.
/// </summary>
IEnumerable<ITypeDefinition> TopLevelTypeDefinitions { get; }
}
}

75
ICSharpCode.Decompiler/TypeSystem/IAttribute.cs

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents an unresolved attribute.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
public interface IUnresolvedAttribute
{
/// <summary>
/// Gets the code region of this attribute.
/// </summary>
DomRegion Region { get; }
/// <summary>
/// Resolves the attribute.
/// </summary>
IAttribute CreateResolvedAttribute(ITypeResolveContext context);
}
/// <summary>
/// Represents an attribute.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
public interface IAttribute
{
/// <summary>
/// Gets the code region of this attribute.
/// </summary>
DomRegion Region { get; }
/// <summary>
/// Gets the type of the attribute.
/// </summary>
IType AttributeType { get; }
/// <summary>
/// Gets the constructor being used.
/// This property may return null if no matching constructor was found.
/// </summary>
IMethod Constructor { get; }
/// <summary>
/// Gets the positional arguments.
/// </summary>
IList<ResolveResult> PositionalArguments { get; }
/// <summary>
/// Gets the named arguments passed to the attribute.
/// </summary>
IList<KeyValuePair<IMember, ResolveResult>> NamedArguments { get; }
}
}

38
ICSharpCode.Decompiler/TypeSystem/ICodeContext.cs

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem
{
public interface ICodeContext : ITypeResolveContext
{
/// <summary>
/// Gets all currently visible local variables and lambda parameters.
/// Does not include method parameters.
/// </summary>
IEnumerable<IVariable> LocalVariables { get; }
/// <summary>
/// Gets whether the context is within a lambda expression or anonymous method.
/// </summary>
bool IsWithinLambdaExpression { get; }
}
}

91
ICSharpCode.Decompiler/TypeSystem/ICompilation.cs

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.TypeSystem
{
public interface ICompilation
{
/// <summary>
/// Gets the current assembly.
/// </summary>
IAssembly MainAssembly { get; }
/// <summary>
/// Gets the type resolve context that specifies this compilation and no current assembly or entity.
/// </summary>
ITypeResolveContext TypeResolveContext { get; }
/// <summary>
/// Gets the list of all assemblies in the compilation.
/// </summary>
/// <remarks>
/// This main assembly is the first entry in the list.
/// </remarks>
IList<IAssembly> Assemblies { get; }
/// <summary>
/// Gets the referenced assemblies.
/// This list does not include the main assembly.
/// </summary>
IList<IAssembly> ReferencedAssemblies { get; }
/// <summary>
/// Gets the root namespace of this compilation.
/// This is a merged version of the root namespaces of all assemblies.
/// </summary>
/// <remarks>
/// This always is the namespace without a name - it's unrelated to the 'root namespace' project setting.
/// </remarks>
INamespace RootNamespace { get; }
/// <summary>
/// Gets the root namespace for a given extern alias.
/// </summary>
/// <remarks>
/// If <paramref name="alias"/> is <c>null</c> or an empty string, this method
/// returns the global root namespace.
/// If no alias with the specified name exists, this method returns null.
/// </remarks>
INamespace GetNamespaceForExternAlias(string alias);
IType FindType(KnownTypeCode typeCode);
/// <summary>
/// Gets the name comparer for the language being compiled.
/// This is the string comparer used for the INamespace.GetTypeDefinition method.
/// </summary>
StringComparer NameComparer { get; }
ISolutionSnapshot SolutionSnapshot { get; }
CacheManager CacheManager { get; }
}
public interface ICompilationProvider
{
/// <summary>
/// Gets the parent compilation.
/// This property never returns null.
/// </summary>
ICompilation Compilation { get; }
}
}

38
ICSharpCode.Decompiler/TypeSystem/IConstantValue.cs

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics.Contracts;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents an unresolved constant value.
/// </summary>
public interface IConstantValue
{
/// <summary>
/// Resolves the value of this constant.
/// </summary>
/// <param name="context">Context where the constant value will be used.</param>
/// <returns>Resolve result representing the constant value.
/// This method never returns null; in case of errors, an ErrorResolveResult will be returned.</returns>
ResolveResult Resolve(ITypeResolveContext context);
}
}

178
ICSharpCode.Decompiler/TypeSystem/IEntity.cs

@ -0,0 +1,178 @@ @@ -0,0 +1,178 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using ICSharpCode.NRefactory.Documentation;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents an unresolved entity.
/// </summary>
public interface IUnresolvedEntity : INamedElement, IHasAccessibility
{
/// <summary>
/// Gets the entity type.
/// </summary>
SymbolKind SymbolKind { get; }
/// <summary>
/// Gets the complete entity region (including header+body)
/// </summary>
DomRegion Region { get; }
/// <summary>
/// Gets the entity body region.
/// </summary>
DomRegion BodyRegion { get; }
/// <summary>
/// Gets the declaring class.
/// For members, this is the class that contains the member.
/// For nested classes, this is the outer class. For top-level entities, this property returns null.
/// </summary>
IUnresolvedTypeDefinition DeclaringTypeDefinition { get; }
/// <summary>
/// Gets the parsed file in which this entity is defined.
/// Returns null if this entity wasn't parsed from source code (e.g. loaded from a .dll with CecilLoader).
/// </summary>
IUnresolvedFile UnresolvedFile { get; }
/// <summary>
/// Gets the attributes on this entity.
/// </summary>
IList<IUnresolvedAttribute> Attributes { get; }
/// <summary>
/// Gets whether this entity is static.
/// Returns true if either the 'static' or the 'const' modifier is set.
/// </summary>
bool IsStatic { get; }
/// <summary>
/// Returns whether this entity is abstract.
/// </summary>
/// <remarks>Static classes also count as abstract classes.</remarks>
bool IsAbstract { get; }
/// <summary>
/// Returns whether this entity is sealed.
/// </summary>
/// <remarks>Static classes also count as sealed classes.</remarks>
bool IsSealed { get; }
/// <summary>
/// Gets whether this member is declared to be shadowing another member with the same name.
/// </summary>
bool IsShadowing { get; }
/// <summary>
/// Gets whether this member is generated by a macro/compiler feature.
/// </summary>
bool IsSynthetic { get; }
}
/// <summary>
/// Represents a resolved entity.
/// </summary>
public interface IEntity : ISymbol, ICompilationProvider, INamedElement, IHasAccessibility
{
/// <summary>
/// Gets the entity type.
/// </summary>
[Obsolete("Use the SymbolKind property instead.")]
EntityType EntityType { get; }
/// <summary>
/// Gets the short name of the entity.
/// </summary>
new string Name { get; }
/// <summary>
/// Gets the complete entity region (including header+body)
/// </summary>
DomRegion Region { get; }
/// <summary>
/// Gets the entity body region.
/// </summary>
DomRegion BodyRegion { get; }
/// <summary>
/// Gets the declaring class.
/// For members, this is the class that contains the member.
/// For nested classes, this is the outer class. For top-level entities, this property returns null.
/// </summary>
ITypeDefinition DeclaringTypeDefinition { get; }
/// <summary>
/// Gets/Sets the declaring type (incl. type arguments, if any).
/// This property will return null for top-level entities.
/// If this is not a specialized member, the value returned is equal to <see cref="DeclaringTypeDefinition"/>.
/// </summary>
IType DeclaringType { get; }
/// <summary>
/// The assembly in which this entity is defined.
/// This property never returns null.
/// </summary>
IAssembly ParentAssembly { get; }
/// <summary>
/// Gets the attributes on this entity.
/// </summary>
IList<IAttribute> Attributes { get; }
/// <summary>
/// Gets the documentation for this entity.
/// </summary>
DocumentationComment Documentation { get; }
/// <summary>
/// Gets whether this entity is static.
/// Returns true if either the 'static' or the 'const' modifier is set.
/// </summary>
bool IsStatic { get; }
/// <summary>
/// Returns whether this entity is abstract.
/// </summary>
/// <remarks>Static classes also count as abstract classes.</remarks>
bool IsAbstract { get; }
/// <summary>
/// Returns whether this entity is sealed.
/// </summary>
/// <remarks>Static classes also count as sealed classes.</remarks>
bool IsSealed { get; }
/// <summary>
/// Gets whether this member is declared to be shadowing another member with the same name.
/// (C# 'new' keyword)
/// </summary>
bool IsShadowing { get; }
/// <summary>
/// Gets whether this member is generated by a macro/compiler feature.
/// </summary>
bool IsSynthetic { get; }
}
}

58
ICSharpCode.Decompiler/TypeSystem/IEvent.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics.Contracts;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.TypeSystem
{
public interface IUnresolvedEvent : IUnresolvedMember
{
bool CanAdd { get; }
bool CanRemove { get; }
bool CanInvoke { get; }
IUnresolvedMethod AddAccessor { get; }
IUnresolvedMethod RemoveAccessor { get; }
IUnresolvedMethod InvokeAccessor { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context for looking up the member. The context must specify the current assembly.
/// A <see cref="SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IEvent Resolve(ITypeResolveContext context);
}
public interface IEvent : IMember
{
bool CanAdd { get; }
bool CanRemove { get; }
bool CanInvoke { get; }
IMethod AddAccessor { get; }
IMethod RemoveAccessor { get; }
IMethod InvokeAccessor { get; }
}
}

99
ICSharpCode.Decompiler/TypeSystem/IField.cs

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics.Contracts;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents a field or constant.
/// </summary>
public interface IUnresolvedField : IUnresolvedMember
{
/// <summary>
/// Gets whether this field is readonly.
/// </summary>
bool IsReadOnly { get; }
/// <summary>
/// Gets whether this field is volatile.
/// </summary>
bool IsVolatile { get; }
/// <summary>
/// Gets whether this field is a constant (C#-like const).
/// </summary>
bool IsConst { get; }
/// <summary>
/// Gets whether this field is a fixed size buffer (C#-like fixed).
/// If this is true, then ConstantValue contains the size of the buffer.
/// </summary>
bool IsFixed { get; }
IConstantValue ConstantValue { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context for looking up the member. The context must specify the current assembly.
/// A <see cref="SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IField Resolve(ITypeResolveContext context);
}
/// <summary>
/// Represents a field or constant.
/// </summary>
public interface IField : IMember, IVariable
{
/// <summary>
/// Gets the name of the field.
/// </summary>
new string Name { get; } // solve ambiguity between IMember.Name and IVariable.Name
/// <summary>
/// Gets the region where the field is declared.
/// </summary>
new DomRegion Region { get; } // solve ambiguity between IEntity.Region and IVariable.Region
/// <summary>
/// Gets whether this field is readonly.
/// </summary>
bool IsReadOnly { get; }
/// <summary>
/// Gets whether this field is volatile.
/// </summary>
bool IsVolatile { get; }
/// <summary>
/// Gets whether this field is a fixed size buffer (C#-like fixed).
/// If this is true, then ConstantValue contains the size of the buffer.
/// </summary>
bool IsFixed { get; }
new IMemberReference ToReference(); // solve ambiguity between IMember.ToReference() and IVariable.ToReference()
}
}

35
ICSharpCode.Decompiler/TypeSystem/IFreezable.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
public interface IFreezable
{
/// <summary>
/// Gets if this instance is frozen. Frozen instances are immutable and thus thread-safe.
/// </summary>
bool IsFrozen { get; }
/// <summary>
/// Freezes this instance.
/// </summary>
void Freeze();
}
}

102
ICSharpCode.Decompiler/TypeSystem/IInterningProvider.cs

@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Provider used for interning.
/// </summary>
/// <remarks>
/// A simple IInterningProvider implementation could use 3 dictionaries:
/// 1. using value equality comparer (for certain types known to implement value equality, e.g. string and IType)
/// 2. using comparer that calls into ISupportsInterning (for types implementing ISupportsInterning)
/// 3. list comparer (for InternList method)
///
/// On the first Intern()-call, the provider tells the object to prepare for interning (ISupportsInterning.PrepareForInterning)
/// and stores it into a dictionary. On further Intern() calls, the original object is returned for all equal objects.
/// This allows reducing the memory usage by using a single object instance where possible.
///
/// Interning provider implementations could also use the interning logic for different purposes:
/// for example, it could be used to determine which objects are used jointly between multiple type definitions
/// and which are used only within a single type definition. Then a persistent file format could be organized so
/// that shared objects are loaded only once, yet non-shared objects get loaded lazily together with the class.
/// </remarks>
public abstract class InterningProvider
{
public static readonly InterningProvider Dummy = new DummyInterningProvider();
/// <summary>
/// Interns the specified object.
///
/// If the object is freezable, it will be frozen.
/// </summary>
public abstract ISupportsInterning Intern(ISupportsInterning obj);
/// <summary>
/// Interns the specified object.
///
/// If the object is freezable, it will be frozen.
/// </summary>
public T Intern<T>(T obj) where T : class, ISupportsInterning
{
ISupportsInterning input = obj;
return (T)Intern(input);
}
/// <summary>
/// Interns the specified string.
/// </summary>
public abstract string Intern(string text);
/// <summary>
/// Inters a boxed value type.
/// </summary>
public abstract object InternValue(object obj);
/// <summary>
/// Interns the given list. Uses reference equality to compare the list elements.
/// </summary>
public abstract IList<T> InternList<T>(IList<T> list) where T : class;
sealed class DummyInterningProvider : InterningProvider
{
public override ISupportsInterning Intern(ISupportsInterning obj)
{
return obj;
}
public override string Intern(string text)
{
return text;
}
public override object InternValue(object obj)
{
return obj;
}
public override IList<T> InternList<T>(IList<T> list)
{
return list;
}
}
}
}

196
ICSharpCode.Decompiler/TypeSystem/IMember.cs

@ -0,0 +1,196 @@ @@ -0,0 +1,196 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Method/field/property/event.
/// </summary>
public interface IUnresolvedMember : IUnresolvedEntity, IMemberReference
{
/// <summary>
/// Gets the return type of this member.
/// This property never returns null.
/// </summary>
ITypeReference ReturnType { get; }
/// <summary>
/// Gets whether this member is explicitly implementing an interface.
/// If this property is true, the member can only be called through the interfaces it implements.
/// </summary>
bool IsExplicitInterfaceImplementation { get; }
/// <summary>
/// Gets the interfaces that are explicitly implemented by this member.
/// </summary>
IList<IMemberReference> ExplicitInterfaceImplementations { get; }
/// <summary>
/// Gets if the member is virtual. Is true only if the "virtual" modifier was used, but non-virtual
/// members can be overridden, too; if they are abstract or overriding a method.
/// </summary>
bool IsVirtual { get; }
/// <summary>
/// Gets whether this member is overriding another member.
/// </summary>
bool IsOverride { get; }
/// <summary>
/// Gets if the member can be overridden. Returns true when the member is "abstract", "virtual" or "override" but not "sealed".
/// </summary>
bool IsOverridable { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context for looking up the member. The context must specify the current assembly.
/// A <see cref="SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IMember Resolve(ITypeResolveContext context);
/// <summary>
/// Creates the resolved member.
/// </summary>
/// <param name="context">
/// The language-specific context that includes the parent type definition.
/// <see cref="IUnresolvedTypeDefinition.CreateResolveContext"/>
/// </param>
IMember CreateResolved(ITypeResolveContext context);
}
public interface IMemberReference : ISymbolReference
{
/// <summary>
/// Gets the declaring type reference for the member.
/// </summary>
ITypeReference DeclaringTypeReference { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context to use for resolving this member reference.
/// Which kind of context is required depends on the which kind of member reference this is;
/// please consult the documentation of the method that was used to create this member reference,
/// or that of the class implementing this method.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IMember Resolve(ITypeResolveContext context);
}
/// <summary>
/// Method/field/property/event.
/// </summary>
public interface IMember : IEntity
{
/// <summary>
/// Gets the original member definition for this member.
/// Returns <c>this</c> if this is not a specialized member.
/// Specialized members are the result of overload resolution with type substitution.
/// </summary>
IMember MemberDefinition { get; }
/// <summary>
/// Gets the unresolved member instance from which this member was created.
/// This property may return <c>null</c> for special members that do not have a corresponding unresolved member instance.
/// </summary>
/// <remarks>
/// For specialized members, this property returns the unresolved member for the original member definition.
/// For partial methods, this property returns the implementing partial method declaration, if one exists, and the
/// defining partial method declaration otherwise.
/// For the members used to represent the built-in C# operators like "operator +(int, int);", this property returns <c>null</c>.
/// </remarks>
IUnresolvedMember UnresolvedMember { get; }
/// <summary>
/// Gets the return type of this member.
/// This property never returns <c>null</c>.
/// </summary>
IType ReturnType { get; }
/// <summary>
/// Gets the interface members implemented by this member (both implicitly and explicitly).
/// </summary>
IList<IMember> ImplementedInterfaceMembers { get; }
/// <summary>
/// Gets whether this member is explicitly implementing an interface.
/// </summary>
bool IsExplicitInterfaceImplementation { get; }
/// <summary>
/// Gets if the member is virtual. Is true only if the "virtual" modifier was used, but non-virtual
/// members can be overridden, too; if they are abstract or overriding a method.
/// </summary>
bool IsVirtual { get; }
/// <summary>
/// Gets whether this member is overriding another member.
/// </summary>
bool IsOverride { get; }
/// <summary>
/// Gets if the member can be overridden. Returns true when the member is "abstract", "virtual" or "override" but not "sealed".
/// </summary>
bool IsOverridable { get; }
/// <summary>
/// Creates a member reference that can be used to rediscover this member in another compilation.
/// </summary>
/// <remarks>
/// If this member is specialized using open generic types, the resulting member reference will need to be looked up in an appropriate generic context.
/// Otherwise, the main resolve context of a compilation is sufficient.
/// </remarks>
[Obsolete("Use the ToReference method instead.")]
IMemberReference ToMemberReference();
/// <summary>
/// Creates a member reference that can be used to rediscover this member in another compilation.
/// </summary>
/// <remarks>
/// If this member is specialized using open generic types, the resulting member reference will need to be looked up in an appropriate generic context.
/// Otherwise, the main resolve context of a compilation is sufficient.
/// </remarks>
new IMemberReference ToReference();
/// <summary>
/// Gets the substitution belonging to this specialized member.
/// Returns TypeParameterSubstitution.Identity for not specialized members.
/// </summary>
TypeParameterSubstitution Substitution {
get;
}
/// <summary>
/// Specializes this member with the given substitution.
/// If this member is already specialized, the new substitution is composed with the existing substition.
/// </summary>
IMember Specialize(TypeParameterSubstitution substitution);
}
}

168
ICSharpCode.Decompiler/TypeSystem/IMethod.cs

@ -0,0 +1,168 @@ @@ -0,0 +1,168 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.TypeSystem
{
public interface IUnresolvedMethod : IUnresolvedParameterizedMember
{
/// <summary>
/// Gets the attributes associated with the return type. (e.g. [return: MarshalAs(...)])
/// </summary>
IList<IUnresolvedAttribute> ReturnTypeAttributes { get; }
IList<IUnresolvedTypeParameter> TypeParameters { get; }
bool IsConstructor { get; }
bool IsDestructor { get; }
bool IsOperator { get; }
/// <summary>
/// Gets whether the method is a C#-style partial method.
/// Check <see cref="HasBody"/> to test if it is a partial method declaration or implementation.
/// </summary>
bool IsPartial { get; }
/// <summary>
/// Gets whether the method is a C#-style async method.
/// </summary>
bool IsAsync { get; }
[Obsolete("Use IsPartial && !HasBody instead")]
bool IsPartialMethodDeclaration { get; }
[Obsolete("Use IsPartial && HasBody instead")]
bool IsPartialMethodImplementation { get; }
/// <summary>
/// Gets whether the method has a body.
/// This property returns <c>false</c> for <c>abstract</c> or <c>extern</c> methods,
/// or for <c>partial</c> methods without implementation.
/// </summary>
bool HasBody { get; }
/// <summary>
/// If this method is an accessor, returns a reference to the corresponding property/event.
/// Otherwise, returns null.
/// </summary>
IUnresolvedMember AccessorOwner { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context for looking up the member. The context must specify the current assembly.
/// A <see cref="SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IMethod Resolve(ITypeResolveContext context);
}
/// <summary>
/// Represents a method, constructor, destructor or operator.
/// </summary>
public interface IMethod : IParameterizedMember
{
/// <summary>
/// Gets the unresolved method parts.
/// For partial methods, this returns all parts.
/// Otherwise, this returns an array with a single element (new[] { UnresolvedMember }).
/// NOTE: The type will change to IReadOnlyList&lt;IUnresolvedMethod&gt; in future versions.
/// </summary>
IList<IUnresolvedMethod> Parts { get; }
/// <summary>
/// Gets the attributes associated with the return type. (e.g. [return: MarshalAs(...)])
/// NOTE: The type will change to IReadOnlyList&lt;IAttribute&gt; in future versions.
/// </summary>
IList<IAttribute> ReturnTypeAttributes { get; }
/// <summary>
/// Gets the type parameters of this method; or an empty list if the method is not generic.
/// NOTE: The type will change to IReadOnlyList&lt;ITypeParameter&gt; in future versions.
/// </summary>
IList<ITypeParameter> TypeParameters { get; }
/// <summary>
/// Gets whether this is a generic method that has been parameterized.
/// </summary>
bool IsParameterized { get; }
/// <summary>
/// Gets the type arguments passed to this method.
/// If the method is generic but not parameterized yet, this property returns the type parameters,
/// as if the method was parameterized with its own type arguments (<c>void M&lt;T&gt;() { M&lt;T&gt;(); }</c>).
///
/// NOTE: The type will change to IReadOnlyList&lt;IType&gt; in future versions.
/// </summary>
IList<IType> TypeArguments { get; }
bool IsExtensionMethod { get; }
bool IsConstructor { get; }
bool IsDestructor { get; }
bool IsOperator { get; }
/// <summary>
/// Gets whether the method is a C#-style partial method.
/// A call to such a method is ignored by the compiler if the partial method has no body.
/// </summary>
/// <seealso cref="HasBody"/>
bool IsPartial { get; }
/// <summary>
/// Gets whether the method is a C#-style async method.
/// </summary>
bool IsAsync { get; }
/// <summary>
/// Gets whether the method has a body.
/// This property returns <c>false</c> for <c>abstract</c> or <c>extern</c> methods,
/// or for <c>partial</c> methods without implementation.
/// </summary>
bool HasBody { get; }
/// <summary>
/// Gets whether the method is a property/event accessor.
/// </summary>
bool IsAccessor { get; }
/// <summary>
/// If this method is an accessor, returns the corresponding property/event.
/// Otherwise, returns null.
/// </summary>
IMember AccessorOwner { get; }
/// <summary>
/// If this method is reduced from an extension method return the original method, <c>null</c> otherwise.
/// A reduced method doesn't contain the extension method parameter. That means that has one parameter less than it's definition.
/// </summary>
IMethod ReducedFrom { get; }
/// <summary>
/// Specializes this method with the given substitution.
/// If this method is already specialized, the new substitution is composed with the existing substition.
/// </summary>
new IMethod Specialize(TypeParameterSubstitution substitution);
}
}

66
ICSharpCode.Decompiler/TypeSystem/INamedElement.cs

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics.Contracts;
namespace ICSharpCode.NRefactory.TypeSystem
{
public interface INamedElement
{
/// <summary>
/// Gets the fully qualified name of the class the return type is pointing to.
/// </summary>
/// <returns>
/// "System.Int32[]" for int[]<br/>
/// "System.Collections.Generic.List" for List&lt;string&gt;
/// "System.Environment.SpecialFolder" for Environment.SpecialFolder
/// </returns>
string FullName { get; }
/// <summary>
/// Gets the short name of the class the return type is pointing to.
/// </summary>
/// <returns>
/// "Int32[]" for int[]<br/>
/// "List" for List&lt;string&gt;
/// "SpecialFolder" for Environment.SpecialFolder
/// </returns>
string Name { get; }
/// <summary>
/// Gets the full reflection name of the element.
/// </summary>
/// <remarks>
/// For types, the reflection name can be parsed back into a ITypeReference by using
/// <see cref="ReflectionHelper.ParseReflectionName(string)"/>.
/// </remarks>
/// <returns>
/// "System.Int32[]" for int[]<br/>
/// "System.Int32[][,]" for C# int[,][]<br/>
/// "System.Collections.Generic.List`1[[System.String]]" for List&lt;string&gt;
/// "System.Environment+SpecialFolder" for Environment.SpecialFolder
/// </returns>
string ReflectionName { get; }
/// <summary>
/// Gets the full name of the namespace containing this entity.
/// </summary>
string Namespace { get; }
}
}

88
ICSharpCode.Decompiler/TypeSystem/INamespace.cs

@ -0,0 +1,88 @@ @@ -0,0 +1,88 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents a resolved namespace.
/// </summary>
public interface INamespace : ISymbol, ICompilationProvider
{
// No pointer back to unresolved namespace:
// multiple unresolved namespaces (from different assemblies) get
// merged into one INamespace.
/// <summary>
/// Gets the extern alias for this namespace.
/// Returns an empty string for normal namespaces.
/// </summary>
string ExternAlias { get; }
/// <summary>
/// Gets the full name of this namespace. (e.g. "System.Collections")
/// </summary>
string FullName { get; }
/// <summary>
/// Gets the short name of this namespace (e.g. "Collections").
/// </summary>
new string Name { get; }
/// <summary>
/// Gets the parent namespace.
/// Returns null if this is the root namespace.
/// </summary>
INamespace ParentNamespace { get; }
/// <summary>
/// Gets the child namespaces in this namespace.
/// </summary>
IEnumerable<INamespace> ChildNamespaces { get; }
/// <summary>
/// Gets the types in this namespace.
/// </summary>
IEnumerable<ITypeDefinition> Types { get; }
/// <summary>
/// Gets the assemblies that contribute types to this namespace (or to child namespaces).
/// </summary>
IEnumerable<IAssembly> ContributingAssemblies { get; }
/// <summary>
/// Gets a direct child namespace by its short name.
/// Returns null when the namespace cannot be found.
/// </summary>
/// <remarks>
/// This method uses the compilation's current string comparer.
/// </remarks>
INamespace GetChildNamespace(string name);
/// <summary>
/// Gets the type with the specified short name and type parameter count.
/// Returns null if the type cannot be found.
/// </summary>
/// <remarks>
/// This method uses the compilation's current string comparer.
/// </remarks>
ITypeDefinition GetTypeDefinition(string name, int typeParameterCount);
}
}

104
ICSharpCode.Decompiler/TypeSystem/IParameter.cs

@ -0,0 +1,104 @@ @@ -0,0 +1,104 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
namespace ICSharpCode.NRefactory.TypeSystem
{
public interface IUnresolvedParameter
{
/// <summary>
/// Gets the name of the variable.
/// </summary>
string Name { get; }
/// <summary>
/// Gets the declaration region of the variable.
/// </summary>
DomRegion Region { get; }
/// <summary>
/// Gets the type of the variable.
/// </summary>
ITypeReference Type { get; }
/// <summary>
/// Gets the list of attributes.
/// </summary>
IList<IUnresolvedAttribute> Attributes { get; }
/// <summary>
/// Gets whether this parameter is a C# 'ref' parameter.
/// </summary>
bool IsRef { get; }
/// <summary>
/// Gets whether this parameter is a C# 'out' parameter.
/// </summary>
bool IsOut { get; }
/// <summary>
/// Gets whether this parameter is a C# 'params' parameter.
/// </summary>
bool IsParams { get; }
/// <summary>
/// Gets whether this parameter is optional.
/// </summary>
bool IsOptional { get; }
IParameter CreateResolvedParameter(ITypeResolveContext context);
}
public interface IParameter : IVariable
{
/// <summary>
/// Gets the list of attributes.
/// </summary>
IList<IAttribute> Attributes { get; }
/// <summary>
/// Gets whether this parameter is a C# 'ref' parameter.
/// </summary>
bool IsRef { get; }
/// <summary>
/// Gets whether this parameter is a C# 'out' parameter.
/// </summary>
bool IsOut { get; }
/// <summary>
/// Gets whether this parameter is a C# 'params' parameter.
/// </summary>
bool IsParams { get; }
/// <summary>
/// Gets whether this parameter is optional.
/// The default value is given by the <see cref="IVariable.ConstantValue"/> property.
/// </summary>
bool IsOptional { get; }
/// <summary>
/// Gets the owner of this parameter.
/// May return null; for example when parameters belong to lambdas or anonymous methods.
/// </summary>
IParameterizedMember Owner { get; }
}
}

40
ICSharpCode.Decompiler/TypeSystem/IParameterizedMember.cs

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents a method or property.
/// </summary>
public interface IUnresolvedParameterizedMember : IUnresolvedMember
{
IList<IUnresolvedParameter> Parameters { get; }
}
/// <summary>
/// Represents a method or property.
/// </summary>
public interface IParameterizedMember : IMember
{
IList<IParameter> Parameters { get; }
}
}

159
ICSharpCode.Decompiler/TypeSystem/IProjectContent.cs

@ -0,0 +1,159 @@ @@ -0,0 +1,159 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents an assembly consisting of source code (parsed files).
/// </summary>
public interface IProjectContent : IUnresolvedAssembly
{
/// <summary>
/// Gets the path to the project file (e.g. .csproj).
/// </summary>
string ProjectFileName { get; }
/// <summary>
/// Gets a parsed file by its file name.
/// </summary>
IUnresolvedFile GetFile(string fileName);
/// <summary>
/// Gets the list of all files in the project content.
/// </summary>
IEnumerable<IUnresolvedFile> Files { get; }
/// <summary>
/// Gets the referenced assemblies.
/// </summary>
IEnumerable<IAssemblyReference> AssemblyReferences { get; }
/// <summary>
/// Gets the compiler settings object.
/// The concrete type of the settings object depends on the programming language used to implement this project.
/// </summary>
object CompilerSettings { get; }
/// <summary>
/// Creates a new <see cref="ICompilation"/> that allows resolving within this project.
/// </summary>
/// <remarks>
/// This method does not support <see cref="ProjectReference"/>s. When dealing with a solution
/// containing multiple projects, consider using <see cref="ISolutionSnapshot.GetCompilation"/> instead.
/// </remarks>
ICompilation CreateCompilation();
/// <summary>
/// Creates a new <see cref="ICompilation"/> that allows resolving within this project.
/// </summary>
/// <param name="solutionSnapshot">The parent solution snapshot to use for the compilation.</param>
/// <remarks>
/// This method is intended to be called by ISolutionSnapshot implementations. Other code should
/// call <see cref="ISolutionSnapshot.GetCompilation"/> instead.
/// This method always creates a new compilation, even if the solution snapshot already contains
/// one for this project.
/// </remarks>
ICompilation CreateCompilation(ISolutionSnapshot solutionSnapshot);
/// <summary>
/// Changes the assembly name of this project content.
/// </summary>
IProjectContent SetAssemblyName(string newAssemblyName);
/// <summary>
/// Changes the project file name of this project content.
/// </summary>
IProjectContent SetProjectFileName(string newProjectFileName);
/// <summary>
/// Changes the path to the assembly location (the output path where the project compiles to).
/// </summary>
IProjectContent SetLocation(string newLocation);
/// <summary>
/// Add assembly references to this project content.
/// </summary>
IProjectContent AddAssemblyReferences(IEnumerable<IAssemblyReference> references);
/// <summary>
/// Add assembly references to this project content.
/// </summary>
IProjectContent AddAssemblyReferences(params IAssemblyReference[] references);
/// <summary>
/// Removes assembly references from this project content.
/// </summary>
IProjectContent RemoveAssemblyReferences(IEnumerable<IAssemblyReference> references);
/// <summary>
/// Removes assembly references from this project content.
/// </summary>
IProjectContent RemoveAssemblyReferences(params IAssemblyReference[] references);
/// <summary>
/// Adds the specified files to the project content.
/// If a file with the same name already exists, updated the existing file.
/// </summary>
/// <remarks>
/// You can create an unresolved file by calling <c>ToTypeSystem()</c> on a syntax tree.
/// </remarks>
IProjectContent AddOrUpdateFiles(IEnumerable<IUnresolvedFile> newFiles);
/// <summary>
/// Adds the specified files to the project content.
/// If a file with the same name already exists, this method updates the existing file.
/// </summary>
/// <remarks>
/// You can create an unresolved file by calling <c>ToTypeSystem()</c> on a syntax tree.
/// </remarks>
IProjectContent AddOrUpdateFiles(params IUnresolvedFile[] newFiles);
/// <summary>
/// Removes the files with the specified names.
/// </summary>
IProjectContent RemoveFiles(IEnumerable<string> fileNames);
/// <summary>
/// Removes the files with the specified names.
/// </summary>
IProjectContent RemoveFiles(params string[] fileNames);
/// <summary>
/// Removes types and attributes from oldFile from the project, and adds those from newFile.
/// </summary>
[Obsolete("Use RemoveFiles()/AddOrUpdateFiles() instead")]
IProjectContent UpdateProjectContent(IUnresolvedFile oldFile, IUnresolvedFile newFile);
/// <summary>
/// Removes types and attributes from oldFiles from the project, and adds those from newFiles.
/// </summary>
[Obsolete("Use RemoveFiles()/AddOrUpdateFiles() instead")]
IProjectContent UpdateProjectContent(IEnumerable<IUnresolvedFile> oldFiles, IEnumerable<IUnresolvedFile> newFiles);
/// <summary>
/// Sets the compiler settings object.
/// The concrete type of the settings object depends on the programming language used to implement this project.
/// Using the incorrect type of settings object results in an <see cref="ArgumentException"/>.
/// </summary>
IProjectContent SetCompilerSettings(object compilerSettings);
}
}

62
ICSharpCode.Decompiler/TypeSystem/IProperty.cs

@ -0,0 +1,62 @@ @@ -0,0 +1,62 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents a property or indexer.
/// </summary>
public interface IUnresolvedProperty : IUnresolvedParameterizedMember
{
bool CanGet { get; }
bool CanSet { get; }
IUnresolvedMethod Getter { get; }
IUnresolvedMethod Setter { get; }
bool IsIndexer { get; }
/// <summary>
/// Resolves the member.
/// </summary>
/// <param name="context">
/// Context for looking up the member. The context must specify the current assembly.
/// A <see cref="SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved member, or <c>null</c> if the member could not be found.
/// </returns>
new IProperty Resolve(ITypeResolveContext context);
}
/// <summary>
/// Represents a property or indexer.
/// </summary>
public interface IProperty : IParameterizedMember
{
bool CanGet { get; }
bool CanSet { get; }
IMethod Getter { get; }
IMethod Setter { get; }
bool IsIndexer { get; }
}
}

43
ICSharpCode.Decompiler/TypeSystem/ISolutionSnapshot.cs

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents a snapshot of the whole solution (multiple compilations).
/// </summary>
public interface ISolutionSnapshot
{
/// <summary>
/// Gets the project content with the specified file name.
/// Returns null if no such project exists in the solution.
/// </summary>
/// <remarks>
/// This method is used by the <see cref="ProjectReference"/> class.
/// </remarks>
IProjectContent GetProjectContent(string projectFileName);
/// <summary>
/// Gets the compilation for the specified project.
/// The project must be a part of the solution (passed to the solution snapshot's constructor).
/// </summary>
ICompilation GetCompilation(IProjectContent project);
}
}

39
ICSharpCode.Decompiler/TypeSystem/ISupportsInterning.cs

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Interface for TypeSystem objects that support interning.
/// See <see cref="InterningProvider"/> for more information.
/// </summary>
public interface ISupportsInterning
{
/// <summary>
/// Gets a hash code for interning.
/// </summary>
int GetHashCodeForInterning();
/// <summary>
/// Equality test for interning.
/// </summary>
bool EqualsForInterning(ISupportsInterning other);
}
}

100
ICSharpCode.Decompiler/TypeSystem/ISymbol.cs

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
public enum SymbolKind : byte
{
None,
/// <seealso cref="ITypeDefinition"/>
TypeDefinition,
/// <seealso cref="IField"/>
Field,
/// <summary>
/// The symbol is a property, but not an indexer.
/// </summary>
/// <seealso cref="IProperty"/>
Property,
/// <summary>
/// The symbol is an indexer, not a regular property.
/// </summary>
/// <seealso cref="IProperty"/>
Indexer,
/// <seealso cref="IEvent"/>
Event,
/// <summary>
/// The symbol is a method which is not an operator/constructor/destructor or accessor.
/// </summary>
/// <seealso cref="IMethod"/>
Method,
/// <summary>
/// The symbol is a user-defined operator.
/// </summary>
/// <seealso cref="IMethod"/>
Operator,
/// <seealso cref="IMethod"/>
Constructor,
/// <seealso cref="IMethod"/>
Destructor,
/// <summary>
/// The accessor method for a property getter/setter or event add/remove.
/// </summary>
/// <seealso cref="IMethod"/>
Accessor,
/// <seealso cref="INamespace"/>
Namespace,
/// <summary>
/// The symbol is a variable, but not a parameter.
/// </summary>
/// <seealso cref="IVariable"/>
Variable,
/// <seealso cref="IParameter"/>
Parameter,
/// <seealso cref="ITypeParameter"/>
TypeParameter,
}
/// <summary>
/// Interface for type system symbols.
/// </summary>
public interface ISymbol
{
/// <summary>
/// This property returns an enum specifying which kind of symbol this is
/// (which derived interfaces of ISymbol are implemented)
/// </summary>
SymbolKind SymbolKind { get; }
/// <summary>
/// Gets the short name of the symbol.
/// </summary>
string Name { get; }
/// <summary>
/// Creates a symbol reference that can be used to rediscover this symbol in another compilation.
/// </summary>
ISymbolReference ToReference();
}
public interface ISymbolReference
{
ISymbol Resolve(ITypeResolveContext context);
}
}

350
ICSharpCode.Decompiler/TypeSystem/IType.cs

@ -0,0 +1,350 @@ @@ -0,0 +1,350 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// This interface represents a resolved type in the type system.
/// </summary>
/// <remarks>
/// <para>
/// A type is potentially
/// - a type definition (<see cref="ITypeDefinition"/>, i.e. a class, struct, interface, delegate, or built-in primitive type)
/// - a parameterized type (<see cref="ParameterizedType"/>, e.g. List&lt;int>)
/// - a type parameter (<see cref="ITypeParameter"/>, e.g. T)
/// - an array (<see cref="ArrayType"/>)
/// - a pointer (<see cref="PointerType"/>)
/// - a managed reference (<see cref="ByReferenceType"/>)
/// - one of the special types (<see cref="SpecialType.UnknownType"/>, <see cref="SpecialType.NullType"/>,
/// <see cref="SpecialType.Dynamic"/>, <see cref="SpecialType.UnboundTypeArgument"/>)
///
/// The <see cref="IType.Kind"/> property can be used to switch on the kind of a type.
/// </para>
/// <para>
/// IType uses the null object pattern: <see cref="SpecialType.UnknownType"/> serves as the null object.
/// Methods or properties returning IType never return null unless documented otherwise.
/// </para>
/// <para>
/// Types should be compared for equality using the <see cref="IEquatable{IType}.Equals(IType)"/> method.
/// Identical types do not necessarily use the same object reference.
/// </para>
/// </remarks>
public interface IType : INamedElement, IEquatable<IType>
{
/// <summary>
/// Gets the type kind.
/// </summary>
TypeKind Kind { get; }
/// <summary>
/// Gets whether the type is a reference type or value type.
/// </summary>
/// <returns>
/// true, if the type is a reference type.
/// false, if the type is a value type.
/// null, if the type is not known (e.g. unconstrained generic type parameter or type not found)
/// </returns>
bool? IsReferenceType { get; }
/// <summary>
/// Gets the underlying type definition.
/// Can return null for types which do not have a type definition (for example arrays, pointers, type parameters).
/// </summary>
ITypeDefinition GetDefinition();
/// <summary>
/// Gets the parent type, if this is a nested type.
/// Returns null for top-level types.
/// </summary>
IType DeclaringType { get; }
/// <summary>
/// Gets the number of type parameters.
/// </summary>
int TypeParameterCount { get; }
/// <summary>
/// Gets the type arguments passed to this type.
/// If this type is a generic type definition that is not parameterized, this property returns the type parameters,
/// as if the type was parameterized with its own type arguments (<c>class C&lt;T&gt; { C&lt;T&gt; field; }</c>).
///
/// NOTE: The type will change to IReadOnlyList&lt;IType&gt; in future versions.
/// </summary>
IList<IType> TypeArguments { get; }
/// <summary>
/// If true the type represents an instance of a generic type.
/// </summary>
bool IsParameterized { get; }
/// <summary>
/// Calls ITypeVisitor.Visit for this type.
/// </summary>
/// <returns>The return value of the ITypeVisitor.Visit call</returns>
IType AcceptVisitor(TypeVisitor visitor);
/// <summary>
/// Calls ITypeVisitor.Visit for all children of this type, and reconstructs this type with the children based
/// on the return values of the visit calls.
/// </summary>
/// <returns>A copy of this type, with all children replaced by the return value of the corresponding visitor call.
/// If the visitor returned the original types for all children (or if there are no children), returns <c>this</c>.
/// </returns>
IType VisitChildren(TypeVisitor visitor);
/// <summary>
/// Gets the direct base types.
/// </summary>
/// <returns>Returns the direct base types including interfaces</returns>
IEnumerable<IType> DirectBaseTypes { get; }
/// <summary>
/// Creates a type reference that can be used to look up a type equivalent to this type in another compilation.
/// </summary>
/// <remarks>
/// If this type contains open generics, the resulting type reference will need to be looked up in an appropriate generic context.
/// Otherwise, the main resolve context of a compilation is sufficient.
/// </remarks>
ITypeReference ToTypeReference();
/// <summary>
/// Gets a type visitor that performs the substitution of class type parameters with the type arguments
/// of this parameterized type.
/// Returns TypeParameterSubstitution.Identity if the type is not parametrized.
/// </summary>
TypeParameterSubstitution GetSubstitution();
/// <summary>
/// Gets a type visitor that performs the substitution of class type parameters with the type arguments
/// of this parameterized type,
/// and also substitutes method type parameters with the specified method type arguments.
/// Returns TypeParameterSubstitution.Identity if the type is not parametrized.
/// </summary>
TypeParameterSubstitution GetSubstitution(IList<IType> methodTypeArguments);
/// <summary>
/// Gets inner classes (including inherited inner classes).
/// </summary>
/// <param name="filter">The filter used to select which types to return.
/// The filter is tested on the original type definitions (before parameterization).</param>
/// <param name="options">Specified additional options for the GetMembers() operation.</param>
/// <remarks>
/// <para>
/// If the nested type is generic, this method will return a parameterized type,
/// where the additional type parameters are set to <see cref="SpecialType.UnboundTypeArgument"/>.
/// </para>
/// <para>
/// Type parameters belonging to the outer class will have the value copied from the outer type
/// if it is a parameterized type. Otherwise, those existing type parameters will be self-parameterized,
/// and thus 'leaked' to the caller in the same way the GetMembers() method does not specialize members
/// from an <see cref="ITypeDefinition"/> and 'leaks' type parameters in member signatures.
/// </para>
/// </remarks>
/// <example>
/// <code>
/// class Base&lt;T> {
/// class Nested&lt;X> {}
/// }
/// class Derived&lt;A, B> : Base&lt;B> {}
///
/// Derived[string,int].GetNestedTypes() = { Base`1+Nested`1[int, unbound] }
/// Derived.GetNestedTypes() = { Base`1+Nested`1[`1, unbound] }
/// Base[`1].GetNestedTypes() = { Base`1+Nested`1[`1, unbound] }
/// Base.GetNestedTypes() = { Base`1+Nested`1[`0, unbound] }
/// </code>
/// </example>
IEnumerable<IType> GetNestedTypes(Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None);
// Note that we cannot 'leak' the additional type parameter as we leak the normal type parameters, because
// the index might collide. For example,
// class Base<T> { class Nested<X> {} }
// class Derived<A, B> : Base<B> { }
//
// Derived<string, int>.GetNestedTypes() = Base+Nested<int, UnboundTypeArgument>
// Derived.GetNestedTypes() = Base+Nested<`1, >
// Here `1 refers to B, and there's no way to return X as it would collide with B.
/// <summary>
/// Gets inner classes (including inherited inner classes)
/// that have <c>typeArguments.Count</c> additional type parameters.
/// </summary>
/// <param name="typeArguments">The type arguments passed to the inner class</param>
/// <param name="filter">The filter used to select which types to return.
/// The filter is tested on the original type definitions (before parameterization).</param>
/// <param name="options">Specified additional options for the GetMembers() operation.</param>
/// <remarks>
/// Type parameters belonging to the outer class will have the value copied from the outer type
/// if it is a parameterized type. Otherwise, those existing type parameters will be self-parameterized,
/// and thus 'leaked' to the caller in the same way the GetMembers() method does not specialize members
/// from an <see cref="ITypeDefinition"/> and 'leaks' type parameters in member signatures.
/// </remarks>
IEnumerable<IType> GetNestedTypes(IList<IType> typeArguments, Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None);
/// <summary>
/// Gets all instance constructors for this type.
/// </summary>
/// <param name="filter">The filter used to select which constructors to return.
/// The filter is tested on the original method definitions (before specialization).</param>
/// <param name="options">Specified additional options for the GetMembers() operation.</param>
/// <remarks>
/// <para>The result does not include static constructors.
/// Constructors in base classes are not returned by default, as GetMemberOptions.IgnoreInheritedMembers is the default value.</para>
/// <para>
/// For methods on parameterized types, type substitution will be performed on the method signature,
/// and the appropriate <see cref="Implementation.SpecializedMethod"/> will be returned.
/// </para>
/// </remarks>
IEnumerable<IMethod> GetConstructors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers);
/// <summary>
/// Gets all methods that can be called on this type.
/// </summary>
/// <param name="filter">The filter used to select which methods to return.
/// The filter is tested on the original method definitions (before specialization).</param>
/// <param name="options">Specified additional options for the GetMembers() operation.</param>
/// <remarks>
/// <para>
/// The result does not include constructors or accessors.
/// </para>
/// <para>
/// For methods on parameterized types, type substitution will be performed on the method signature,
/// and the appropriate <see cref="Implementation.SpecializedMethod"/> will be returned.
/// </para>
/// <para>
/// If the method being returned is generic, and this type is a parameterized type where the type
/// arguments involve another method's type parameters, the resulting specialized signature
/// will be ambiguous as to which method a type parameter belongs to.
/// For example, "List[[``0]].GetMethods()" will return "ConvertAll(Converter`2[[``0, ``0]])".
///
/// If possible, use the other GetMethods() overload to supply type arguments to the method,
/// so that both class and method type parameter can be substituted at the same time, so that
/// the ambiguity can be avoided.
/// </para>
/// </remarks>
IEnumerable<IMethod> GetMethods(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None);
/// <summary>
/// Gets all generic methods that can be called on this type with the specified type arguments.
/// </summary>
/// <param name="typeArguments">The type arguments used for the method call.</param>
/// <param name="filter">The filter used to select which methods to return.
/// The filter is tested on the original method definitions (before specialization).</param>
/// <param name="options">Specified additional options for the GetMembers() operation.</param>
/// <remarks>
/// <para>The result does not include constructors or accessors.</para>
/// <para>
/// Type substitution will be performed on the method signature, creating a <see cref="Implementation.SpecializedMethod"/>
/// with the specified type arguments.
/// </para>
/// <para>
/// When the list of type arguments is empty, this method acts like the GetMethods() overload without
/// the type arguments parameter - that is, it also returns generic methods,
/// and the other overload's remarks about ambiguous signatures apply here as well.
/// </para>
/// </remarks>
IEnumerable<IMethod> GetMethods(IList<IType> typeArguments, Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None);
/// <summary>
/// Gets all properties that can be called on this type.
/// </summary>
/// <param name="filter">The filter used to select which properties to return.
/// The filter is tested on the original property definitions (before specialization).</param>
/// <param name="options">Specified additional options for the GetMembers() operation.</param>
/// <remarks>
/// For properties on parameterized types, type substitution will be performed on the property signature,
/// and the appropriate <see cref="Implementation.SpecializedProperty"/> will be returned.
/// </remarks>
IEnumerable<IProperty> GetProperties(Predicate<IUnresolvedProperty> filter = null, GetMemberOptions options = GetMemberOptions.None);
/// <summary>
/// Gets all fields that can be accessed on this type.
/// </summary>
/// <param name="filter">The filter used to select which constructors to return.
/// The filter is tested on the original field definitions (before specialization).</param>
/// <param name="options">Specified additional options for the GetMembers() operation.</param>
/// <remarks>
/// For fields on parameterized types, type substitution will be performed on the field's return type,
/// and the appropriate <see cref="Implementation.SpecializedField"/> will be returned.
/// </remarks>
IEnumerable<IField> GetFields(Predicate<IUnresolvedField> filter = null, GetMemberOptions options = GetMemberOptions.None);
/// <summary>
/// Gets all events that can be accessed on this type.
/// </summary>
/// <param name="filter">The filter used to select which events to return.
/// The filter is tested on the original event definitions (before specialization).</param>
/// <param name="options">Specified additional options for the GetMembers() operation.</param>
/// <remarks>
/// For fields on parameterized types, type substitution will be performed on the event's return type,
/// and the appropriate <see cref="Implementation.SpecializedEvent"/> will be returned.
/// </remarks>
IEnumerable<IEvent> GetEvents(Predicate<IUnresolvedEvent> filter = null, GetMemberOptions options = GetMemberOptions.None);
/// <summary>
/// Gets all members that can be called on this type.
/// </summary>
/// <param name="filter">The filter used to select which members to return.
/// The filter is tested on the original member definitions (before specialization).</param>
/// <param name="options">Specified additional options for the GetMembers() operation.</param>
/// <remarks>
/// <para>
/// The resulting list is the union of GetFields(), GetProperties(), GetMethods() and GetEvents().
/// It does not include constructors.
/// For parameterized types, type substitution will be performed.
/// </para>
/// <para>
/// For generic methods, the remarks about ambiguous signatures from the
/// <see cref="GetMethods(Predicate{IUnresolvedMethod}, GetMemberOptions)"/> method apply here as well.
/// </para>
/// </remarks>
IEnumerable<IMember> GetMembers(Predicate<IUnresolvedMember> filter = null, GetMemberOptions options = GetMemberOptions.None);
/// <summary>
/// Gets all accessors belonging to properties or events on this type.
/// </summary>
/// <param name="filter">The filter used to select which members to return.
/// The filter is tested on the original member definitions (before specialization).</param>
/// <param name="options">Specified additional options for the GetMembers() operation.</param>
/// <remarks>
/// Accessors are not returned by GetMembers() or GetMethods().
/// </remarks>
IEnumerable<IMethod> GetAccessors(Predicate<IUnresolvedMethod> filter = null, GetMemberOptions options = GetMemberOptions.None);
}
[Flags]
public enum GetMemberOptions
{
/// <summary>
/// No options specified - this is the default.
/// Members will be specialized, and inherited members will be included.
/// </summary>
None = 0x00,
/// <summary>
/// Do not specialize the returned members - directly return the definitions.
/// </summary>
ReturnMemberDefinitions = 0x01,
/// <summary>
/// Do not list inherited members - only list members defined directly on this type.
/// </summary>
IgnoreInheritedMembers = 0x02
}
}

170
ICSharpCode.Decompiler/TypeSystem/ITypeDefinition.cs

@ -0,0 +1,170 @@ @@ -0,0 +1,170 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents an unresolved class, enum, interface, struct, delegate or VB module.
/// For partial classes, an unresolved type definition represents only a single part.
/// </summary>
public interface IUnresolvedTypeDefinition : ITypeReference, IUnresolvedEntity
{
TypeKind Kind { get; }
FullTypeName FullTypeName { get; }
IList<ITypeReference> BaseTypes { get; }
IList<IUnresolvedTypeParameter> TypeParameters { get; }
IList<IUnresolvedTypeDefinition> NestedTypes { get; }
IList<IUnresolvedMember> Members { get; }
IEnumerable<IUnresolvedMethod> Methods { get; }
IEnumerable<IUnresolvedProperty> Properties { get; }
IEnumerable<IUnresolvedField> Fields { get; }
IEnumerable<IUnresolvedEvent> Events { get; }
/// <summary>
/// Gets whether the type definition contains extension methods.
/// Returns null when the type definition needs to be resolved in order to determine whether
/// methods are extension methods.
/// </summary>
bool? HasExtensionMethods { get; }
/// <summary>
/// Gets whether the partial modifier is set on this part of the type definition.
/// </summary>
bool IsPartial { get; }
/// <summary>
/// Gets whether this unresolved type definition causes the addition of a default constructor
/// if no other constructor is present.
/// </summary>
bool AddDefaultConstructorIfRequired { get; }
/// <summary>
/// Looks up the resolved type definition from the <paramref name="context"/> corresponding to this unresolved
/// type definition.
/// </summary>
/// <param name="context">
/// Context for looking up the type. The context must specify the current assembly.
/// A <see cref="SimpleTypeResolveContext"/> that specifies the current assembly is sufficient.
/// </param>
/// <returns>
/// Returns the resolved type definition.
/// In case of an error, returns an <see cref="Implementation.UnknownType"/> instance.
/// Never returns null.
/// </returns>
new IType Resolve(ITypeResolveContext context);
/// <summary>
/// This method is used to add language-specific elements like the C# UsingScope
/// to the type resolve context.
/// </summary>
/// <param name="parentContext">The parent context (e.g. the parent assembly),
/// including the parent type definition for inner classes.</param>
/// <returns>
/// The parent context, modified to include language-specific elements (e.g. using scope)
/// associated with this type definition.
/// </returns>
/// <remarks>
/// Use <c>unresolvedTypeDef.CreateResolveContext(parentContext).WithTypeDefinition(typeDef)</c> to
/// create the context for use within the type definition.
/// </remarks>
ITypeResolveContext CreateResolveContext(ITypeResolveContext parentContext);
}
/// <summary>
/// Represents a class, enum, interface, struct, delegate or VB module.
/// For partial classes, this represents the whole class.
/// </summary>
public interface ITypeDefinition : IType, IEntity
{
/// <summary>
/// Returns all parts that contribute to this type definition.
/// Non-partial classes have a single part that represents the whole class.
/// </summary>
IList<IUnresolvedTypeDefinition> Parts { get; }
IList<ITypeParameter> TypeParameters { get; }
IList<ITypeDefinition> NestedTypes { get; }
IList<IMember> Members { get; }
IEnumerable<IField> Fields { get; }
IEnumerable<IMethod> Methods { get; }
IEnumerable<IProperty> Properties { get; }
IEnumerable<IEvent> Events { get; }
/// <summary>
/// Gets the known type code for this type definition.
/// </summary>
KnownTypeCode KnownTypeCode { get; }
/// <summary>
/// For enums: returns the underlying primitive type.
/// For all other types: returns <see cref="SpecialType.UnknownType"/>.
/// </summary>
IType EnumUnderlyingType { get; }
/// <summary>
/// Gets the full name of this type.
/// </summary>
FullTypeName FullTypeName { get; }
/// <summary>
/// Gets/Sets the declaring type (incl. type arguments, if any).
/// This property will return null for top-level types.
/// </summary>
new IType DeclaringType { get; } // solves ambiguity between IType.DeclaringType and IEntity.DeclaringType
/// <summary>
/// Gets whether this type contains extension methods.
/// </summary>
/// <remarks>This property is used to speed up the search for extension methods.</remarks>
bool HasExtensionMethods { get; }
/// <summary>
/// Gets whether this type definition is made up of one or more partial classes.
/// </summary>
bool IsPartial { get; }
/// <summary>
/// Determines how this type is implementing the specified interface member.
/// </summary>
/// <returns>
/// The method on this type that implements the interface member;
/// or null if the type does not implement the interface.
/// </returns>
IMember GetInterfaceImplementation(IMember interfaceMember);
/// <summary>
/// Determines how this type is implementing the specified interface members.
/// </summary>
/// <returns>
/// For each interface member, this method returns the class member
/// that implements the interface member.
/// For interface members that are missing an implementation, the
/// result collection will contain a null element.
/// </returns>
IList<IMember> GetInterfaceImplementation(IList<IMember> interfaceMembers);
}
}

151
ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs

@ -0,0 +1,151 @@ @@ -0,0 +1,151 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Type parameter of a generic class/method.
/// </summary>
public interface IUnresolvedTypeParameter : INamedElement
{
/// <summary>
/// Get the type of this type parameter's owner.
/// </summary>
/// <returns>SymbolKind.TypeDefinition or SymbolKind.Method</returns>
SymbolKind OwnerType { get; }
/// <summary>
/// Gets the index of the type parameter in the type parameter list of the owning method/class.
/// </summary>
int Index { get; }
/// <summary>
/// Gets the list of attributes declared on this type parameter.
/// </summary>
IList<IUnresolvedAttribute> Attributes { get; }
/// <summary>
/// Gets the variance of this type parameter.
/// </summary>
VarianceModifier Variance { get; }
/// <summary>
/// Gets the region where the type parameter is defined.
/// </summary>
DomRegion Region { get; }
ITypeParameter CreateResolvedTypeParameter(ITypeResolveContext context);
}
/// <summary>
/// Type parameter of a generic class/method.
/// </summary>
public interface ITypeParameter : IType, ISymbol
{
/// <summary>
/// Get the type of this type parameter's owner.
/// </summary>
/// <returns>SymbolKind.TypeDefinition or SymbolKind.Method</returns>
SymbolKind OwnerType { get; }
/// <summary>
/// Gets the owning method/class.
/// This property may return null (for example for the dummy type parameters used by <see cref="ParameterListComparer.NormalizeMethodTypeParameters"/>).
/// </summary>
/// <remarks>
/// For "class Outer&lt;T&gt; { class Inner {} }",
/// inner.TypeParameters[0].Owner will be the outer class, because the same
/// ITypeParameter instance is used both on Outer`1 and Outer`1+Inner.
/// </remarks>
IEntity Owner { get; }
/// <summary>
/// Gets the index of the type parameter in the type parameter list of the owning method/class.
/// </summary>
int Index { get; }
/// <summary>
/// Gets the name of the type parameter.
/// </summary>
new string Name { get; }
/// <summary>
/// Gets the list of attributes declared on this type parameter.
/// </summary>
IList<IAttribute> Attributes { get; }
/// <summary>
/// Gets the variance of this type parameter.
/// </summary>
VarianceModifier Variance { get; }
/// <summary>
/// Gets the region where the type parameter is defined.
/// </summary>
DomRegion Region { get; }
/// <summary>
/// Gets the effective base class of this type parameter.
/// </summary>
IType EffectiveBaseClass { get; }
/// <summary>
/// Gets the effective interface set of this type parameter.
/// </summary>
ICollection<IType> EffectiveInterfaceSet { get; }
/// <summary>
/// Gets if the type parameter has the 'new()' constraint.
/// </summary>
bool HasDefaultConstructorConstraint { get; }
/// <summary>
/// Gets if the type parameter has the 'class' constraint.
/// </summary>
bool HasReferenceTypeConstraint { get; }
/// <summary>
/// Gets if the type parameter has the 'struct' constraint.
/// </summary>
bool HasValueTypeConstraint { get; }
}
/// <summary>
/// Represents the variance of a type parameter.
/// </summary>
public enum VarianceModifier : byte
{
/// <summary>
/// The type parameter is not variant.
/// </summary>
Invariant,
/// <summary>
/// The type parameter is covariant (used in output position).
/// </summary>
Covariant,
/// <summary>
/// The type parameter is contravariant (used in input position).
/// </summary>
Contravariant
};
}

73
ICSharpCode.Decompiler/TypeSystem/ITypeReference.cs

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents a reference to a type.
/// Must be resolved before it can be used as type.
/// </summary>
public interface ITypeReference
{
// Keep this interface simple: I decided against having GetMethods/GetEvents etc. here,
// so that the Resolve step is never hidden from the consumer.
// I decided against implementing IFreezable here: IUnresolvedTypeDefinition can be used as ITypeReference,
// but when freezing the reference, one wouldn't expect the definition to freeze.
/// <summary>
/// Resolves this type reference.
/// </summary>
/// <param name="context">
/// Context to use for resolving this type reference.
/// Which kind of context is required depends on the which kind of type reference this is;
/// please consult the documentation of the method that was used to create this type reference,
/// or that of the class implementing this method.
/// </param>
/// <returns>
/// Returns the resolved type.
/// In case of an error, returns an unknown type (<see cref="TypeKind.Unknown"/>).
/// Never returns null.
/// </returns>
IType Resolve(ITypeResolveContext context);
}
public interface ITypeResolveContext : ICompilationProvider
{
/// <summary>
/// Gets the current assembly.
/// This property may return null if this context does not specify any assembly.
/// </summary>
IAssembly CurrentAssembly { get; }
/// <summary>
/// Gets the current type definition.
/// </summary>
ITypeDefinition CurrentTypeDefinition { get ;}
/// <summary>
/// Gets the current member.
/// </summary>
IMember CurrentMember { get; }
ITypeResolveContext WithCurrentTypeDefinition(ITypeDefinition typeDefinition);
ITypeResolveContext WithCurrentMember(IMember member);
}
}

80
ICSharpCode.Decompiler/TypeSystem/IUnresolvedFile.cs

@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.TypeSystem
{
[Obsolete("IParsedFile was renamed to IUnresolvedFile", true)]
public interface IParsedFile {}
/// <summary>
/// Represents a single file that was parsed.
/// </summary>
public interface IUnresolvedFile
{
/// <summary>
/// Returns the full path of the file.
/// </summary>
string FileName { get; }
/// <summary>
/// Gets the time when the file was last written.
/// </summary>
DateTime? LastWriteTime { get; set; }
/// <summary>
/// Gets all top-level type definitions.
/// </summary>
IList<IUnresolvedTypeDefinition> TopLevelTypeDefinitions { get; }
/// <summary>
/// Gets all assembly attributes that are defined in this file.
/// </summary>
IList<IUnresolvedAttribute> AssemblyAttributes { get; }
/// <summary>
/// Gets all module attributes that are defined in this file.
/// </summary>
IList<IUnresolvedAttribute> ModuleAttributes { get; }
/// <summary>
/// Gets the top-level type defined at the specified location.
/// Returns null if no type is defined at that location.
/// </summary>
IUnresolvedTypeDefinition GetTopLevelTypeDefinition(TextLocation location);
/// <summary>
/// Gets the type (potentially a nested type) defined at the specified location.
/// Returns null if no type is defined at that location.
/// </summary>
IUnresolvedTypeDefinition GetInnermostTypeDefinition(TextLocation location);
/// <summary>
/// Gets the member defined at the specified location.
/// Returns null if no member is defined at that location.
/// </summary>
IUnresolvedMember GetMember(TextLocation location);
/// <summary>
/// Gets the parser errors.
/// </summary>
IList<Error> Errors { get; }
}
}

54
ICSharpCode.Decompiler/TypeSystem/IVariable.cs

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.TypeSystem
{
/// <summary>
/// Represents a variable (name/type pair).
/// </summary>
public interface IVariable : ISymbol
{
/// <summary>
/// Gets the name of the variable.
/// </summary>
new string Name { get; }
/// <summary>
/// Gets the declaration region of the variable.
/// </summary>
DomRegion Region { get; }
/// <summary>
/// Gets the type of the variable.
/// </summary>
IType Type { get; }
/// <summary>
/// Gets whether this variable is a constant (C#-like const).
/// </summary>
bool IsConst { get; }
/// <summary>
/// If this field is a constant, retrieves the value.
/// For parameters, this is the default value.
/// </summary>
object ConstantValue { get; }
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save