Browse Source

Implemented disambiguation for identical simple names and type names. (e.g. "public Color Color;")

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
77c7d08b9a
  1. 17
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs
  2. 32
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs
  3. 22
      ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs
  4. 26
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs
  5. 453
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  6. 44
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

17
ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs

@ -18,19 +18,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -18,19 +18,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Assert.AreEqual("System.Runtime", result.NamespaceName);
}
[Test]
[Test, Ignore("Parser produces incorrect position (attribute position doesn't include empty arg list)")]
public void AttributeWithShortName()
{
string program = "using System; [$Obsolete$] class Test {}";
string program = "using System; [$Obsolete$()] class Test {}";
TypeResolveResult result = Resolve<TypeResolveResult>(program);
Assert.AreEqual("System.ObsoleteAttribute", result.Type.FullName);
}
[Test]
[Test, Ignore("Parser produces incorrect position (attribute position doesn't include empty arg list)")]
public void QualifiedAttributeWithShortName()
{
string program = "using System; [$System.Obsolete$] class Test {}";
string program = "using System; [$System.Obsolete$()] class Test {}";
TypeResolveResult result = Resolve<TypeResolveResult>(program);
Assert.AreEqual("System.ObsoleteAttribute", result.Type.FullName);
@ -54,6 +54,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -54,6 +54,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Assert.AreEqual("System.LoaderOptimization", (mrr.Member as IMethod).Parameters[0].Type.Resolve(context).FullName);
}
[Test]
public void AttributeWithoutArgumentListRefersToConstructor()
{
string program = "using System; [$Obsolete$] class Test {}";
MemberResolveResult result = Resolve<MemberResolveResult>(program);
Assert.AreEqual("System.ObsoleteAttribute..ctor", result.Member.FullName);
}
[Test]
public void AttributeArgumentInClassContext1()
{

32
ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs

@ -191,27 +191,45 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -191,27 +191,45 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Assert.AreSame(SharedTypes.UnknownType, result.Type);
}
[Test]
public void PropertyNameAmbiguousWithTypeName()
{
string program = @"class A {
const string propertyNameAmbiguousWithTypeNameProgram = @"class A {
public Color Color { get; set; }
void Method() {
$
}
}
class Color { public static readonly Color Empty = null; }
class Color {
public static readonly Color Empty = null;
public static int M() { }
public int M(int a) { }
}
";
[Test]
public void PropertyNameAmbiguousWithTypeName()
{
string program = propertyNameAmbiguousWithTypeNameProgram;
TypeResolveResult trr = Resolve<TypeResolveResult>(program.Replace("$", "$Color$ c;"));
Assert.AreEqual("Color", trr.Type.Name);
MemberResolveResult mrr = Resolve<MemberResolveResult>(program.Replace("$", "x = $Color$;"));
Assert.AreEqual("Color", mrr.Member.Name);
}
[Test]
public void PropertyNameAmbiguousWithTypeName_MemberAccessOnAmbiguousIdentifier()
{
string program = propertyNameAmbiguousWithTypeNameProgram;
Resolve<MemberResolveResult>(program.Replace("$", "$Color$ = Color.Empty;"));
Resolve<TypeResolveResult>(program.Replace("$", "Color = $Color$.Empty;"));
Resolve<MemberResolveResult>(program.Replace("$", "x = $Color$.ToString();"));
}
[Test]
public void PropertyNameAmbiguousWithTypeName_MethodInvocationOnAmbiguousIdentifier()
{
string program = propertyNameAmbiguousWithTypeNameProgram;
Resolve<MemberResolveResult>(program.Replace("$", "x = $Color$.M(1);"));
Resolve<TypeResolveResult>(program.Replace("$", "x = $Color$.M();"));
}
[Test]

22
ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs

