Browse Source

Merge remote-tracking branch 'upstream/master' into mansheng

newNRvisualizers
Mansheng Yang 14 years ago
parent
commit
79ae62a330
  1. 2
      ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs
  2. 8
      ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs
  3. 2
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  4. 134
      ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  5. 5
      ICSharpCode.NRefactory.CSharp/Parser/mcs/doc.cs
  6. 8
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpConversions.cs
  7. 70
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  8. 37
      ICSharpCode.NRefactory.CSharp/Resolver/DynamicInvocationResolveResult.cs
  9. 26
      ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs
  10. 126
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  11. 19
      ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpDocumentationComment.cs
  12. 38
      ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs
  13. 15
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs
  14. 14
      ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs
  15. 113
      ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/PreprocessorDirectiveTests.cs
  16. 27
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs
  17. 612
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/DynamicTests.cs
  18. 41
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs
  19. 21
      ICSharpCode.NRefactory.Tests/Documentation/CSharpCrefLookupTests.cs
  20. 20
      ICSharpCode.NRefactory.Tests/Documentation/CSharpCrefParserTests.cs
  21. 71
      ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs
  22. 17
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  23. 38
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  24. 2
      ICSharpCode.NRefactory/Properties/GlobalAssemblyInfo.cs
  25. 16
      ICSharpCode.NRefactory/Semantics/Conversion.cs
  26. 13
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  27. 2
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedMember.cs
  28. 4
      Packages/ICSharpCode.NRefactory.nuspec

2
ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs

@ -721,7 +721,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -721,7 +721,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
}
DefiniteAssignmentStatus afterTrue = conditionalExpression.TrueExpression.AcceptVisitor(this, beforeTrue);
DefiniteAssignmentStatus afterFalse = conditionalExpression.TrueExpression.AcceptVisitor(this, beforeFalse);
DefiniteAssignmentStatus afterFalse = conditionalExpression.FalseExpression.AcceptVisitor(this, beforeFalse);
return MergeStatus(CleanSpecialValues(afterTrue), CleanSpecialValues(afterFalse));
}
}

8
ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs

@ -62,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -62,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildrenByRole(MemberRole); }
}
string[] conditionals = null;
IList<string> conditionalSymbols = null;
List<Error> errors = new List<Error> ();
@ -76,12 +76,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -76,12 +76,12 @@ namespace ICSharpCode.NRefactory.CSharp
/// the conditional symbols at the start of the first token in the file - including the ones defined
/// in the source file.
/// </summary>
public string[] Conditionals {
public IList<string> ConditionalSymbols {
get {
return conditionals ?? new string[0];
return conditionalSymbols ?? EmptyList<string>.Instance;
}
internal set {
conditionals = value;
conditionalSymbols = value;
}
}

2
ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -41,7 +41,7 @@ @@ -41,7 +41,7 @@
<DefineConstants>TRACE;FULL_AST</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<DebugType>PdbOnly</DebugType>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugType>full</DebugType>

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

@ -3469,6 +3469,73 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3469,6 +3469,73 @@ namespace ICSharpCode.NRefactory.CSharp
return result;
}
#endregion
#region XmlDoc
public DocumentationReference ConvertXmlDoc(DocumentationBuilder doc)
{
DocumentationReference result = new DocumentationReference();
if (doc.ParsedName != null) {
if (doc.ParsedName.Name == "<this>") {
result.EntityType = EntityType.Indexer;
} else {
result.MemberName = doc.ParsedName.Name;
}
if (doc.ParsedName.Left != null) {
result.DeclaringType = ConvertToType(doc.ParsedName.Left);
} else if (doc.ParsedBuiltinType != null) {
result.DeclaringType = ConvertToType(doc.ParsedBuiltinType);
}
if (doc.ParsedName.TypeParameters != null) {
for (int i = 0; i < doc.ParsedName.TypeParameters.Count; i++) {
result.TypeArguments.Add(ConvertToType(doc.ParsedName.TypeParameters[i]));
}
}
} else if (doc.ParsedBuiltinType != null) {
result.EntityType = EntityType.TypeDefinition;
result.DeclaringType = ConvertToType(doc.ParsedBuiltinType);
}
if (doc.ParsedParameters != null) {
result.HasParameterList = true;
result.Parameters.AddRange(doc.ParsedParameters.Select(ConvertXmlDocParameter));
}
if (doc.ParsedOperator != null) {
result.EntityType = EntityType.Operator;
result.OperatorType = (OperatorType)doc.ParsedOperator;
if (result.OperatorType == OperatorType.Implicit || result.OperatorType == OperatorType.Explicit) {
var returnTypeParam = result.Parameters.LastOrNullObject();
returnTypeParam.Remove(); // detach from parameter list
var returnType = returnTypeParam.Type;
returnType.Remove();
result.ConversionOperatorReturnType = returnType;
}
if (result.Parameters.Count == 0) {
// reset HasParameterList if necessary
result.HasParameterList = false;
}
}
return result;
}
ParameterDeclaration ConvertXmlDocParameter(DocumentationParameter p)
{
ParameterDeclaration result = new ParameterDeclaration();
switch (p.Modifier) {
case Parameter.Modifier.OUT:
result.ParameterModifier = ParameterModifier.Out;
break;
case Parameter.Modifier.REF:
result.ParameterModifier = ParameterModifier.Ref;
break;
case Parameter.Modifier.PARAMS:
result.ParameterModifier = ParameterModifier.Params;
break;
}
if (p.Type != null) {
result.Type = ConvertToType(p.Type);
}
return result;
}
#endregion
}
public CSharpParser ()
@ -3671,7 +3738,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3671,7 +3738,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
conversionVisitor.Unit.FileName = fileName;
conversionVisitor.Unit.Conditionals = top.Conditionals.ToArray ();
conversionVisitor.Unit.ConditionalSymbols = top.Conditionals.ToArray ();
return conversionVisitor.Unit;
}
@ -3733,8 +3800,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3733,8 +3800,13 @@ namespace ICSharpCode.NRefactory.CSharp
if (cu == null)
return Enumerable.Empty<EntityDeclaration> ();
var td = cu.Children.FirstOrDefault () as TypeDeclaration;
if (td != null)
return td.Members;
if (td != null) {
var members = td.Members.ToArray();
// detach members from parent
foreach (var m in members)
m.Remove();
return members;
}
return Enumerable.Empty<EntityDeclaration> ();
}
@ -3743,8 +3815,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3743,8 +3815,13 @@ namespace ICSharpCode.NRefactory.CSharp
string code = "void M() { " + Environment.NewLine + reader.ReadToEnd () + "}";
var members = ParseTypeMembers (new StringReader (code), lineModifier - 1);
var method = members.FirstOrDefault () as MethodDeclaration;
if (method != null && method.Body != null)
return method.Body.Statements;
if (method != null && method.Body != null) {
var statements = method.Body.Statements.ToArray();
// detach statements from parent
foreach (var st in statements)
st.Remove();
return statements;
}
return Enumerable.Empty<Statement> ();
}
@ -3753,8 +3830,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3753,8 +3830,11 @@ namespace ICSharpCode.NRefactory.CSharp
string code = reader.ReadToEnd () + " a;";
var members = ParseTypeMembers (new StringReader (code));
var field = members.FirstOrDefault () as FieldDeclaration;
if (field != null)
return field.ReturnType;
if (field != null) {
AstType type = field.ReturnType;
type.Remove();
return type;
}
return AstType.Null;
}
@ -3763,8 +3843,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3763,8 +3843,11 @@ namespace ICSharpCode.NRefactory.CSharp
var es = ParseStatements (new StringReader ("tmp = " + Environment.NewLine + reader.ReadToEnd () + ";"), -1).FirstOrDefault () as ExpressionStatement;
if (es != null) {
AssignmentExpression ae = es.Expression as AssignmentExpression;
if (ae != null)
return ae.Right;
if (ae != null) {
Expression expr = ae.Right;
expr.Remove();
return expr;
}
}
return Expression.Null;
}
@ -3780,12 +3863,39 @@ namespace ICSharpCode.NRefactory.CSharp @@ -3780,12 +3863,39 @@ namespace ICSharpCode.NRefactory.CSharp
public DocumentationReference ParseDocumentationReference (string cref)
{
// see Mono.CSharp.DocumentationBuilder.HandleXrefCommon
if (cref == null)
throw new ArgumentNullException ("cref");
// Additional symbols for < and > are allowed for easier XML typing
cref = cref.Replace ('{', '<').Replace ('}', '>');
// TODO: add support for parsing cref attributes
// (documentation_parsing production, see DocumentationBuilder.HandleXrefCommon)
throw new NotImplementedException ();
lock (parseLock) {
errorReportPrinter = new ErrorReportPrinter("");
var ctx = new CompilerContext(compilerSettings.ToMono(), errorReportPrinter);
ctx.Settings.TabSize = 1;
var stream = new MemoryStream(Encoding.Unicode.GetBytes(cref));
var reader = new SeekableStreamReader(stream, Encoding.Unicode);
var file = new SourceFile("", "", 0);
Location.Initialize(new List<SourceFile> (new [] { file }));
var module = new ModuleContainer(ctx);
module.DocumentationBuilder = new DocumentationBuilder();
var source_file = new CompilationSourceFile (module);
var report = new Report (ctx, errorReportPrinter);
var parser = new Mono.CSharp.CSharpParser (reader, source_file, report);
parser.Lexer.putback_char = Tokenizer.DocumentationXref;
parser.Lexer.parsing_generic_declaration_doc = true;
parser.parse ();
if (report.Errors > 0) {
// Report.Warning (1584, 1, mc.Location, "XML comment on `{0}' has syntactically incorrect cref attribute `{1}'",
// mc.GetSignatureForError (), cref);
}
ConversionVisitor conversionVisitor = new ConversionVisitor (false, parser.LocationsBag);
DocumentationReference docRef = conversionVisitor.ConvertXmlDoc(module.DocumentationBuilder);
CompilerCallableEntryPoint.Reset();
return docRef;
}
}
}
}

