diff --git a/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs b/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs index be1b830e1f..205a768846 100644 --- a/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs @@ -110,9 +110,11 @@ namespace ICSharpCode.NRefactory.CSharp /// Create an ITypeReference for this AstType. /// /// - /// The resulting type reference requires a - /// - /// to be resolved. + /// The resulting type reference will read the context information from the + /// : + /// For resolving type parameters, the CurrentTypeDefinition/CurrentMember is used. + /// For resolving simple names, the current namespace and usings from the CurrentUsingScope + /// (on CSharpTypeResolveContext only) is used. /// public abstract ITypeReference ToTypeReference(SimpleNameLookupMode lookupMode = SimpleNameLookupMode.Type); diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs index 9eba223e0e..bede38b5cc 100644 --- a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs @@ -388,7 +388,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // C# 4.0 spec: §7.6.9 Postfix increment and decrement operators // C# 4.0 spec: §7.7.5 Prefix increment and decrement operators TypeCode code = ReflectionHelper.GetTypeCode(type); - if ((code >= TypeCode.SByte && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer) + if ((code >= TypeCode.Char && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer) return UnaryOperatorResolveResult(expression.Type, op, expression); else return new ErrorResolveResult(expression.Type); @@ -1352,7 +1352,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return r; } - if (context.CurrentUsingScope != null) { + if (context.CurrentUsingScope == null) { + // If no using scope was specified, we still need to look in the global namespace: + r = LookInUsingScopeNamespace(null, compilation.RootNamespace, identifier, typeArguments, parameterizeResultType); + } else { if (k == 0 && lookupMode != SimpleNameLookupMode.TypeInUsingDeclaration) { if (!context.CurrentUsingScope.ResolveCache.TryGetValue(identifier, out r)) { r = LookInCurrentUsingScope(identifier, typeArguments, false, false); @@ -1361,9 +1364,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } else { r = LookInCurrentUsingScope(identifier, typeArguments, lookupMode == SimpleNameLookupMode.TypeInUsingDeclaration, parameterizeResultType); } - if (r != null) - return r; } + if (r != null) + return r; if (typeArguments.Count == 0 && identifier == "dynamic") { return new TypeResolveResult(SpecialType.Dynamic); @@ -1418,36 +1421,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ResolveResult LookInCurrentUsingScope(string identifier, IList typeArguments, bool isInUsingDeclaration, bool parameterizeResultType) { - int k = typeArguments.Count; // look in current namespace definitions ResolvedUsingScope currentUsingScope = this.CurrentUsingScope; for (ResolvedUsingScope u = currentUsingScope; u != null; u = u.Parent) { - INamespace n = u.Namespace; - // first look for a namespace - if (k == 0 && n != null) { - INamespace childNamespace = n.GetChildNamespace(identifier); - if (childNamespace != null) { - if (u.HasAlias(identifier)) - return new AmbiguousTypeResolveResult(new UnknownType(null, identifier)); - return new NamespaceResolveResult(childNamespace); - } - } - // then look for a type - if (n != null) { - ITypeDefinition def = n.GetTypeDefinition(identifier, k); - if (def != null) { - IType result = def; - if (parameterizeResultType && k > 0) { - result = new ParameterizedType(def, typeArguments); - } - if (u.HasAlias(identifier)) - return new AmbiguousTypeResolveResult(result); - else - return new TypeResolveResult(result); - } - } + var resultInNamespace = LookInUsingScopeNamespace(u, u.Namespace, identifier, typeArguments, parameterizeResultType); + if (resultInNamespace != null) + return resultInNamespace; // then look for aliases: - if (k == 0) { + if (typeArguments.Count == 0) { if (u.ExternAliases.Contains(identifier)) { return ResolveExternAlias(identifier); } @@ -1463,10 +1444,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (!(isInUsingDeclaration && u == currentUsingScope)) { IType firstResult = null; foreach (var importedNamespace in u.Usings) { - ITypeDefinition def = importedNamespace.GetTypeDefinition(identifier, k); + ITypeDefinition def = importedNamespace.GetTypeDefinition(identifier, typeArguments.Count); if (def != null) { IType resultType; - if (parameterizeResultType && k > 0) + if (parameterizeResultType && typeArguments.Count > 0) resultType = new ParameterizedType(def, typeArguments); else resultType = def; @@ -1485,6 +1466,35 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } return null; } + + ResolveResult LookInUsingScopeNamespace(ResolvedUsingScope usingScope, INamespace n, string identifier, IList typeArguments, bool parameterizeResultType) + { + if (n == null) + return null; + // first look for a namespace + int k = typeArguments.Count; + if (k == 0) { + INamespace childNamespace = n.GetChildNamespace(identifier); + if (childNamespace != null) { + if (usingScope != null && usingScope.HasAlias(identifier)) + return new AmbiguousTypeResolveResult(new UnknownType(null, identifier)); + return new NamespaceResolveResult(childNamespace); + } + } + // then look for a type + ITypeDefinition def = n.GetTypeDefinition(identifier, k); + if (def != null) { + IType result = def; + if (parameterizeResultType && k > 0) { + result = new ParameterizedType(def, typeArguments); + } + if (usingScope != null && usingScope.HasAlias(identifier)) + return new AmbiguousTypeResolveResult(result); + else + return new TypeResolveResult(result); + } + return null; + } bool TopLevelTypeDefinitionIsAccessible(ITypeDefinition typeDef) { diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs index c240bc2876..a822b9a66d 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeOrNamespaceReference.cs @@ -58,7 +58,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem // to what we're doing with ConstantExpression. // However, in almost all cases this will work correctly - if the resulting type is only available in the // nested compilation and not in this, we wouldn't be able to map it anyways. - return ResolveType(new CSharpResolver((CSharpTypeResolveContext)context)); + var ctx = context as CSharpTypeResolveContext; + if (ctx == null) { + ctx = new CSharpTypeResolveContext(context.CurrentAssembly ?? context.Compilation.MainAssembly, null, context.CurrentTypeDefinition, context.CurrentMember); + } + return ResolveType(new CSharpResolver(ctx)); // A potential issue might be this scenario: diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs index 38567372d5..9ab5bd1d4f 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs @@ -80,6 +80,13 @@ namespace ICSharpCode.NRefactory.CSharp.Parser Assert.AreEqual(genericInterfaceOfString, interfaceMethod2.DeclaringType); Assert.IsTrue(interfaceMethod2.Parameters[1].IsRef); } + + [Test] + public void ConvertStandaloneTypeReference() + { + var typeRef = new MemberType(new SimpleType("System"), "Array").ToTypeReference(); + Assert.AreEqual(compilation.FindType(KnownTypeCode.Array), typeRef.Resolve(compilation.TypeResolveContext)); + } } [TestFixture] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs index f8b904f4f1..da17c240b6 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs @@ -61,8 +61,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void SimpleNameLookupWithoutContext() { - // nothing should be found without specifying any UsingScope - however, the resolver also must not crash - Assert.IsTrue(resolver.WithCurrentUsingScope(null).ResolveSimpleName("System", new IType[0]).IsError); + // without any using scope, we still want to find elements of the global namespace: + var nrr = (NamespaceResolveResult)resolver.WithCurrentUsingScope(null).ResolveSimpleName("System", new IType[0]); + Assert.AreEqual("System", nrr.NamespaceName); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs index f4ae311a60..36979f72e8 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs @@ -71,6 +71,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver TestOperator(UnaryOperatorType.Increment, MakeResult(typeof(byte)), Conversion.IdentityConversion, typeof(byte)); + TestOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(char)), + Conversion.IdentityConversion, typeof(char)); + + TestOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(float)), + Conversion.IdentityConversion, typeof(float)); + + TestOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(decimal)), + Conversion.IdentityConversion, typeof(decimal)); + TestOperator(UnaryOperatorType.Decrement, MakeResult(typeof(ulong)), Conversion.IdentityConversion, typeof(ulong)); diff --git a/NRefactory.sln b/NRefactory.sln index 2a656dc2fd..08b92e6157 100644 --- a/NRefactory.sln +++ b/NRefactory.sln @@ -1,12 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -# SharpDevelop 4.2.0.8299-alpha +# SharpDevelop 4.2.0.8528-beta Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DC98210E-1646-483B-819A-2BB8272461E4}" ProjectSection(SolutionItems) = preProject README = README doc\TODO = doc\TODO Packages\ICSharpCode.NRefactory.nuspec = Packages\ICSharpCode.NRefactory.nuspec + ICSharpCode.NRefactory.snk = ICSharpCode.NRefactory.snk EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory", "ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj", "{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}"