@ -658,20 +658,26 @@ namespace ICSharpCode.NRefactory.CSharp @@ -658,20 +658,26 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
IAttribute ConvertAttribute(CSharp.Attribute attr)
internal static ITypeReference ConvertAttributeType(AstType type, ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope)
{
DomRegion region = MakeRegion(attr);
ITypeReference type = ConvertType(attr.Type);
if (!attr.Type.GetChildByRole(AstNode.Roles.Identifier).IsVerbatim) {
ITypeReference tr = ConvertType(type, parentTypeDefinition, parentMethodDefinition, parentUsingScope, SimpleNameLookupMode.Type);
if (!type.GetChildByRole(AstNode.Roles.Identifier).IsVerbatim) {
// Try to add "Attribute" suffix, but only if the identifier
// (=last identifier in fully qualified name) isn't a verbatim identifier.
SimpleTypeOrNamespaceReference st = type as SimpleTypeOrNamespaceReference;
MemberTypeOrNamespaceReference mt = type as MemberTypeOrNamespaceReference;
SimpleTypeOrNamespaceReference st = tr as SimpleTypeOrNamespaceReference;
MemberTypeOrNamespaceReference mt = tr as MemberTypeOrNamespaceReference;
if (st != null)
type = new AttributeTypeReference(st, st.AddSuffix("Attribute"));
return new AttributeTypeReference(st, st.AddSuffix("Attribute"));
else if (mt != null)
type = new AttributeTypeReference(mt, mt.AddSuffix("Attribute"));
return new AttributeTypeReference(mt, mt.AddSuffix("Attribute"));
}
return tr;
}
IAttribute ConvertAttribute(CSharp.Attribute attr)
{
DomRegion region = MakeRegion(attr);
ITypeReference type = ConvertAttributeType(attr.Type, currentTypeDefinition, currentMethod, usingScope);
List<IConstantValue> positionalArguments = null;
List<KeyValuePair<string, IConstantValue>> namedCtorArguments = null;
List<KeyValuePair<string, IConstantValue>> namedArguments = null;

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

@ -41,8 +41,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -41,8 +41,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public IMethod ResolveConstructor(ITypeResolveContext context)
{
CSharpResolver r = new CSharpResolver(context);
IType type = attributeType.Resolve(context);
throw new NotImplementedException();
int totalArgumentCount = 0;
if (positionalArguments != null)
totalArgumentCount += positionalArguments.Count;
if (namedCtorArguments != null)
totalArgumentCount += namedCtorArguments.Count;
ResolveResult[] arguments = new ResolveResult[totalArgumentCount];
string[] argumentNames = new string[totalArgumentCount];
int i = 0;
if (positionalArguments != null) {
while (i < positionalArguments.Count) {
IConstantValue cv = positionalArguments[i];
arguments[i] = new ConstantResolveResult(cv.GetValueType(context), cv.GetValue(context));
i++;
}
}
if (namedCtorArguments != null) {
foreach (var pair in namedCtorArguments) {
argumentNames[i] = pair.Key;
arguments[i] = new ConstantResolveResult(pair.Value.GetValueType(context), pair.Value.GetValue(context));
i++;
}
}
MemberResolveResult mrr = r.ResolveObjectCreation(type, arguments, argumentNames) as MemberResolveResult;
return mrr != null ? mrr.Member as IMethod : null;
}
public IList<IConstantValue> GetPositionalArguments(ITypeResolveContext context)

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

@ -38,6 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -38,6 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
static readonly ResolveResult errorResult = new ErrorResolveResult(SharedTypes.UnknownType);
CSharpResolver resolver;
SimpleNameLookupMode currentTypeLookupMode = SimpleNameLookupMode.Type;
readonly ParsedFile parsedFile;
readonly Dictionary<AstNode, ResolveResult> resolveResultCache = new Dictionary<AstNode, ResolveResult>();
readonly Dictionary<AstNode, CSharpResolver> resolverBeforeDict = new Dictionary<AstNode, CSharpResolver>();
@ -232,7 +233,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -232,7 +233,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
if (newTypeDefinition != null)
resolver.CurrentTypeDefinition = newTypeDefinition;
ScanChildren(typeDeclaration);
for (AstNode child = typeDeclaration.FirstChild; child != null; child = child.NextSibling) {
if (child.Role == TypeDeclaration.BaseTypeRole) {
currentTypeLookupMode = SimpleNameLookupMode.BaseTypeReference;
Scan(child);
currentTypeLookupMode = SimpleNameLookupMode.Type;
} else {
Scan(child);
}
}
return newTypeDefinition != null ? new TypeResolveResult(newTypeDefinition) : errorResult;
} finally {
resolver.CurrentTypeDefinition = previousTypeDefinition;
@ -256,6 +267,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -256,6 +267,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return VisitFieldOrEventDeclaration(fieldDeclaration);
}
public override ResolveResult VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, object data)
{
return VisitFieldOrEventDeclaration(fixedFieldDeclaration);
}
public override ResolveResult VisitEventDeclaration(EventDeclaration eventDeclaration, object data)
{
return VisitFieldOrEventDeclaration(eventDeclaration);
@ -307,6 +323,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -307,6 +323,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
public override ResolveResult VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, object data)
{
ScanChildren(fixedVariableInitializer);
if (resolverEnabled) {
if (resolver.CurrentMember != null)
return new MemberResolveResult(resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context));
else
return errorResult;
} else {
return null;
}
}
ResolveResult VisitMethodMember(AttributedNode member)
{
try {
@ -468,11 +497,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -468,11 +497,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
resolver.CurrentMember = null;
}
}
public override ResolveResult VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, object data)
{
throw new NotImplementedException();
}
#endregion
#region Track CheckForOverflow
@ -534,15 +558,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -534,15 +558,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region Visit Expressions
static bool IsTargetOfInvocation(AstNode node)
{
InvocationExpression ie = node.Parent as InvocationExpression;
return ie != null && ie.Target == node;
}
IType ResolveType(AstType type)
{
return MakeTypeReference(type).Resolve(resolver.Context);
return Resolve(type).Type;
}
public override ResolveResult VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data)
@ -717,32 +735,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -717,32 +735,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return errorResult;
}
public override ResolveResult VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
{
if (resolverEnabled) {
List<IType> typeArguments = new List<IType>();
foreach (AstType typeArgument in identifierExpression.TypeArguments) {
typeArguments.Add(ResolveType(typeArgument));
}
return resolver.ResolveSimpleName(identifierExpression.Identifier, typeArguments,
IsTargetOfInvocation(identifierExpression));
} else {
ScanChildren(identifierExpression);
return null;
}
}
ResolveResult[] GetArguments(IEnumerable<Expression> argumentExpressions, out string[] argumentNames)
{
argumentNames = null; // TODO: add support for named arguments
ResolveResult[] arguments = new ResolveResult[argumentExpressions.Count()];
int i = 0;
foreach (AstNode argument in argumentExpressions) {
arguments[i++] = Resolve(argument);
}
return arguments;
}
public override ResolveResult VisitIndexerExpression(IndexerExpression indexerExpression, object data)
{
if (resolverEnabled) {
@ -756,19 +748,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -756,19 +748,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
public override ResolveResult VisitInvocationExpression(InvocationExpression invocationExpression, object data)
{
if (resolverEnabled) {
ResolveResult target = Resolve(invocationExpression.Target);
string[] argumentNames;
ResolveResult[] arguments = GetArguments(invocationExpression.Arguments, out argumentNames);
return resolver.ResolveInvocation(target, arguments, argumentNames);
} else {
ScanChildren(invocationExpression);
return null;
}
}
public override ResolveResult VisitIsExpression(IsExpression isExpression, object data)
{
ScanChildren(isExpression);
@ -783,23 +762,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -783,23 +762,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
throw new NotImplementedException();
}
public override ResolveResult VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{
if (resolverEnabled) {
ResolveResult target = Resolve(memberReferenceExpression.Target);
List<IType> typeArguments = new List<IType>();
foreach (AstType typeArgument in memberReferenceExpression.TypeArguments) {
typeArguments.Add(ResolveType(typeArgument));
}
return resolver.ResolveMemberAccess(target, memberReferenceExpression.MemberName,
typeArguments,
IsTargetOfInvocation(memberReferenceExpression));
} else {
ScanChildren(memberReferenceExpression);
return null;
}
}
public override ResolveResult VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data)
{
if (resolverEnabled) {
@ -948,6 +910,187 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -948,6 +910,187 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#endregion
#region Visit Identifier/MemberReference/Invocation-Expression
// IdentifierExpression, MemberReferenceExpression and InvocationExpression
// are grouped together because they have to work together for
// "7.6.4.1 Identical simple names and type names" support
List<IType> GetTypeArguments(IEnumerable<AstType> typeArguments)
{
List<IType> result = new List<IType>();
foreach (AstType typeArgument in typeArguments) {
result.Add(ResolveType(typeArgument));
}
return result;
}
ResolveResult[] GetArguments(IEnumerable<Expression> argumentExpressions, out string[] argumentNames)
{
argumentNames = null;
ResolveResult[] arguments = new ResolveResult[argumentExpressions.Count()];
int i = 0;
foreach (AstNode argument in argumentExpressions) {
NamedArgumentExpression nae = argument as NamedArgumentExpression;
AstNode argumentValue;
if (nae != null) {
if (argumentNames == null)
argumentNames = new string[arguments.Length];
argumentNames[i] = nae.Identifier;
argumentValue = nae.Expression;
} else {
argumentValue = argument;
}
arguments[i++] = Resolve(argumentValue);
}
return arguments;
}
static bool IsTargetOfInvocation(AstNode node)
{
InvocationExpression ie = node.Parent as InvocationExpression;
return ie != null && ie.Target == node;
}
bool IsVariableReferenceWithSameType(ResolveResult rr, string identifier, out TypeResolveResult trr)
{
if (!(rr is MemberResolveResult || rr is LocalResolveResult)) {
trr = null;
return false;
}
trr = resolver.LookupSimpleNameOrTypeName(identifier, EmptyList<IType>.Instance, SimpleNameLookupMode.Type) as TypeResolveResult;
return trr != null && trr.Type.Equals(rr.Type);
}
/// <summary>
/// Gets whether 'rr' is considered a static access on the target identifier.
/// </summary>
/// <param name="rr">Resolve Result of the MemberReferenceExpression</param>
/// <param name="invocationRR">Resolve Result of the InvocationExpression</param>
bool IsStaticResult(ResolveResult rr, ResolveResult invocationRR)
{
if (rr is TypeResolveResult)
return true;
MemberResolveResult mrr = (rr is MethodGroupResolveResult ? invocationRR : rr) as MemberResolveResult;
return mrr != null && mrr.Member.IsStatic;
}
public override ResolveResult VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
{
// Note: this method is not called when it occurs in a situation where an ambiguity between
// simple names and type names might occur.
if (resolverEnabled) {
var typeArguments = GetTypeArguments(identifierExpression.TypeArguments);
return resolver.ResolveSimpleName(identifierExpression.Identifier, typeArguments,
IsTargetOfInvocation(identifierExpression));
} else {
ScanChildren(identifierExpression);
return null;
}
}
public override ResolveResult VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{
// target = Resolve(identifierExpression = memberReferenceExpression.Target)
// trr = ResolveType(identifierExpression)
// rr = Resolve(memberReferenceExpression)
IdentifierExpression identifierExpression = memberReferenceExpression.Target as IdentifierExpression;
if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0) {
// Special handling for §7.6.4.1 Identicial simple names and type names
ResolveResult target = resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList<IType>.Instance);
TypeResolveResult trr;
if (IsVariableReferenceWithSameType(target, identifierExpression.Identifier, out trr)) {
// It's ambiguous
ResolveResult rr = ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
resolveResultCache.Add(identifierExpression, IsStaticResult(rr, null) ? trr : target);
return rr;
} else {
// It's not ambiguous
resolveResultCache.Add(identifierExpression, target);
if (resolverEnabled) {
return ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
} else {
// Scan children (but not the IdentifierExpression which we already resolved)
for (AstNode child = memberReferenceExpression.FirstChild; child != null; child = child.NextSibling) {
if (child != identifierExpression)
Scan(child);
}
return null;
}
}
} else {
// Regular code path
if (resolverEnabled) {
ResolveResult target = Resolve(memberReferenceExpression.Target);
return ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression);
} else {
ScanChildren(memberReferenceExpression);
return null;
}
}
}
ResolveResult ResolveMemberReferenceOnGivenTarget(ResolveResult target, MemberReferenceExpression memberReferenceExpression)
{
var typeArguments = GetTypeArguments(memberReferenceExpression.TypeArguments);
return resolver.ResolveMemberAccess(
target, memberReferenceExpression.MemberName, typeArguments,
IsTargetOfInvocation(memberReferenceExpression));
}
public override ResolveResult VisitInvocationExpression(InvocationExpression invocationExpression, object data)
{
// rr = Resolve(invocationExpression)
// target = Resolve(memberReferenceExpression = invocationExpression.Target)
// idRR = Resolve(identifierExpression = memberReferenceExpression.Target)
// trr = ResolveType(identifierExpression)
MemberReferenceExpression mre = invocationExpression.Target as MemberReferenceExpression;
IdentifierExpression identifierExpression = mre != null ? mre.Target as IdentifierExpression : null;
if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0) {
// Special handling for §7.6.4.1 Identicial simple names and type names
ResolveResult idRR = resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList<IType>.Instance);
ResolveResult target = ResolveMemberReferenceOnGivenTarget(idRR, mre);
resolveResultCache.Add(mre, target);
TypeResolveResult trr;
if (IsVariableReferenceWithSameType(idRR, identifierExpression.Identifier, out trr)) {
// It's ambiguous
ResolveResult rr = ResolveInvocationOnGivenTarget(target, invocationExpression);
resolveResultCache.Add(identifierExpression, IsStaticResult(target, rr) ? trr : idRR);
return rr;
} else {
// It's not ambiguous
resolveResultCache.Add(identifierExpression, idRR);
if (resolverEnabled) {
return ResolveInvocationOnGivenTarget(target, invocationExpression);
} else {
// Scan children (but not the MRE which we already resolved)
for (AstNode child = invocationExpression.FirstChild; child != null; child = child.NextSibling) {
if (child != mre)
Scan(child);
}
return null;
}
}
} else {
// Regular code path
if (resolverEnabled) {
ResolveResult target = Resolve(invocationExpression.Target);
return ResolveInvocationOnGivenTarget(target, invocationExpression);
} else {
ScanChildren(invocationExpression);
return null;
}
}
}
ResolveResult ResolveInvocationOnGivenTarget(ResolveResult target, InvocationExpression invocationExpression)
{
string[] argumentNames;
ResolveResult[] arguments = GetArguments(invocationExpression.Arguments, out argumentNames);
return resolver.ResolveInvocation(target, arguments, argumentNames);
}
#endregion
#region Local Variable Scopes (Block Statements)
public override ResolveResult VisitBlockStatement(BlockStatement blockStatement, object data)
{
@ -1056,23 +1199,48 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1056,23 +1199,48 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
ITypeReference MakeTypeReference(AstType type, AstNode initializerExpression, bool isForEach)
{
bool needsResolving;
if (mode == ResolveVisitorNavigationMode.ResolveAll) {
needsResolving = true;
} else {
var modeForType = navigator.Scan(type);
needsResolving = (modeForType == ResolveVisitorNavigationMode.Resolve || modeForType == ResolveVisitorNavigationMode.ResolveAll);
}
if (initializerExpression != null && IsVar(type)) {
return new VarTypeReference(this, resolver.Clone(), initializerExpression, isForEach);
var typeRef = new VarTypeReference(this, resolver.Clone(), initializerExpression, isForEach);
if (needsResolving) {
// Hack: I don't see a clean way to make the 'var' SimpleType resolve to the inferred type,
// so we just do it here and store the result in the resolver cache.
IType actualType = typeRef.Resolve(resolver.Context);
if (actualType.Kind != TypeKind.Unknown) {
resolveResultCache.Add(type, new TypeResolveResult(actualType));
} else {
resolveResultCache.Add(type, errorResult);
}
return actualType;
} else {
return typeRef;
}
} else {
return MakeTypeReference(type);
// Perf: avoid duplicate resolving of the type (once as ITypeReference, once directly in ResolveVisitor)
// if possible. By using ResolveType when we know we need to resolve the node anyways, the resolve cache
// can take care of the duplicate call.
if (needsResolving)
return ResolveType(type);
else
return MakeTypeReference(type);
}
}
ITypeReference MakeTypeReference(AstType type)
static bool IsVar(AstType returnType)
{
return TypeSystemConvertVisitor.ConvertType(type, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.UsingScope, SimpleNameLookupMode.Type);
SimpleType st = returnType as SimpleType;
return st != null && st.Identifier == "var" && st.TypeArguments.Count == 0;
}
static bool IsVar(AstType returnType)
ITypeReference MakeTypeReference(AstType type)
{
return returnType is SimpleType
&& ((SimpleType)returnType).Identifier == "var"
&& ((SimpleType)returnType).TypeArguments.Count == 0;
return TypeSystemConvertVisitor.ConvertType(type, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.UsingScope, currentTypeLookupMode);
}
sealed class VarTypeReference : ITypeReference
@ -1099,6 +1267,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1099,6 +1267,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var oldMode = visitor.mode;
var oldResolver = visitor.resolver;
var oldTypeLookupMode = visitor.currentTypeLookupMode;
try {
visitor.mode = ResolveVisitorNavigationMode.Resolve;
visitor.resolver = storedContext;
@ -1113,6 +1282,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1113,6 +1282,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} finally {
visitor.mode = oldMode;
visitor.resolver = oldResolver;
visitor.currentTypeLookupMode = oldTypeLookupMode;
visitor = null;
storedContext = null;
@ -1153,57 +1323,44 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1153,57 +1323,44 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region Attributes
ITypeReference GetAttributeType (Attribute attribute)
{
var withoutSuffix = MakeTypeReference(attribute.Type);
ITypeReference withSuffix;
if (attribute.Type is SimpleType) {
var st = (SimpleType)attribute.Type;
withSuffix = MakeTypeReference(new SimpleType (st.Identifier + "Attribute"));
} else if (attribute.Type is MemberType) {
var mt = (MemberType)attribute.Type;
withSuffix = MakeTypeReference(new MemberType (mt.Target.Clone (), mt.MemberName + "Attribute"));
} else {
// unsupported type.
return SharedTypes.UnknownType;
}
return new AttributeTypeReference(withoutSuffix, withSuffix);
}
public override ResolveResult VisitAttribute(Attribute attribute, object data)
{
ScanChildren(attribute);
if (resolverEnabled) {
var type = GetAttributeType (attribute).Resolve (resolver.Context);
if (!attribute.HasArgumentList)
return new TypeResolveResult (type);
// try if the attribute usage references a constructuor
var type = ResolveType(attribute.Type);
// Separate arguments into ctor arguments and non-ctor arguments:
var constructorArguments = attribute.Arguments.Where(a => !(a is AssignmentExpression));
var nonConstructorArguments = attribute.Arguments.Where(a => a is AssignmentExpression);
// Scan the non-constructor arguments
foreach (var arg in nonConstructorArguments)
Scan(arg);
// Resolve the ctor arguments and find the matching ctor overload
string[] argumentNames;
ResolveResult[] arguments = GetArguments(attribute.Arguments, out argumentNames);
var result = resolver.ResolveObjectCreation(type, arguments, argumentNames);
Console.WriteLine (result);
// if this is an error give back type resolve result, an attribute arg list isn't a constructor reference
// in all cases. - is it better to always give back the type resolve result ?
if (result.IsError)
return new TypeResolveResult (type);
return result;
ResolveResult[] arguments = GetArguments(constructorArguments, out argumentNames);
return resolver.ResolveObjectCreation(type, arguments, argumentNames);
} else {
ScanChildren(attribute);
return null;
}
return null;
}
#endregion
#region Using Declaration
public override ResolveResult VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data)
{
// TODO: set isInUsingDeclaration
currentTypeLookupMode = SimpleNameLookupMode.TypeInUsingDeclaration;
ScanChildren(usingDeclaration);
currentTypeLookupMode = SimpleNameLookupMode.Type;
return null;
}
public override ResolveResult VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, object data)
{
// TODO: set isInUsingDeclaration
currentTypeLookupMode = SimpleNameLookupMode.TypeInUsingDeclaration;
ScanChildren(usingDeclaration);
currentTypeLookupMode = SimpleNameLookupMode.Type;
return null;
}
#endregion
@ -1211,37 +1368,76 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1211,37 +1368,76 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region Type References
public override ResolveResult VisitPrimitiveType(PrimitiveType primitiveType, object data)
{
ScanChildren(primitiveType);
return new TypeResolveResult(ResolveType(primitiveType));
if (!resolverEnabled)
return null;
IType type = MakeTypeReference(primitiveType).Resolve(resolver.Context);
if (type.Kind != TypeKind.Unknown)
return new TypeResolveResult(type);
else
return errorResult;
}
public override ResolveResult VisitSimpleType(SimpleType simpleType, object data)
ResolveResult HandleAttributeType(AstType astType)
{
ScanChildren(simpleType);
return ResolveTypeOrNamespace(simpleType);
ScanChildren(astType);
IType type = TypeSystemConvertVisitor.ConvertAttributeType(astType, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.UsingScope).Resolve(resolver.Context);
if (type.Kind != TypeKind.Unknown)
return new TypeResolveResult(type);
else
return errorResult;
}
ResolveResult ResolveTypeOrNamespace(AstType type)
public override ResolveResult VisitSimpleType(SimpleType simpleType, object data)
{
ITypeReference typeRef = MakeTypeReference(type);
ITypeOrNamespaceReference typeOrNsRef = typeRef as ITypeOrNamespaceReference;
if (typeOrNsRef != null) {
return typeOrNsRef.DoResolve(resolver.Context);
} else {
return new TypeResolveResult(typeRef.Resolve(resolver.Context));
if (!resolverEnabled) {
ScanChildren(simpleType);
return null;
}
if (simpleType.Parent is Attribute) {
return HandleAttributeType(simpleType);
}
var typeArguments = GetTypeArguments(simpleType.TypeArguments);
return resolver.LookupSimpleNameOrTypeName(simpleType.Identifier, typeArguments, currentTypeLookupMode);
}
public override ResolveResult VisitMemberType(MemberType memberType, object data)
{
ScanChildren(memberType);
return ResolveTypeOrNamespace(memberType);
if (!resolverEnabled) {
ScanChildren(memberType);
return null;
}
if (memberType.Parent is Attribute) {
return HandleAttributeType(memberType);
}
ResolveResult target;
if (memberType.IsDoubleColon && memberType.Target is SimpleType) {
target = resolver.ResolveAlias(((SimpleType)memberType.Target).Identifier);
} else {
target = Resolve(memberType.Target);
}
var typeArguments = GetTypeArguments(memberType.TypeArguments);
return resolver.ResolveMemberAccess(target, memberType.MemberName, typeArguments);
}
public override ResolveResult VisitComposedType(ComposedType composedType, object data)
{
ScanChildren(composedType);
return new TypeResolveResult(ResolveType(composedType));
if (!resolverEnabled) {
ScanChildren(composedType);
return null;
}
IType t = ResolveType(composedType.BaseType);
if (composedType.HasNullableSpecifier) {
t = NullableType.Create(t, resolver.Context);
}
for (int i = 0; i < composedType.PointerRank; i++) {
t = new PointerType(t);
}
foreach (var a in composedType.ArraySpecifiers.Reverse()) {
t = new ArrayType(t, a.Dimensions);
}
return new TypeResolveResult(t);
}
#endregion
@ -1270,11 +1466,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1270,11 +1466,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
throw new NotImplementedException();
}
public override ResolveResult VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, object data)
{
throw new NotImplementedException();
}
#region Token Nodes
public override ResolveResult VisitIdentifier(Identifier identifier, object data)
{

44
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -742,26 +742,18 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -742,26 +742,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
}
DefaultAttribute a = new DefaultAttribute(ReadTypeReference(attribute.AttributeType), ctorParameters);
try {
if (attribute.HasConstructorArguments) {
foreach (var arg in attribute.ConstructorArguments) {
a.PositionalArguments.Add(ReadConstantValue(arg));
}
if (attribute.HasConstructorArguments) {
foreach (var arg in attribute.ConstructorArguments) {
a.PositionalArguments.Add(ReadConstantValue(arg));
}
} catch (InvalidOperationException) {
// occurs when Cecil can't decode an argument
}
try {
if (attribute.HasFields || attribute.HasProperties) {
foreach (var arg in attribute.Fields) {
a.NamedArguments.Add(new KeyValuePair<string, IConstantValue>(arg.Name, ReadConstantValue(arg.Argument)));
}
foreach (var arg in attribute.Properties) {
a.NamedArguments.Add(new KeyValuePair<string, IConstantValue>(arg.Name, ReadConstantValue(arg.Argument)));
}
if (attribute.HasFields || attribute.HasProperties) {
foreach (var arg in attribute.Fields) {
a.NamedArguments.Add(new KeyValuePair<string, IConstantValue>(arg.Name, ReadConstantValue(arg.Argument)));
}
foreach (var arg in attribute.Properties) {
a.NamedArguments.Add(new KeyValuePair<string, IConstantValue>(arg.Name, ReadConstantValue(arg.Argument)));
}
} catch (InvalidOperationException) {
// occurs when Cecil can't decode an argument
}
return a;
}
@ -773,12 +765,12 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -773,12 +765,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
void AddSecurityAttributes(Mono.Collections.Generic.Collection<SecurityDeclaration> securityDeclarations, IList<IAttribute> targetCollection)
{
foreach (var secDecl in securityDeclarations) {
foreach (var secAttribute in secDecl.SecurityAttributes) {
ITypeReference attributeType = ReadTypeReference(secAttribute.AttributeType);
var a = new DefaultAttribute(attributeType, new[] { securityActionTypeReference });
a.PositionalArguments.Add(new SimpleConstantValue(securityActionTypeReference, (ushort)secDecl.Action));
try {
try {
foreach (var secAttribute in secDecl.SecurityAttributes) {
ITypeReference attributeType = ReadTypeReference(secAttribute.AttributeType);
var a = new DefaultAttribute(attributeType, new[] { securityActionTypeReference });
a.PositionalArguments.Add(new SimpleConstantValue(securityActionTypeReference, (ushort)secDecl.Action));
if (secAttribute.HasFields || secAttribute.HasProperties) {
foreach (var arg in secAttribute.Fields) {
a.NamedArguments.Add(new KeyValuePair<string, IConstantValue>(arg.Name, ReadConstantValue(arg.Argument)));
@ -787,10 +779,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -787,10 +779,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
a.NamedArguments.Add(new KeyValuePair<string, IConstantValue>(arg.Name, ReadConstantValue(arg.Argument)));
}
}
} catch (InvalidOperationException) {
// occurs when Cecil can't decode an argument
targetCollection.Add(a);
}
targetCollection.Add(a);
} catch (ResolutionException) {
// occurs when Cecil can't decode an argument
}
}
}

Loading…
Cancel
Save