5
ICSharpCode.NRefactory.CSharp/Parser/mcs/doc.cs

@ -57,6 +57,11 @@ namespace Mono.CSharp @@ -57,6 +57,11 @@ namespace Mono.CSharp
XmlDocumentation.PreserveWhitespace = false;
}
internal DocumentationBuilder()
{
// for NRefactory CSharpParser.ParseDocumentationReference
}
Report Report {
get {
return module.Compiler.Report;

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

@ -471,7 +471,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -471,7 +471,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool IdentityOrVarianceConversion(IType s, IType t, int subtypeCheckNestingDepth)
{
ITypeDefinition def = s.GetDefinition();
if (def != null && def.Equals(t.GetDefinition())) {
if (def != null) {
if (!def.Equals(t.GetDefinition()))
return false;
ParameterizedType ps = s as ParameterizedType;
ParameterizedType pt = t as ParameterizedType;
if (ps != null && pt != null) {
@ -499,8 +501,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -499,8 +501,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return false; // only of of them is parameterized, or counts don't match? -> not valid conversion
}
return true;
} else {
// not type definitions? we still need to check for equal types (e.g. s and t might be type parameters)
return s.Equals(t);
}
return false;
}
#endregion

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

@ -1900,15 +1900,37 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1900,15 +1900,37 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// C# 4.0 spec: §7.6.5
if (target.Type.Kind == TypeKind.Dynamic) {
return new DynamicInvocationResolveResult(target, arguments.Select((a, i) => new DynamicInvocationArgument(argumentNames != null ? argumentNames[i] : null, a)).ToList().AsReadOnly());
return new DynamicInvocationResolveResult(target, DynamicInvocationType.Invocation, arguments.Select((a, i) => new DynamicInvocationArgument(argumentNames != null ? argumentNames[i] : null, a)).ToList().AsReadOnly());
}
MethodGroupResolveResult mgrr = target as MethodGroupResolveResult;
if (mgrr != null) {
if (arguments.Any(a => a.Type.Kind == TypeKind.Dynamic)) {
// If we have dynamic arguments, we need to represent the invocation as a dynamic invocation if there is more than one applicable method.
var or2 = CreateOverloadResolution(arguments, argumentNames, mgrr.TypeArguments.ToArray());
var applicableMethods = mgrr.MethodsGroupedByDeclaringType.SelectMany(m => m, (x, m) => new { x.DeclaringType, Method = m }).Where(x => OverloadResolution.IsApplicable(or2.AddCandidate(x.Method))).ToList();
if (applicableMethods.Count > 1) {
ResolveResult actualTarget;
if (applicableMethods.All(x => x.Method.IsStatic) && !(mgrr.TargetResult is TypeResolveResult))
actualTarget = new TypeResolveResult(mgrr.TargetType);
else
actualTarget = mgrr.TargetResult;
var l = new List<MethodListWithDeclaringType>();
foreach (var m in applicableMethods) {
if (l.Count == 0 || l[l.Count - 1].DeclaringType != m.DeclaringType)
l.Add(new MethodListWithDeclaringType(m.DeclaringType));
l[l.Count - 1].Add(m.Method);
}
return new DynamicInvocationResolveResult(new MethodGroupResolveResult(actualTarget, mgrr.MethodName, l, mgrr.TypeArguments), DynamicInvocationType.Invocation, arguments.Select((a, i) => new DynamicInvocationArgument(argumentNames != null ? argumentNames[i] : null, a)).ToList().AsReadOnly());
}
}
OverloadResolution or = mgrr.PerformOverloadResolution(compilation, arguments, argumentNames, checkForOverflow: checkForOverflow, conversions: conversions);
if (or.BestCandidate != null) {
if (or.BestCandidate.IsStatic && !or.IsExtensionMethodInvocation && !(mgrr.TargetResult is TypeResolveResult))
return or.CreateResolveResult(new TypeResolveResult(mgrr.TargetResult.Type));
return or.CreateResolveResult(new TypeResolveResult(mgrr.TargetType));
else
return or.CreateResolveResult(mgrr.TargetResult);
} else {
@ -2043,10 +2065,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2043,10 +2065,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
switch (target.Type.Kind) {
case TypeKind.Dynamic:
for (int i = 0; i < arguments.Length; i++) {
arguments[i] = Convert(arguments[i], SpecialType.Dynamic);
}
return new ArrayAccessResolveResult(SpecialType.Dynamic, target, arguments);
return new DynamicInvocationResolveResult(target, DynamicInvocationType.Indexing, arguments.Select((a, i) => new DynamicInvocationArgument(argumentNames != null ? argumentNames[i] : null, a)).ToList().AsReadOnly());
case TypeKind.Array:
case TypeKind.Pointer:
@ -2056,9 +2075,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2056,9 +2075,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
// §7.6.6.2 Indexer access
OverloadResolution or = CreateOverloadResolution(arguments, argumentNames);
MemberLookup lookup = CreateMemberLookup();
var indexers = lookup.LookupIndexers(target.Type);
if (arguments.Any(a => a.Type.Kind == TypeKind.Dynamic)) {
// If we have dynamic arguments, we need to represent the invocation as a dynamic invocation if there is more than one applicable indexer.
var or2 = CreateOverloadResolution(arguments, argumentNames, null);
var applicableIndexers = indexers.SelectMany(x => x).Where(m => OverloadResolution.IsApplicable(or2.AddCandidate(m))).ToList();
if (applicableIndexers.Count > 1) {
return new DynamicInvocationResolveResult(target, DynamicInvocationType.Indexing, arguments.Select((a, i) => new DynamicInvocationArgument(argumentNames != null ? argumentNames[i] : null, a)).ToList().AsReadOnly());
}
}
OverloadResolution or = CreateOverloadResolution(arguments, argumentNames);
or.AddMethodLists(indexers);
if (or.BestCandidate != null) {
return or.CreateResolveResult(target);
@ -2109,16 +2140,35 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2109,16 +2140,35 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public ResolveResult ResolveObjectCreation(IType type, ResolveResult[] arguments, string[] argumentNames = null, bool allowProtectedAccess = false, IList<ResolveResult> initializerStatements = null)
{
if (type.Kind == TypeKind.Delegate && arguments.Length == 1) {
return Convert(arguments[0], type);
ResolveResult input = arguments[0];
IMethod invoke = input.Type.GetDelegateInvokeMethod();
if (invoke != null) {
input = new MethodGroupResolveResult(
input, invoke.Name,
methods: new[] { new MethodListWithDeclaringType(invoke.DeclaringType) { invoke } },
typeArguments: EmptyList<IType>.Instance
);
}
return Convert(input, type);
}
OverloadResolution or = CreateOverloadResolution(arguments, argumentNames);
MemberLookup lookup = CreateMemberLookup();
var allApplicable = (arguments.Any(a => a.Type.Kind == TypeKind.Dynamic) ? new List<IMethod>() : null);
foreach (IMethod ctor in type.GetConstructors()) {
if (lookup.IsAccessible(ctor, allowProtectedAccess))
or.AddCandidate(ctor);
if (lookup.IsAccessible(ctor, allowProtectedAccess)) {
var orErrors = or.AddCandidate(ctor);
if (allApplicable != null && OverloadResolution.IsApplicable(orErrors))
allApplicable.Add(ctor);
}
else
or.AddCandidate(ctor, OverloadResolutionErrors.Inaccessible);
}
if (allApplicable != null && allApplicable.Count > 1) {
// If we have dynamic arguments, we need to represent the invocation as a dynamic invocation if there is more than one applicable constructor.
return new DynamicInvocationResolveResult(new MethodGroupResolveResult(null, allApplicable[0].Name, new[] { new MethodListWithDeclaringType(type, allApplicable) }, null), DynamicInvocationType.ObjectCreation, arguments.Select((a, i) => new DynamicInvocationArgument(argumentNames != null ? argumentNames[i] : null, a)).ToList().AsReadOnly(), initializerStatements);
}
if (or.BestCandidate != null) {
return or.CreateResolveResult(null, initializerStatements);
} else {

37
ICSharpCode.NRefactory.CSharp/Resolver/DynamicInvocationResolveResult.cs

@ -45,24 +45,57 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -45,24 +45,57 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
public enum DynamicInvocationType {
/// <summary>
/// The invocation is a normal invocation ( 'a(b)' ).
/// </summary>
Invocation,
/// <summary>
/// The invocation is an indexing ( 'a[b]' ).
/// </summary>
Indexing,
/// <summary>
/// The invocation is an object creation ( 'new a(b)' ). Also used when invoking a base constructor ( ' : base(a) ' ) and chaining constructors ( ' : this(a) ').
/// </summary>
ObjectCreation,
}
/// <summary>
/// Represents the result of an invocation of a member of a dynamic object.
/// </summary>
public class DynamicInvocationResolveResult : ResolveResult
{
/// <summary>
/// Target of the invocation (a dynamic object).
/// Target of the invocation. Can be a dynamic expression or a <see cref="MethodGroupResolveResult"/>.
/// </summary>
public readonly ResolveResult Target;
/// <summary>
/// Type of the invocation.
/// </summary>
public readonly DynamicInvocationType InvocationType;
/// <summary>
/// Arguments for the call.
/// </summary>
public readonly IList<DynamicInvocationArgument> Arguments;
public DynamicInvocationResolveResult(ResolveResult target, IList<DynamicInvocationArgument> arguments) : base(SpecialType.Dynamic) {
/// <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.
/// Initializer statements can only exist if the <see cref="InvocationType"/> is <see cref="DynamicInvocationType.ObjectCreation"/>.
/// </summary>
public readonly IList<ResolveResult> InitializerStatements;
public DynamicInvocationResolveResult(ResolveResult target, DynamicInvocationType invocationType, IList<DynamicInvocationArgument> arguments, IList<ResolveResult> initializerStatements = null) : base(SpecialType.Dynamic) {
this.Target = target;
this.InvocationType = invocationType;
this.Arguments = arguments ?? EmptyList<DynamicInvocationArgument>.Instance;
this.InitializerStatements = initializerStatements ?? EmptyList<ResolveResult>.Instance;
}
public override string ToString()

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

@ -29,10 +29,32 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -29,10 +29,32 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// A method list that belongs to a declaring type.
/// </summary>
public class MethodListWithDeclaringType : List<IParameterizedMember>
{
readonly IType declaringType;
/// <summary>
/// The declaring type.
/// </summary>
/// <remarks>
/// Not all methods in this list necessarily have this as their declaring type.
/// For example, this program:
/// <code>
/// class Base {
/// public virtual void M() {}
/// }
/// class Derived : Base {
/// public override void M() {}
/// public void M(int i) {}
/// }
/// </code>
/// results in two lists:
/// <c>new MethodListWithDeclaringType(Base) { Derived.M() }</c>,
/// <c>new MethodListWithDeclaringType(Derived) { Derived.M(int) }</c>
/// </remarks>
public IType DeclaringType {
get { return declaringType; }
}
@ -64,8 +86,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -64,8 +86,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public MethodGroupResolveResult(ResolveResult targetResult, string methodName, IList<MethodListWithDeclaringType> methods, IList<IType> typeArguments) : base(SpecialType.UnknownType)
{
if (targetResult == null)
throw new ArgumentNullException("targetResult");
if (methods == null)
throw new ArgumentNullException("methods");
this.targetResult = targetResult;
@ -85,7 +105,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -85,7 +105,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Gets the type of the reference to the target object.
/// </summary>
public IType TargetType {
get { return targetResult.Type; }
get { return targetResult != null ? targetResult.Type : SpecialType.UnknownType; }
}
/// <summary>

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

@ -938,6 +938,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -938,6 +938,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ScanChildren(parameterDeclaration);
if (resolverEnabled) {
string name = parameterDeclaration.Name;
if (parameterDeclaration.Parent is DocumentationReference) {
// create a dummy parameter
IType type = ResolveType(parameterDeclaration.Type);
switch (parameterDeclaration.ParameterModifier) {
case ParameterModifier.Ref:
case ParameterModifier.Out:
type = new ByReferenceType(type);
break;
}
return new LocalResolveResult(new DefaultParameter(
type, name,
isRef: parameterDeclaration.ParameterModifier == ParameterModifier.Ref,
isOut: parameterDeclaration.ParameterModifier == ParameterModifier.Out,
isParams: parameterDeclaration.ParameterModifier == ParameterModifier.Params));
}
// Look in lambda parameters:
foreach (IParameter p in resolver.LocalVariables.OfType<IParameter>()) {
if (p.Name == name)
@ -1479,12 +1496,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1479,12 +1496,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolveResult rr = resolver.ResolveObjectCreation(type, arguments, argumentNames, false, initializerStatements);
if (arguments.Length == 1 && rr.Type.Kind == TypeKind.Delegate) {
// process conversion in case it's a delegate creation
ProcessConversionResult(objectCreateExpression.Arguments.Single(), rr as ConversionResolveResult);
// Apply conversion to argument if it directly wraps the argument
// (but not when creating a delegate from a delegate, as then there would be a MGRR for .Invoke in between)
// This is necessary for lambda type inference.
var crr = rr as ConversionResolveResult;
if (crr != null && crr.Input == arguments[0]) {
ProcessConversionResult(objectCreateExpression.Arguments.Single(), crr);
// wrap the result so that the delegate creation is not handled as a reference
// to the target method - otherwise FindReferencedEntities would produce two results for
// the same delegate creation.
return WrapResult(rr);
} else {
return rr;
}
} else {
// process conversions in all other cases
ProcessConversionsInInvocation(null, objectCreateExpression.Arguments, rr as CSharpInvocationResolveResult);
@ -3847,7 +3872,102 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -3847,7 +3872,102 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region Documentation Reference
ResolveResult IAstVisitor<ResolveResult>.VisitDocumentationReference(DocumentationReference documentationReference)
{
throw new NotImplementedException();
// Resolve child nodes:
ITypeDefinition declaringTypeDef;
if (documentationReference.DeclaringType.IsNull)
declaringTypeDef = resolver.CurrentTypeDefinition;
else
declaringTypeDef = ResolveType(documentationReference.DeclaringType).GetDefinition();
IType[] typeArguments = documentationReference.TypeArguments.Select(ResolveType).ToArray();
IType conversionOperatorReturnType = ResolveType(documentationReference.ConversionOperatorReturnType);
IParameter[] parameters = documentationReference.Parameters.Select(ResolveXmlDocParameter).ToArray();
if (documentationReference.EntityType == EntityType.TypeDefinition) {
if (declaringTypeDef != null)
return new TypeResolveResult(declaringTypeDef);
else
return errorResult;
}
if (documentationReference.EntityType == EntityType.None) {
// might be a type, member or ctor
string memberName = documentationReference.MemberName;
ResolveResult rr;
if (documentationReference.DeclaringType.IsNull) {
rr = resolver.LookupSimpleNameOrTypeName(memberName, typeArguments, NameLookupMode.Expression);
} else {
var target = Resolve(documentationReference.DeclaringType);
rr = resolver.ResolveMemberAccess(target, memberName, typeArguments);
}
// reduce to definition:
if (rr.IsError) {
return rr;
} else if (rr is TypeResolveResult) {
var typeDef = rr.Type.GetDefinition();
if (typeDef == null)
return errorResult;
if (documentationReference.HasParameterList) {
var ctors = typeDef.GetConstructors(options: GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions);
return FindByParameters(ctors, parameters);
} else {
return new TypeResolveResult(typeDef);
}
} else if (rr is MemberResolveResult) {
var mrr = (MemberResolveResult)rr;
return new MemberResolveResult(null, mrr.Member.MemberDefinition);
} else if (rr is MethodGroupResolveResult) {
var mgrr = (MethodGroupResolveResult)rr;
var methods = mgrr.MethodsGroupedByDeclaringType.Reverse()
.SelectMany(ml => ml.Select(m => (IParameterizedMember)m.MemberDefinition));
return FindByParameters(methods, parameters);
}
return rr;
}
// Indexer or operator
if (declaringTypeDef == null)
return errorResult;
if (documentationReference.EntityType == EntityType.Indexer) {
var indexers = declaringTypeDef.Properties.Where(p => p.IsIndexer && !p.IsExplicitInterfaceImplementation);
return FindByParameters(indexers, parameters);
} else if (documentationReference.EntityType == EntityType.Operator) {
var opType = documentationReference.OperatorType;
string memberName = OperatorDeclaration.GetName(opType);
var methods = declaringTypeDef.Methods.Where(m => m.IsOperator && m.Name == memberName);
if (opType == OperatorType.Implicit || opType == OperatorType.Explicit) {
// conversion operator
foreach (var method in methods) {
if (ParameterListComparer.Instance.Equals(method.Parameters, parameters)) {
if (method.ReturnType.Equals(conversionOperatorReturnType))
return new MemberResolveResult(null, method);
}
}
return new MemberResolveResult(null, methods.FirstOrDefault());
} else {
// not a conversion operator
return FindByParameters(methods, parameters);
}
} else {
throw new NotSupportedException(); // unknown entity type
}
}
IParameter ResolveXmlDocParameter(ParameterDeclaration p)
{
var lrr = Resolve(p) as LocalResolveResult;
if (lrr != null && lrr.IsParameter)
return (IParameter)lrr.Variable;
else
return new DefaultParameter(SpecialType.UnknownType, string.Empty);
}
ResolveResult FindByParameters(IEnumerable<IParameterizedMember> methods, IList<IParameter> parameters)
{
foreach (var method in methods) {
if (ParameterListComparer.Instance.Equals(method.Parameters, parameters))
return new MemberResolveResult(null, method);
}
return new MemberResolveResult(null, methods.FirstOrDefault());
}
#endregion
}

19
ICSharpCode.NRefactory.CSharp/TypeSystem/CSharpDocumentationComment.cs

@ -17,8 +17,10 @@ @@ -17,8 +17,10 @@
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.TypeSystem
@ -38,6 +40,23 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem @@ -38,6 +40,23 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem
// resolve ID string
return base.ResolveCref(cref);
}
var documentationReference = new CSharpParser().ParseDocumentationReference(cref);
var csharpContext = context as CSharpTypeResolveContext;
CSharpResolver resolver;
if (csharpContext != null) {
resolver = new CSharpResolver(csharpContext);
} else {
resolver = new CSharpResolver(context.Compilation);
}
var astResolver = new CSharpAstResolver(resolver, documentationReference);
var rr = astResolver.Resolve(documentationReference);
MemberResolveResult mrr = rr as MemberResolveResult;
if (mrr != null)
return mrr.Member;
TypeResolveResult trr = rr as TypeResolveResult;
if (trr != null)
return trr.Type.GetDefinition();
return null;
}
}

38
ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs

@ -17,9 +17,9 @@ @@ -17,9 +17,9 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.IO;
using System.Linq;
using System.Threading;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
@ -289,5 +289,41 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -289,5 +289,41 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(case2.Statements.First()));
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(@switch));
}
[Test]
public void ConditionalExpression1()
{
string code = "int a; int b = X ? (a = 1) : 0;";
var block = new BlockStatement();
block.Statements.AddRange(new CSharpParser().ParseStatements(new StringReader(code)));
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(block);
da.Analyze("a");
Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(block));
}
[Test]
public void ConditionalExpression2()
{
string code = "int a; int b = X ? (a = 1) : (a = 2);";
var block = new BlockStatement();
block.Statements.AddRange(new CSharpParser().ParseStatements(new StringReader(code)));
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(block);
da.Analyze("a");
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(block));
}
[Test]
public void ConditionalExpression3()
{
string code = "int a; int b = true ? (a = 1) : 0;";
var block = new BlockStatement();
block.Statements.AddRange(new CSharpParser().ParseStatements(new StringReader(code)));
DefiniteAssignmentAnalysis da = CreateDefiniteAssignmentAnalysis(block);
da.Analyze("a");
Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(block));
}
}
}

15
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Linq;
using System.Text;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
@ -234,5 +235,19 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -234,5 +235,19 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
Assert.AreEqual(new TextLocation(1, 2), pe.EndLocation);
Assert.AreEqual("0", pe.LiteralValue);
}
[Test]
[Ignore("Mono parser crash")]
public void LargeVerbatimString()
{
StringBuilder b = new StringBuilder();
for (int i = 0; i < 10000; i++) {
b.Append(i.ToString());
b.Append("\r\n");
}
string literal = b.ToString();
var pe = ParseUtilCSharp.ParseExpression<PrimitiveExpression>("@\"" + literal + "\"");
Assert.AreEqual(literal, pe.Value);
}
}
}

14
ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs

@ -205,5 +205,19 @@ public class Form1 { @@ -205,5 +205,19 @@ public class Form1 {
typeof(NamespaceDeclaration)
}, cu.Children.Select(c => c.GetType()).ToArray());
}
[Ignore("Fixme!")]
[Test]
public void AssemblyAttributeBeforeClass()
{
var cu = new CSharpParser().Parse(new StringReader("using System; [assembly: Attr] class X {}"), "code.cs");
Assert.AreEqual(
new Type[] {
typeof(UsingDeclaration),
typeof(AttributeSection),
typeof(TypeDeclaration)
}, cu.Children.Select(c => c.GetType()).ToArray());
Assert.That(((TypeDeclaration)cu.LastChild).Attributes, Is.Empty);
}
}
}

113
ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/PreprocessorDirectiveTests.cs

@ -132,5 +132,118 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope @@ -132,5 +132,118 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope
Assert.AreEqual(PreProcessorDirectiveType.Pragma, ppd.Type);
Assert.AreEqual("warning disable 809", ppd.Argument);
}
const string elifProgram = @"
#if AAA
class A { }
#elif BBB
class B { }
#endif";
[Test]
[Ignore("parser bug (missing comment node)")]
public void ElifBothFalse()
{
CSharpParser parser = new CSharpParser();
var cu = parser.Parse(elifProgram, "elif.cs");
Assert.IsFalse(parser.HasErrors);
Assert.AreEqual(new Role[] {
Roles.PreProcessorDirective,
Roles.Comment,
Roles.PreProcessorDirective,
Roles.Comment,
Roles.PreProcessorDirective
}, cu.Children.Select(c => c.Role).ToArray());
var aaa = cu.GetChildrenByRole(Roles.PreProcessorDirective).ElementAt(0);
Assert.IsFalse(aaa.Take);
Assert.AreEqual(PreProcessorDirectiveType.If, aaa.Type);
Assert.AreEqual("AAA", aaa.Argument);
var bbb = cu.GetChildrenByRole(Roles.PreProcessorDirective).ElementAt(1);
Assert.IsFalse(bbb.Take);
Assert.AreEqual(PreProcessorDirectiveType.Elif, bbb.Type);
Assert.AreEqual("BBB", bbb.Argument);
}
[Test]
[Ignore("parser bug (bbb.Take is true, should be false)")]
public void ElifBothTrue()
{
CSharpParser parser = new CSharpParser();
parser.CompilerSettings.ConditionalSymbols.Add("AAA");
var cu = parser.Parse(elifProgram, "elif.cs");
Assert.IsFalse(parser.HasErrors);
Assert.AreEqual(new Role[] {
Roles.PreProcessorDirective,
NamespaceDeclaration.MemberRole,
Roles.PreProcessorDirective,
Roles.Comment,
Roles.PreProcessorDirective
}, cu.Children.Select(c => c.Role).ToArray());
var aaa = cu.GetChildrenByRole(Roles.PreProcessorDirective).ElementAt(0);
Assert.IsTrue(aaa.Take);
Assert.AreEqual(PreProcessorDirectiveType.If, aaa.Type);
Assert.AreEqual("AAA", aaa.Argument);
var bbb = cu.GetChildrenByRole(Roles.PreProcessorDirective).ElementAt(1);
Assert.IsFalse(bbb.Take);
Assert.AreEqual(PreProcessorDirectiveType.Elif, bbb.Type);
Assert.AreEqual("BBB", bbb.Argument);
}
[Test]
[Ignore("parser bug (bbb.Take is true, should be false)")]
public void ElifFirstTaken()
{
CSharpParser parser = new CSharpParser();
parser.CompilerSettings.ConditionalSymbols.Add("AAA");
var cu = parser.Parse(elifProgram, "elif.cs");
Assert.IsFalse(parser.HasErrors);
Assert.AreEqual(new Role[] {
Roles.PreProcessorDirective,
NamespaceDeclaration.MemberRole,
Roles.PreProcessorDirective,
Roles.Comment,
Roles.PreProcessorDirective
}, cu.Children.Select(c => c.Role).ToArray());
var aaa = cu.GetChildrenByRole(Roles.PreProcessorDirective).ElementAt(0);
Assert.IsTrue(aaa.Take);
Assert.AreEqual(PreProcessorDirectiveType.If, aaa.Type);
Assert.AreEqual("AAA", aaa.Argument);
var bbb = cu.GetChildrenByRole(Roles.PreProcessorDirective).ElementAt(1);
Assert.IsFalse(bbb.Take);
Assert.AreEqual(PreProcessorDirectiveType.Elif, bbb.Type);
Assert.AreEqual("BBB", bbb.Argument);
}
[Test]
public void ElifSecondTaken()
{
CSharpParser parser = new CSharpParser();
parser.CompilerSettings.ConditionalSymbols.Add("BBB");
var cu = parser.Parse(elifProgram, "elif.cs");
Assert.IsFalse(parser.HasErrors);
Assert.AreEqual(new Role[] {
Roles.PreProcessorDirective,
Roles.Comment,
Roles.PreProcessorDirective,
NamespaceDeclaration.MemberRole,
Roles.PreProcessorDirective
}, cu.Children.Select(c => c.Role).ToArray());
var aaa = cu.GetChildrenByRole(Roles.PreProcessorDirective).ElementAt(0);
Assert.IsFalse(aaa.Take);
Assert.AreEqual(PreProcessorDirectiveType.If, aaa.Type);
Assert.AreEqual("AAA", aaa.Argument);
var bbb = cu.GetChildrenByRole(Roles.PreProcessorDirective).ElementAt(1);
Assert.IsTrue(bbb.Take);
Assert.AreEqual(PreProcessorDirectiveType.Elif, bbb.Type);
Assert.AreEqual("BBB", bbb.Argument);
}
}
}

27
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs

@ -524,7 +524,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -524,7 +524,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
[Test]
public void ExplicitUserDefinedConversion() {
public void ExplicitUserDefinedConversion()
{
var rr = Resolve<ConversionResolveResult>(@"
class C1 {}
class C2 {
@ -541,5 +542,29 @@ class C { @@ -541,5 +542,29 @@ class C {
Assert.IsTrue(rr.Conversion.IsUserDefined);
Assert.AreEqual("op_Explicit", rr.Conversion.Method.Name);
}
[Test]
public void ImplicitTypeParameterConversion()
{
string program = @"using System;
class Test {
public void M<T, U>(T t) where T : U {
U u = $t$;
}
}";
Assert.AreEqual(C.BoxingConversion, GetConversion(program));
}
[Test]
public void InvalidImplicitTypeParameterConversion()
{
string program = @"using System;
class Test {
public void M<T, U>(T t) where U : T {
U u = $t$;
}
}";
Assert.AreEqual(C.None, GetConversion(program));
}
}
}

612
ICSharpCode.NRefactory.Tests/CSharp/Resolver/DynamicTests.cs

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
@ -37,6 +38,7 @@ class TestClass { @@ -37,6 +38,7 @@ class TestClass {
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
Assert.That(rr.Target, Is.InstanceOf<DynamicMemberResolveResult>());
var dynamicMember = (DynamicMemberResolveResult)rr.Target;
Assert.That(dynamicMember.Target is LocalResolveResult && ((LocalResolveResult)dynamicMember.Target).Variable.Name == "obj");
@ -61,6 +63,7 @@ class TestClass { @@ -61,6 +63,7 @@ class TestClass {
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
Assert.That(rr.Target, Is.InstanceOf<DynamicMemberResolveResult>());
var dynamicMember = (DynamicMemberResolveResult)rr.Target;
Assert.That(dynamicMember.Target is LocalResolveResult && ((LocalResolveResult)dynamicMember.Target).Variable.Name == "obj");
@ -86,12 +89,14 @@ class TestClass { @@ -86,12 +89,14 @@ class TestClass {
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
Assert.That(rr.Target, Is.InstanceOf<DynamicInvocationResolveResult>());
var innerInvocation = (DynamicInvocationResolveResult)rr.Target;
Assert.That(innerInvocation.Target, Is.InstanceOf<DynamicMemberResolveResult>());
var dynamicMember = (DynamicMemberResolveResult)innerInvocation.Target;
Assert.That(dynamicMember.Target is LocalResolveResult && ((LocalResolveResult)dynamicMember.Target).Variable.Name == "obj");
Assert.That(dynamicMember.Member, Is.EqualTo("SomeMethod"));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
Assert.That(innerInvocation.Arguments.Count, Is.EqualTo(1));
Assert.That(innerInvocation.Arguments[0].Name, Is.Null);
Assert.That(innerInvocation.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)innerInvocation.Arguments[0].Value).Variable.Name == "a");
@ -99,5 +104,612 @@ class TestClass { @@ -99,5 +104,612 @@ class TestClass {
Assert.That(rr.Arguments[0].Name, Is.Null);
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "b");
}
[Test]
public void InvocationWithDynamicArgumentWithOneApplicableMethod() {
string program = @"using System;
class TestClass {
public void SomeMethod(int a) {}
public void SomeMethod(int a, string b) {}
void F() {
dynamic obj = null;
var x = $this.SomeMethod(obj)$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo("SomeMethod"));
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Conversion.IsImplicit, Is.True);
Assert.That(cr.Conversion.IsDynamicConversion, Is.True);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWhenBothAnOwnAndABaseMethodAreApplicable() {
string program = @"using System;
class TestBase {
public void SomeMethod(int a) {}
}
class TestClass : TestBase {
public void SomeMethod(string a) {}
public void SomeMethod(string a, int b) {}
void F() {
dynamic obj = null;
var x = $this.SomeMethod(obj)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.InstanceOf<ThisResolveResult>());
Assert.That(mg.MethodName, Is.EqualTo("SomeMethod"));
Assert.That(mg.Methods.Count(), Is.EqualTo(2));
Assert.That(mg.Methods.Any(m => m.Parameters.Count == 1 && m.DeclaringType.Name == "TestBase" && m.Name == "SomeMethod" && m.Parameters[0].Type.Name == "Int32"));
Assert.That(mg.Methods.Any(m => m.Parameters.Count == 1 && m.DeclaringType.Name == "TestClass" && m.Name == "SomeMethod" && m.Parameters[0].Type.Name == "String"));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "obj");
}
[Test, Ignore("Fails")]
public void InvocationWithDynamicArgumentWhenABaseMethodIsShadowed() {
string program = @"using System;
class TestBase {
public void SomeMethod(int a) {}
}
class TestClass : TestBase {
public void SomeMethod(int a) {}
public void SomeMethod(string a, int b) {}
void F() {
dynamic obj = null;
var x = $this.SomeMethod(obj)$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo("SomeMethod"));
Assert.That(rr.Member.DeclaringType.Name, Is.EqualTo("TestClass"));
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Conversion.IsImplicit, Is.True);
Assert.That(cr.Conversion.IsDynamicConversion, Is.True);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWithTwoApplicableMethods() {
string program = @"using System;
class TestClass {
public void SomeMethod(int a) {}
public void SomeMethod(string a) {}
public void SomeMethod(int a, string b) {}
void F() {
dynamic obj = null;
var x = $SomeMethod(obj)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.InstanceOf<ThisResolveResult>());
Assert.That(mg.MethodName, Is.EqualTo("SomeMethod"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 1));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == "SomeMethod" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWithTwoApplicableStaticMethods() {
string program = @"using System;
class TestClass {
public static void SomeMethod(int a) {}
public static void SomeMethod(string a) {}
public static void SomeMethod(int a, string b) {}
void F() {
dynamic obj = null;
var x = $SomeMethod(obj)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.InstanceOf<TypeResolveResult>());
Assert.That(mg.MethodName, Is.EqualTo("SomeMethod"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 1));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == "SomeMethod" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWithApplicableStaticAndNonStaticMethodsFavorTheNonStaticOne() {
string program = @"using System;
class TestClass {
public static void SomeMethod(int a) {}
public void SomeMethod(string a) {}
public static void SomeMethod(int a, string b) {}
void F() {
dynamic obj = null;
var x = $SomeMethod(obj)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.InstanceOf<ThisResolveResult>());
Assert.That(mg.MethodName, Is.EqualTo("SomeMethod"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 1));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == "SomeMethod" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "obj");
}
[Test]
public void InvocationWithDynamicArgumentWhenTheOnlyApplicableMethodIsAnExtensionMethod() {
string program = @"using System;
static class OtherClass {
public void SomeMethod(this TestClass x, int a) {}
public void SomeMethod(this TestClass x, string a) {}
public void SomeMethod(this TestClass x, int a, string b) {}
}
class TestClass {
void F() {
dynamic obj = null;
var x = $this.SomeMethod(obj)$;
}
}";
var rr = Resolve(program);
Assert.That(rr.IsError, Is.True);
}
[Test]
public void InvocationWithDynamicArgumentWithTwoApplicableMethodsAndNamedArguments() {
string program = @"using System;
class TestClass {
public void SomeMethod(int a, int i) {}
public void SomeMethod(string a, int i) {}
public void SomeMethod(int a, string b, int i) {}
void F() {
dynamic obj = null;
int idx = 0;
var x = $this.SomeMethod(a: obj, i: idx)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Invocation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.InstanceOf<ThisResolveResult>());
Assert.That(mg.MethodName, Is.EqualTo("SomeMethod"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 2) && mg.Methods.All(m => m.Parameters[1].Type.Name == "Int32"));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == "SomeMethod" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0].Name, Is.EqualTo("a"));
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "obj");
Assert.That(rr.Arguments[1].Name, Is.EqualTo("i"));
Assert.That(rr.Arguments[1].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[1].Value).Variable.Name == "idx");
}
[Test]
public void IndexingDynamicObjectWithUnnamedArguments() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
int a = 0, b = 0;
object o = $obj[a]$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Indexing));
Assert.That(rr.Target is LocalResolveResult && ((LocalResolveResult)rr.Target).Variable.Name == "obj");
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0].Name, Is.Null);
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "a");
}
[Test]
public void IndexingDynamicObjectWithNamedArguments() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
int a = 0, b = 0;
$obj[arg1: a, arg2: b]$ = 1;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Indexing));
Assert.That(rr.Target is LocalResolveResult && ((LocalResolveResult)rr.Target).Variable.Name == "obj");
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0].Name, Is.EqualTo("arg1"));
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "a");
Assert.That(rr.Arguments[1].Name, Is.EqualTo("arg2"));
Assert.That(rr.Arguments[1].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[1].Value).Variable.Name == "b");
}
[Test]
public void IndexingWithDynamicArgumentWithOneApplicableIndexer() {
string program = @"using System;
class TestClass {
public int this[int a] { get { return 0; } }
public int this[int a, string b] { get { return 0; } }
void F() {
dynamic obj = null;
var x = $this[obj]$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo("Item"));
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Conversion.IsImplicit, Is.True);
Assert.That(cr.Conversion.IsDynamicConversion, Is.True);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void IndexingWithDynamicArgumentWithTwoApplicableIndexersAndUnnamedArguments() {
string program = @"using System;
class TestClass {
public int this[int a] { get { return 0; } }
public int this[string a] { get { return 0; } }
void F() {
dynamic obj = null;
var x = $this[obj]$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Indexing));
Assert.That(rr.Target, Is.InstanceOf<ThisResolveResult>());
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0].Name, Is.Null);
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "obj");
}
[Test]
public void IndexingWithDynamicArgumentWithAnApplicableBaseIndexer() {
string program = @"using System;
class TestBase {
public int this[int a] { get { return 0; } }
}
class TestClass : TestBase {
public int this[string a] { get { return 0; } }
public int this[string a, int b] { get { return 0; } }
void F() {
dynamic obj = null;
var x = $this[obj]$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Indexing));
Assert.That(rr.Target, Is.InstanceOf<ThisResolveResult>());
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0].Name, Is.Null);
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "obj");
}
[Test, Ignore("Fails")]
public void IndexingWithDynamicArgumentWithTheOnlyApplicableIndexerShadowingABaseIndexer() {
string program = @"using System;
class TestBase {
public int this[int a] { get { return 0; } }
}
class TestClass : TestBase {
public new int this[int a] { get { return 0; } }
public int this[int a, string b] { get { return 0; } }
void F() {
dynamic obj = null;
var x = $this[obj]$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo("Item"));
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Conversion.IsImplicit, Is.True);
Assert.That(cr.Conversion.IsDynamicConversion, Is.True);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void IndexingWithDynamicArgumentWithTwoApplicableIndexersAndNamedArguments() {
string program = @"using System;
class TestClass {
public int this[int a, int i] { get { return 0; } }
public int this[string a, int i] { get { return 0; } }
void F() {
dynamic obj = null;
int idx = 0;
var x = $this[a: obj, i: idx]$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.Indexing));
Assert.That(rr.Target, Is.InstanceOf<ThisResolveResult>());
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0].Name, Is.EqualTo("a"));
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "obj");
Assert.That(rr.Arguments[1].Name, Is.EqualTo("i"));
Assert.That(rr.Arguments[1].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[1].Value).Variable.Name == "idx");
}
[Test]
public void ConstructingObjectWithDynamicArgumentWithOneApplicableConstructor() {
string program = @"using System;
class TestClass {
public TestClass(int a) {}
public void TestClass(int a, string b) {}
void F() {
dynamic obj = null;
var x = $new TestClass(obj)$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo(".ctor"));
Assert.That(rr.TargetResult, Is.Null);
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(1));
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Input is LocalResolveResult && ((LocalResolveResult)cr.Input).Variable.Name == "obj");
}
[Test]
public void ConstructingObjectWithDynamicArgumentWithTwoApplicableConstructors() {
string program = @"using System;
class TestClass {
public TestClass(int a, int b) {}
public TestClass(string a, int b) {}
public void TestClass(int a, string b) {}
void F() {
dynamic obj = null;
int i = 0;
var x = $new TestClass(obj, i)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.ObjectCreation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.Null);
Assert.That(mg.MethodName, Is.EqualTo(".ctor"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 2 && m.Parameters[1].Type.Name == "Int32"));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == ".ctor" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "obj");
Assert.That(rr.Arguments[1].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[1].Value).Variable.Name == "i");
}
[Test]
public void ConstructingObjectWithDynamicArgumentWithTwoApplicableConstructorsAndNamedArguments() {
string program = @"using System;
class TestClass {
public TestClass(int arg1, int arg2) {}
public TestClass(string arg1, int arg2) {}
public void TestClass(int a) {}
void F() {
dynamic obj = null;
int i = 0;
var x = $new TestClass(arg1: obj, arg2: i)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.ObjectCreation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.Null);
Assert.That(mg.MethodName, Is.EqualTo(".ctor"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 2 && m.Parameters[1].Type.Name == "Int32"));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == ".ctor" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0].Name, Is.EqualTo("arg1"));
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "obj");
Assert.That(rr.Arguments[1].Name, Is.EqualTo("arg2"));
Assert.That(rr.Arguments[1].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[1].Value).Variable.Name == "i");
}
[Test]
public void ConstructingObjectWithDynamicArgumentWithTwoApplicableConstructorsAndInitializerStatements() {
string program = @"using System;
class TestClass {
public TestClass(int a, int b) {}
public TestClass(string a, int b) {}
public int A { get; set; }
void F() {
dynamic obj = null;
int i = 0;
int j = 0;
var x = $new TestClass(obj, i) { A = j }$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.ObjectCreation));
Assert.That(rr.InitializerStatements.Count, Is.EqualTo(1));
var or = rr.InitializerStatements[0] as OperatorResolveResult;
Assert.That(or, Is.Not.Null);
Assert.That(or.OperatorType, Is.EqualTo(ExpressionType.Assign));
var mrr = or.Operands[0] as MemberResolveResult;
Assert.That(mrr, Is.Not.Null);
Assert.That(mrr.TargetResult, Is.InstanceOf<InitializedObjectResolveResult>());
Assert.That(mrr.Member.Name, Is.EqualTo("A"));
Assert.That(or.Operands[1], Is.InstanceOf<LocalResolveResult>());
Assert.That(((LocalResolveResult)or.Operands[1]).Variable.Name, Is.EqualTo("j"));
}
[Test]
public void InitializingBaseWithDynamicArgumentAndOneApplicableConstructor() {
string program = @"using System;
class TestBase {
public TestBase(int a, int b) {}
public TestBase(string a) {}
}
class TestClass : TestBase {
private static dynamic d;
private static int i;
public TestClass() : $base(d, i)$ {}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo(".ctor"));
Assert.That(rr.TargetResult, Is.Null);
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(2));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Member.DeclaringType.Name, Is.EqualTo("TestBase"));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Input is MemberResolveResult && ((MemberResolveResult)cr.Input).Member.Name == "d");
Assert.That(rr.Arguments[1] is MemberResolveResult && ((MemberResolveResult)rr.Arguments[1]).Member.Name == "i");
}
[Test]
public void InitializingBaseWithDynamicArgumentAndTwoApplicableConstructors() {
string program = @"using System;
class TestBase {
public TestBase(int a, int b) {}
public TestBase(string a, int b) {}
public TestBase(string a) {}
}
class TestClass : TestBase {
private static dynamic d;
private static int i;
public TestClass() : $base(d, i)$ {}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.ObjectCreation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.Null);
Assert.That(mg.MethodName, Is.EqualTo(".ctor"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 2 && m.Parameters[1].Type.Name == "Int32"));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == ".ctor" && m.DeclaringType.Name == "TestBase"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0].Value is MemberResolveResult && ((MemberResolveResult)rr.Arguments[0].Value).Member.Name == "d");
Assert.That(rr.Arguments[1].Value is MemberResolveResult && ((MemberResolveResult)rr.Arguments[1].Value).Member.Name == "i");
}
[Test]
public void ConstructorChainingWithDynamicArgumentAndOneApplicableConstructor() {
string program = @"using System;
class TestClass {
private static dynamic d;
private static int i;
public TestClass(int a, int b) {}
public TestClass(string a) {}
public TestClass() : $this(d, i)$ {}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.That(rr.Member.Name, Is.EqualTo(".ctor"));
Assert.That(rr.TargetResult, Is.Null);
Assert.That(((IParameterizedMember)rr.Member).Parameters.Count, Is.EqualTo(2));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Member.DeclaringType.Name, Is.EqualTo("TestClass"));
var cr = rr.Arguments[0] as ConversionResolveResult;
Assert.That(cr, Is.Not.Null);
Assert.That(cr.Input is MemberResolveResult && ((MemberResolveResult)cr.Input).Member.Name == "d");
Assert.That(rr.Arguments[1] is MemberResolveResult && ((MemberResolveResult)rr.Arguments[1]).Member.Name == "i");
}
[Test]
public void ConstructorChainingWithDynamicArgumentAndTwoApplicableConstructors() {
string program = @"using System;
class TestBase {
}
class TestClass {
private static dynamic d;
private static int i;
public TestClass(int a, int b) {}
public TestClass(string a, int b) {}
public TestClass(string a) {}
public TestClass() : $this(d, i)$ {}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.InvocationType, Is.EqualTo(DynamicInvocationType.ObjectCreation));
var mg = rr.Target as MethodGroupResolveResult;
Assert.That(mg, Is.Not.Null, "Expected a MethodGroup");
Assert.That(mg.TargetResult, Is.Null);
Assert.That(mg.MethodName, Is.EqualTo(".ctor"));
Assert.That(mg.Methods.All(m => m.Parameters.Count == 2 && m.Parameters[1].Type.Name == "Int32"));
Assert.That(mg.Methods.Select(m => m.Parameters[0].Type.Name), Is.EquivalentTo(new[] { "Int32", "String" }));
Assert.That(mg.Methods.All(m => m.Name == ".ctor" && m.DeclaringType.Name == "TestClass"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0].Value is MemberResolveResult && ((MemberResolveResult)rr.Arguments[0].Value).Member.Name == "d");
Assert.That(rr.Arguments[1].Value is MemberResolveResult && ((MemberResolveResult)rr.Arguments[1].Value).Member.Name == "i");
}
}
}

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

@ -275,5 +275,46 @@ class Test<T> where T : new() { @@ -275,5 +275,46 @@ class Test<T> where T : new() {
Assert.AreEqual(TypeKind.TypeParameter, rr.Type.Kind);
Assert.AreEqual(TypeKind.TypeParameter, rr.Member.DeclaringType.Kind);
}
[Test]
public void CreateDelegateFromMethodGroup()
{
string program = @"using System;
delegate void D(int i);
class C {
void M(int y) {
D d = $new D(M)$;
}
}";
var rr = Resolve<ConversionResolveResult>(program);
Assert.IsFalse(rr.IsError);
Assert.IsTrue(rr.Conversion.IsIdentityConversion);
var rr2 = (ConversionResolveResult)rr.Input;
Assert.IsFalse(rr2.IsError);
Assert.IsTrue(rr2.Conversion.IsMethodGroupConversion);
Assert.AreEqual("C.M", rr2.Conversion.Method.FullName);
var mgrr = (MethodGroupResolveResult)rr2.Input;
Assert.IsInstanceOf<ThisResolveResult>(mgrr.TargetResult);
}
[Test]
public void CreateDelegateFromDelegate()
{
string program = @"using System;
delegate void D1(int i);
delegate void D2(int i);
class C {
void M(D1 d1) {
D2 d2 = $new D2(d1)$;
}
}";
var rr = Resolve<ConversionResolveResult>(program);
Assert.IsFalse(rr.IsError);
Assert.IsTrue(rr.Conversion.IsMethodGroupConversion);
Assert.AreEqual("D1.Invoke", rr.Conversion.Method.FullName);
var mgrr = (MethodGroupResolveResult)rr.Input;
Assert.IsInstanceOf<LocalResolveResult>(mgrr.TargetResult);
}
}
}

21
ICSharpCode.NRefactory.Tests/Documentation/CSharpCrefLookupTests.cs

@ -26,7 +26,6 @@ using NUnit.Framework; @@ -26,7 +26,6 @@ using NUnit.Framework;
namespace ICSharpCode.NRefactory.Documentation
{
[TestFixture]
[Ignore("Cref parsing not yet implemented")]
public class CSharpCrefLookupTests
{
IEntity Lookup(string cref)
@ -58,7 +57,7 @@ class Impl<T> : IGeneric<List<string>[,], T> { @@ -58,7 +57,7 @@ class Impl<T> : IGeneric<List<string>[,], T> {
var pc = new CSharpProjectContent().AddAssemblyReferences(new[] { CecilLoaderTests.Mscorlib });
var cu = new CSharpParser().Parse(new StringReader(program), "program.cs");
var compilation = pc.UpdateProjectContent(null, cu.ToTypeSystem()).CreateCompilation();
var typeDefinition = compilation.MainAssembly.TopLevelTypeDefinitions.Single();
var typeDefinition = compilation.MainAssembly.TopLevelTypeDefinitions.First();
IEntity entity = typeDefinition.Documentation.ResolveCref(cref);
Assert.IsNotNull(entity, "ResolveCref() returned null.");
return entity;
@ -109,7 +108,7 @@ class Impl<T> : IGeneric<List<string>[,], T> { @@ -109,7 +108,7 @@ class Impl<T> : IGeneric<List<string>[,], T> {
[Test]
public void M()
{
Assert.AreEqual("M:Test.M(System.String[0:,0:])",
Assert.AreEqual("M:Test.M(System.Int32)",
IdStringProvider.GetIdString(Lookup("M")));
}
@ -141,19 +140,25 @@ class Impl<T> : IGeneric<List<string>[,], T> { @@ -141,19 +140,25 @@ class Impl<T> : IGeneric<List<string>[,], T> {
[Test]
public void MethodInGenericInterface()
{
Assert.AreEqual("M:XmlDocTest.IGeneric`2.Test``1(``0[0:,0:]@)",
Assert.AreEqual("M:IGeneric`2.Test``1(``0[0:,0:]@)",
IdStringProvider.GetIdString(Lookup("IGeneric{X, Y}.Test")));
Assert.AreEqual("M:XmlDocTest.IGeneric`2.Test``1(``0[0:,0:]@)",
Assert.AreEqual("M:IGeneric`2.Test``1(``0[0:,0:]@)",
IdStringProvider.GetIdString(Lookup("IGeneric{X, Y}.Test{Z}")));
Assert.AreEqual("M:XmlDocTest.IGeneric`2.Test``1(``0[0:,0:]@)",
Assert.AreEqual("M:IGeneric`2.Test``1(``0[0:,0:]@)",
IdStringProvider.GetIdString(Lookup("IGeneric{X, Y}.Test{Z}(ref Z[,])")));
}
[Test]
public void Indexer()
[Ignore("Fails due to mcs parser bug (see CSharpCrefParserTests.This)")]
public void IndexerWithoutDeclaringType()
{
Assert.AreEqual("P:Test.Item(System.Int32)",
IdStringProvider.GetIdString(Lookup("this")));
}
[Test]
public void IndexerWithDeclaringType()
{
Assert.AreEqual("P:Test.Item(System.Int32)",
IdStringProvider.GetIdString(Lookup("Test.this")));
Assert.AreEqual("P:Test.Item(System.Int32)",
@ -161,6 +166,7 @@ class Impl<T> : IGeneric<List<string>[,], T> { @@ -161,6 +166,7 @@ class Impl<T> : IGeneric<List<string>[,], T> {
}
[Test]
[Ignore("mcs bug, see CSharpCrefParserTests.OperatorPlusWithDeclaringType")]
public void OperatorPlus()
{
Assert.AreEqual("M:Test.op_Addition(Test,System.Int32)",
@ -172,6 +178,7 @@ class Impl<T> : IGeneric<List<string>[,], T> { @@ -172,6 +178,7 @@ class Impl<T> : IGeneric<List<string>[,], T> {
}
[Test]
[Ignore("mcs bug, see CSharpCrefParserTests.OperatorPlusWithDeclaringType")]
public void ImplicitOperator()
{
Assert.AreEqual("M:Test.op_Implicit(Test)~System.Int32",

20
ICSharpCode.NRefactory.Tests/Documentation/CSharpCrefParserTests.cs

@ -25,7 +25,6 @@ using NUnit.Framework; @@ -25,7 +25,6 @@ using NUnit.Framework;
namespace ICSharpCode.NRefactory.Documentation
{
[TestFixture]
[Ignore("Cref parsing not yet implemented")]
public class CSharpCrefParserTests
{
[Test]
@ -39,6 +38,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -39,6 +38,7 @@ namespace ICSharpCode.NRefactory.Documentation
}
[Test]
[Ignore("mcs bug")]
public void This()
{
ParseUtilCSharp.AssertDocumentationReference(
@ -49,6 +49,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -49,6 +49,7 @@ namespace ICSharpCode.NRefactory.Documentation
}
[Test]
[Ignore("mcs bug (Unexpected symbol `this', expecting `explicit', `implicit', `operator', or `type')")]
public void ThisWithParameter()
{
ParseUtilCSharp.AssertDocumentationReference(
@ -115,6 +116,21 @@ namespace ICSharpCode.NRefactory.Documentation @@ -115,6 +116,21 @@ namespace ICSharpCode.NRefactory.Documentation
});
}
[Test]
public void IntParse()
{
ParseUtilCSharp.AssertDocumentationReference(
"int.Parse(string)",
new DocumentationReference {
DeclaringType = new PrimitiveType("int"),
MemberName = "Parse",
HasParameterList = true,
Parameters = {
new ParameterDeclaration { Type = new PrimitiveType("string") }
}
});
}
[Test]
public void Generic()
{
@ -201,6 +217,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -201,6 +217,7 @@ namespace ICSharpCode.NRefactory.Documentation
}
[Test]
[Ignore("mcs bug (Unexpected symbol `operator', expecting `identifier' or `this')")]
public void OperatorPlusWithDeclaringType()
{
ParseUtilCSharp.AssertDocumentationReference(
@ -256,6 +273,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -256,6 +273,7 @@ namespace ICSharpCode.NRefactory.Documentation
}
[Test]
[Ignore("mcs bug (Unexpected symbol `explicit', expecting `identifier' or `this')")]
public void ExplicitOperatorWithParameterListAndDeclaringType()
{
ParseUtilCSharp.AssertDocumentationReference(

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

@ -21,6 +21,7 @@ using System.Collections; @@ -21,6 +21,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
@ -31,12 +32,43 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -31,12 +32,43 @@ namespace ICSharpCode.NRefactory.TypeSystem
[TestFixture]
public class GetAllBaseTypesTest
{
const string corlib = @"
namespace System {
class Object {}
class ValueType {}
class String : System.Collections.Generic.IEnumerable<char>, IComparable<string> {}
class Array : System.Collections.IList, ICloneable {}
interface ICloneable {}
interface IComparable<in T> {}
struct Int32 {}
struct Char {}
}
namespace System.Collections {
interface IEnumerable {}
interface ICollection : IEnumerable {}
interface IList : ICollection {}
interface IDictionary : ICollection {}
}
namespace System.Collections.Generic {
interface IEnumerable<out T> : IEnumerable {}
interface ICollection<T> : IEnumerable<T> {}
interface IList<T> : ICollection<T> {}
interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>> {}
class List<T> : IList, IList<T> {}
class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary {}
struct KeyValuePair<TKey, TValue> {}
}
";
ICompilation compilation;
[SetUp]
public void SetUp()
{
compilation = new SimpleCompilation(CecilLoaderTests.Mscorlib);
var parsedFile = new CSharpParser().Parse(corlib, "corlib.cs").ToTypeSystem();
compilation = new CSharpProjectContent().SetAssemblyName("mscorlib").UpdateProjectContent(null, parsedFile).CreateCompilation();
}
IType[] GetAllBaseTypes(Type type)
@ -46,7 +78,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -46,7 +78,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
IType[] GetTypes(params Type[] types)
{
return types.Select(t => compilation.FindType(t)).OrderBy(t => t.ReflectionName).ToArray();;
return types.Select(t => compilation.FindType(t)).OrderBy(t => t.ReflectionName).ToArray();
}
ITypeDefinition Resolve(IUnresolvedTypeDefinition typeDef)
@ -58,24 +90,26 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -58,24 +90,26 @@ namespace ICSharpCode.NRefactory.TypeSystem
public void ObjectBaseTypes()
{
Assert.AreEqual(GetTypes(typeof(object)), GetAllBaseTypes(typeof(object)));
Assert.That(compilation.FindType(KnownTypeCode.Object).DirectBaseTypes, Is.Empty);
}
[Test]
public void StringBaseTypes()
{
Assert.AreEqual(GetTypes(typeof(string), typeof(object), typeof(IComparable), typeof(ICloneable), typeof(IConvertible),
typeof(IComparable<string>), typeof(IEquatable<string>), typeof(IEnumerable<char>), typeof(IEnumerable)),
Assert.AreEqual(GetTypes(typeof(string), typeof(object),
typeof(IComparable<string>), typeof(IEnumerable<char>), typeof(IEnumerable)),
GetAllBaseTypes(typeof(string)));
}
[Test]
[Ignore("Produces different results in .NET 4.5 due to new read-only interfaces")]
public void ArrayOfString()
{
Assert.AreEqual(GetTypes(typeof(string[]), typeof(Array), typeof(object),
typeof(IList), typeof(ICollection), typeof(IEnumerable),
typeof(IList<string>), typeof(ICollection<string>), typeof(IEnumerable<string>),
typeof(IStructuralEquatable), typeof(IStructuralComparable), typeof(ICloneable)),
var expectedTypes = GetTypes(
typeof(string[]), typeof(Array), typeof(object),
typeof(IList), typeof(ICollection), typeof(IEnumerable), typeof(ICloneable),
typeof(IList<string>), typeof(ICollection<string>), typeof(IEnumerable<string>));
Assert.AreEqual(expectedTypes,
GetAllBaseTypes(typeof(string[])));
}
@ -83,8 +117,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -83,8 +117,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
public unsafe void ArrayOfPointers()
{
Assert.AreEqual(GetTypes(typeof(int*[]), typeof(Array), typeof(object),
typeof(IList), typeof(ICollection), typeof(IEnumerable),
typeof(IStructuralEquatable), typeof(IStructuralComparable), typeof(ICloneable)),
typeof(IList), typeof(ICollection), typeof(IEnumerable), typeof(ICloneable)),
GetAllBaseTypes(typeof(int*[])));
}
@ -92,8 +125,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -92,8 +125,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
public void MultidimensionalArrayOfString()
{
Assert.AreEqual(GetTypes(typeof(string[,]), typeof(Array), typeof(object),
typeof(IList), typeof(ICollection), typeof(IEnumerable),
typeof(IStructuralEquatable), typeof(IStructuralComparable), typeof(ICloneable)),
typeof(IList), typeof(ICollection), typeof(IEnumerable), typeof(ICloneable)),
GetAllBaseTypes(typeof(string[,])));
}
@ -175,7 +207,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -175,7 +207,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
[Test]
[Ignore("Produces different results in .NET 4.5 due to new read-only interfaces")]
public void BaseTypesOfListOfString()
{
Assert.AreEqual(
@ -186,7 +217,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -186,7 +217,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
[Test]
[Ignore("Produces different results in .NET 4.5 due to new read-only interfaces")]
public void BaseTypesOfUnboundDictionary()
{
Assert.AreEqual(
@ -198,15 +228,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -198,15 +228,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
typeof(ICollection).FullName,
typeof(IDictionary).FullName,
typeof(IEnumerable).FullName,
typeof(object).FullName,
typeof(IDeserializationCallback).FullName,
typeof(ISerializable).FullName,
typeof(object).FullName
},
GetAllBaseTypes(typeof(Dictionary<,>)).Select(t => t.ReflectionName).ToArray());
GetAllBaseTypes(typeof(Dictionary<,>)).Select(t => t.ReflectionName).OrderBy(n => n).ToArray());
}
[Test]
[Ignore("Produces different results in .NET 4.5 due to new read-only interfaces")]
public void BaseTypeDefinitionsOfListOfString()
{
Assert.AreEqual(
@ -217,12 +244,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -217,12 +244,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
[Test]
[Ignore("Produces different results in .NET 4.5 due to new read-only interfaces")]
public void BaseTypeDefinitionsOfStringArray()
{
Assert.AreEqual(
GetTypes(typeof(Array), typeof(object),
typeof(ICloneable), typeof(IStructuralComparable), typeof(IStructuralEquatable),
GetTypes(typeof(Array), typeof(object), typeof(ICloneable),
typeof(IList), typeof(ICollection), typeof(IEnumerable),
typeof(IEnumerable<>), typeof(ICollection<>), typeof(IList<>)),
compilation.FindType(typeof(string[])).GetAllBaseTypeDefinitions().OrderBy(t => t.ReflectionName).ToArray());

17
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs

@ -44,6 +44,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase @@ -44,6 +44,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
public class ParamsAttribute : Attribute
{
public ParamsAttribute(params object[] x) {}
[Params(Property = new string[] { "a", "b" })]
public string[] Property { get; set; }
}
[Double(1)]
@ -291,4 +294,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase @@ -291,4 +294,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
public class ClassThatImplementsEventExplicitly : IHasEvent {
event EventHandler IHasEvent.Event { add {} remove {} }
}
public interface IShadowTestBase {
void Method();
int this[int i] { get; set; }
int Prop { get; set; }
event EventHandler Evt;
}
public interface IShadowTestDerived : IShadowTestBase {
new void Method();
new int this[int i] { get; set; }
new int Prop { get; set; }
new event EventHandler Evt;
}
}

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

@ -821,6 +821,23 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -821,6 +821,23 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual("Test", rr.Input.ConstantValue);
}
[Test]
public void ParamsAttribute_Property()
{
ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute));
IProperty prop = type.Properties.Single(p => p.Name == "Property");
var attr = prop.Attributes.Single();
Assert.AreEqual(type, attr.AttributeType);
var normalArguments = ((ArrayCreateResolveResult)attr.PositionalArguments.Single()).InitializerElements;
Assert.AreEqual(0, normalArguments.Count);
var namedArg = attr.NamedArguments.Single();
Assert.AreEqual(prop, namedArg.Key);
var arrayElements = ((ArrayCreateResolveResult)namedArg.Value).InitializerElements;
Assert.AreEqual(2, arrayElements.Count);
}
[Test]
public void DoubleAttribute_ImplicitNumericConversion()
{
@ -978,6 +995,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -978,6 +995,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
public void ExplicitIndexerImplementationReturnsTheCorrectMembers() {
ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsIndexersExplicitly));
Assert.That(type.Properties.All(p => p.EntityType == EntityType.Indexer));
Assert.That(type.Properties.All(p => p.ImplementedInterfaceMembers.Count == 1));
Assert.That(type.Properties.All(p => p.Getter.ImplementedInterfaceMembers.Count == 1));
Assert.That(type.Properties.All(p => p.Setter.ImplementedInterfaceMembers.Count == 1));
@ -1094,5 +1112,25 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1094,5 +1112,25 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.That(evt.AddAccessor.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.add_Event" }));
Assert.That(evt.RemoveAccessor.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.remove_Event" }));
}
[Test]
public void MembersDeclaredInDerivedInterfacesDoNotImplementBaseMembers() {
ITypeDefinition type = GetTypeDefinition(typeof(IShadowTestDerived));
var method = type.Methods.Single(m => m.Name == "Method");
var indexer = type.Properties.Single(p => p.IsIndexer);
var prop = type.Properties.Single(p => p.Name == "Prop");
var evt = type.Events.Single(e => e.Name == "Evt");
Assert.That(method.ImplementedInterfaceMembers, Is.Empty);
Assert.That(indexer.ImplementedInterfaceMembers, Is.Empty);
Assert.That(indexer.Getter.ImplementedInterfaceMembers, Is.Empty);
Assert.That(indexer.Setter.ImplementedInterfaceMembers, Is.Empty);
Assert.That(prop.ImplementedInterfaceMembers, Is.Empty);
Assert.That(prop.Getter.ImplementedInterfaceMembers, Is.Empty);
Assert.That(prop.Setter.ImplementedInterfaceMembers, Is.Empty);
Assert.That(evt.ImplementedInterfaceMembers, Is.Empty);
Assert.That(evt.AddAccessor.ImplementedInterfaceMembers, Is.Empty);
Assert.That(evt.RemoveAccessor.ImplementedInterfaceMembers, Is.Empty);
}
}
}

2
ICSharpCode.NRefactory/Properties/GlobalAssemblyInfo.cs

@ -23,4 +23,4 @@ using System.Runtime.InteropServices; @@ -23,4 +23,4 @@ using System.Runtime.InteropServices;
// [AssemblyFileVersion] is the version of the NuGet package,
// should follow http://semver.org/ rules
[assembly: AssemblyFileVersion("5.0.1")]
[assembly: AssemblyFileVersion("5.1.0")]

16
ICSharpCode.NRefactory/Semantics/Conversion.cs

@ -185,6 +185,14 @@ namespace ICSharpCode.NRefactory.Semantics @@ -185,6 +185,14 @@ namespace ICSharpCode.NRefactory.Semantics
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; }
}
@ -365,6 +373,14 @@ namespace ICSharpCode.NRefactory.Semantics @@ -365,6 +373,14 @@ namespace ICSharpCode.NRefactory.Semantics
get { return false; }
}
public virtual bool IsNullLiteralConversion {
get { return false; }
}
public virtual bool IsConstantExpressionConversion {
get { return false; }
}
public virtual bool IsNumericConversion {
get { return false; }
}

13
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -1676,7 +1676,18 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1676,7 +1676,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
bool getterVisible = property.GetMethod != null && IsVisible(property.GetMethod.Attributes);
bool setterVisible = property.SetMethod != null && IsVisible(property.SetMethod.Attributes);
if (getterVisible || setterVisible) {
EntityType type = property.Name == defaultMemberName ? EntityType.Indexer : EntityType.Property;
EntityType type = EntityType.Property;
if (property.HasParameters) {
// Try to detect indexer:
if (property.Name == defaultMemberName) {
type = EntityType.Indexer; // normal indexer
} else if (property.Name.EndsWith(".Item", StringComparison.Ordinal) && (property.GetMethod ?? property.SetMethod).HasOverrides) {
// explicit interface implementation of indexer
type = EntityType.Indexer;
// We can't really tell parameterized properties and indexers apart in this case without
// resolving the interface, so we rely on the "Item" naming convention instead.
}
}
members.Add(ReadProperty(property, td, type));
}
}

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

@ -76,7 +76,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -76,7 +76,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
result.Add(member);
}
return result.ToArray();
} else if (unresolved.IsStatic) {
} else if (unresolved.IsStatic || DeclaringTypeDefinition == null || DeclaringTypeDefinition.Kind == TypeKind.Interface) {
return EmptyList<IMember>.Instance;
} else {
// TODO: implement interface member mappings correctly

4
Packages/ICSharpCode.NRefactory.nuspec

@ -2,9 +2,9 @@ @@ -2,9 +2,9 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>ICSharpCode.NRefactory</id>
<version>5.0.1</version>
<version>5.1.0</version>
<title>NRefactory</title>
<authors>Daniel Grunwald, Mike Krüger</authors>
<authors>Daniel Grunwald, Mike Krüger, Erik Källén</authors>
<owners>Daniel Grunwald</owners>
<licenseUrl>http://www.opensource.org/licenses/mit-license.php</licenseUrl>
<projectUrl>https://github.com/icsharpcode/NRefactory/</projectUrl>

Loading…
Cancel
Save