From ba290b6bf9f6a027a2412cfbe17121d46e06520f Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 9 Dec 2008 18:28:22 +0000 Subject: [PATCH] Add "IUsingScope" to allow representing the nesting of usings in namespaces in SharpDevelop.Dom. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3675 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/CodeCompletion/ConvertVisitor.cs | 8 ++- .../Project/Src/PythonAstWalker.cs | 2 +- .../Project/Src/PythonResolver.cs | 2 +- .../Test/Parsing/ParseImportTestFixture.cs | 4 +- ...paceContentsAddedToCtrlSpaceTestFixture.cs | 2 +- .../Src/SuppressMessageCommand.cs | 11 ++- .../Misc/UnitTesting/Test/Utils/MockClass.cs | 6 ++ .../NamespaceRefactoringService.cs | 8 +-- src/Main/Base/Test/MemberLookupHelperTests.cs | 8 +-- src/Main/Base/Test/SearchClassTests.cs | 6 +- src/Main/Base/Test/SearchGenericClassTests.cs | 8 +-- src/Main/Base/Test/Utils/MockClass.cs | 6 ++ .../ICSharpCode.SharpDevelop.Dom.csproj | 2 + .../Project/Src/CtrlSpaceResolveHelper.cs | 2 +- .../Project/Src/ExtensionMethods.cs | 29 ++++++++ .../Src/Implementations/AbstractEntity.cs | 11 ++- .../Src/Implementations/DefaultClass.cs | 25 +++++++ .../Implementations/DefaultCompilationUnit.cs | 14 ++-- .../Src/Implementations/DefaultUsingScope.cs | 70 +++++++++++++++++++ .../Project/Src/Interfaces/IClass.cs | 7 ++ .../Src/Interfaces/ICompilationUnit.cs | 6 +- .../Project/Src/Interfaces/IUsingScope.cs | 46 ++++++++++++ .../NRefactoryASTConvertVisitor.cs | 53 +++++++------- .../NRefactoryResolver/NRefactoryResolver.cs | 25 ++++--- .../ProjectContent/DefaultProjectContent.cs | 6 +- .../NRefactoryRefactoringProvider.cs | 6 +- 26 files changed, 295 insertions(+), 78 deletions(-) create mode 100644 src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultUsingScope.cs create mode 100644 src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IUsingScope.cs diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs index b1076de35e..3736935aed 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ConvertVisitor.cs @@ -137,7 +137,7 @@ namespace Grunwald.BooBinding.CodeCompletion u.Usings.Add(p.Namespace); else u.AddAlias(p.Alias.Name, new GetClassReturnType(_cu.ProjectContent, p.Namespace, 0)); - _cu.Usings.Add(u); + _cu.UsingScope.Usings.Add(u); } private IClass OuterClass { @@ -504,6 +504,12 @@ namespace Grunwald.BooBinding.CodeCompletion OuterClass.Properties.Add(property); property.UserData = node; } + + public override void OnNamespaceDeclaration(Boo.Lang.Compiler.Ast.NamespaceDeclaration node) + { + _cu.UsingScope = new DefaultUsingScope { NamespaceName = node.Name }; + base.OnNamespaceDeclaration(node); + } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs index b122602db0..3e5e39e74b 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs @@ -108,7 +108,7 @@ namespace ICSharpCode.PythonBinding Console.WriteLine("Name: " + name.MakeString()); newUsing.Usings.Add(name.MakeString()); } - compilationUnit.Usings.Add(newUsing); + compilationUnit.UsingScope.Usings.Add(newUsing); return false; } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs index 4f317700bf..8622c534ed 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonResolver.cs @@ -287,7 +287,7 @@ namespace ICSharpCode.PythonBinding if (typeName != null) { IClass resolvedClass = GetClass(typeName); if (resolvedClass != null) { - DefaultClass dummyClass = new DefaultClass(null, "Global"); + DefaultClass dummyClass = new DefaultClass(DefaultCompilationUnit.DummyCompilationUnit, "Global"); DefaultMethod dummyMethod = new DefaultMethod(dummyClass, String.Empty); DefaultField.LocalVariableField field = new DefaultField.LocalVariableField(resolvedClass.DefaultReturnType, expression, DomRegion.Empty, dummyClass); return new LocalResolveResult(dummyMethod, field); diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseImportTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseImportTestFixture.cs index b63deebd1b..1540f8d6c3 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseImportTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Parsing/ParseImportTestFixture.cs @@ -38,13 +38,13 @@ namespace PythonBinding.Tests.Parsing [Test] public void OneUsing() { - Assert.AreEqual(1, compilationUnit.Usings.Count); + Assert.AreEqual(1, compilationUnit.UsingScope.Usings.Count); } [Test] public void UsingSystem() { - Assert.AreEqual("System", compilationUnit.Usings[0].Usings[0]); + Assert.AreEqual("System", compilationUnit.UsingScope.Usings[0].Usings[0]); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/NamespaceContentsAddedToCtrlSpaceTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/NamespaceContentsAddedToCtrlSpaceTestFixture.cs index 1e59a492d6..d5726feadd 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/NamespaceContentsAddedToCtrlSpaceTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Resolver/NamespaceContentsAddedToCtrlSpaceTestFixture.cs @@ -44,7 +44,7 @@ namespace PythonBinding.Tests.Resolver // Add usings. DefaultUsing newUsing = new DefaultUsing(cu.ProjectContent); newUsing.Usings.Add("MyNamespace"); - cu.Usings.Add(newUsing); + cu.UsingScope.Usings.Add(newUsing); results = resolver.CtrlSpace(0, "".Length, parseInfo, "", ExpressionContext.Default); } diff --git a/src/AddIns/Misc/CodeAnalysis/Src/SuppressMessageCommand.cs b/src/AddIns/Misc/CodeAnalysis/Src/SuppressMessageCommand.cs index 4009338842..fcec753620 100644 --- a/src/AddIns/Misc/CodeAnalysis/Src/SuppressMessageCommand.cs +++ b/src/AddIns/Misc/CodeAnalysis/Src/SuppressMessageCommand.cs @@ -141,11 +141,20 @@ namespace ICSharpCode.CodeAnalysis { if (CheckImports(cu.ProjectContent.DefaultImports)) return true; - foreach (IUsing u in cu.Usings) { + return CheckImports(cu.UsingScope); + } + + static bool CheckImports(IUsingScope scope) + { + foreach (IUsing u in scope.Usings) { if (CheckImports(u)) { return true; } } + foreach (IUsingScope childscope in scope.ChildScopes) { + if (CheckImports(childscope)) + return true; + } return false; } diff --git a/src/AddIns/Misc/UnitTesting/Test/Utils/MockClass.cs b/src/AddIns/Misc/UnitTesting/Test/Utils/MockClass.cs index a6c03d2b25..a126fa98ef 100644 --- a/src/AddIns/Misc/UnitTesting/Test/Utils/MockClass.cs +++ b/src/AddIns/Misc/UnitTesting/Test/Utils/MockClass.cs @@ -127,6 +127,12 @@ namespace UnitTesting.Tests.Utils } } + public IUsingScope UsingScope { + get { + throw new NotImplementedException(); + } + } + public DomRegion BodyRegion { get { throw new NotImplementedException(); diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/NamespaceRefactoringService.cs b/src/Main/Base/Project/Src/Services/RefactoringService/NamespaceRefactoringService.cs index 478fd405d0..716ea03db1 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/NamespaceRefactoringService.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/NamespaceRefactoringService.cs @@ -46,7 +46,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring if (info == null) return; ICompilationUnit cu = info.MostRecentCompilationUnit; - List newUsings = new List(cu.Usings); + List newUsings = new List(cu.UsingScope.Usings); if (sort) { newUsings.Sort(CompareUsings); } @@ -72,7 +72,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring PutEmptyLineAfterLastSystemNamespace(newUsings); } - cu.ProjectContent.Language.CodeGenerator.ReplaceUsings(new TextEditorDocument(document), cu.Usings, newUsings); + cu.ProjectContent.Language.CodeGenerator.ReplaceUsings(new TextEditorDocument(document), cu.UsingScope.Usings, newUsings); } static void PutEmptyLineAfterLastSystemNamespace(List newUsings) @@ -98,7 +98,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring IUsing newUsingDecl = new DefaultUsing(cu.ProjectContent); newUsingDecl.Usings.Add(newNamespace); - List newUsings = new List(cu.Usings); + List newUsings = new List(cu.UsingScope.Usings); if (sortExistingUsings) { newUsings.Sort(CompareUsings); } @@ -118,7 +118,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring if (sortExistingUsings) { PutEmptyLineAfterLastSystemNamespace(newUsings); } - cu.ProjectContent.Language.CodeGenerator.ReplaceUsings(new TextEditorDocument(document), cu.Usings, newUsings); + cu.ProjectContent.Language.CodeGenerator.ReplaceUsings(new TextEditorDocument(document), cu.UsingScope.Usings, newUsings); } } } diff --git a/src/Main/Base/Test/MemberLookupHelperTests.cs b/src/Main/Base/Test/MemberLookupHelperTests.cs index 7a613a2f88..9715bfc627 100644 --- a/src/Main/Base/Test/MemberLookupHelperTests.cs +++ b/src/Main/Base/Test/MemberLookupHelperTests.cs @@ -89,8 +89,8 @@ namespace ICSharpCode.SharpDevelop.Tests DefaultProjectContent dpc = new DefaultProjectContent(); dpc.ReferencedContents.Add(msc); DefaultCompilationUnit cu = new DefaultCompilationUnit(dpc); - cu.Usings.Add(new DefaultUsing(dpc, new DomRegion(1,1, 5,5))); - cu.Usings[0].Usings.Add("System.Collections.Generic"); + cu.UsingScope.Usings.Add(new DefaultUsing(dpc, new DomRegion(1,1, 5,5))); + cu.UsingScope.Usings[0].Usings.Add("System.Collections.Generic"); DefaultClass listDerivingClass = new DefaultClass(cu, "DerivesFromList"); cu.Classes.Add(listDerivingClass); @@ -108,8 +108,8 @@ namespace ICSharpCode.SharpDevelop.Tests DefaultProjectContent dpc = new DefaultProjectContent(); dpc.ReferencedContents.Add(msc); DefaultCompilationUnit cu = new DefaultCompilationUnit(dpc); - cu.Usings.Add(new DefaultUsing(dpc, new DomRegion(1,1, 5,5))); - cu.Usings[0].Usings.Add("System.Collections.Generic"); + cu.UsingScope.Usings.Add(new DefaultUsing(dpc, new DomRegion(1,1, 5,5))); + cu.UsingScope.Usings[0].Usings.Add("System.Collections.Generic"); DefaultClass listDerivingClass = new DefaultClass(cu, "DerivesFromList"); cu.Classes.Add(listDerivingClass); diff --git a/src/Main/Base/Test/SearchClassTests.cs b/src/Main/Base/Test/SearchClassTests.cs index fecbf0ae97..72cb8dad19 100644 --- a/src/Main/Base/Test/SearchClassTests.cs +++ b/src/Main/Base/Test/SearchClassTests.cs @@ -25,9 +25,9 @@ namespace ICSharpCode.SharpDevelop.Tests pc.Language = language; DefaultCompilationUnit cu = new DefaultCompilationUnit(pc); if (language == LanguageProperties.VBNet) - cu.Usings.Add(CreateUsing(pc, "syStEm")); + cu.UsingScope.Usings.Add(CreateUsing(pc, "syStEm")); else - cu.Usings.Add(CreateUsing(pc, "System")); + cu.UsingScope.Usings.Add(CreateUsing(pc, "System")); return cu; } @@ -168,7 +168,7 @@ namespace ICSharpCode.SharpDevelop.Tests ICompilationUnit cu = Prepare(LanguageProperties.CSharp); cu.ProjectContent.ReferencedContents.Add(ref1.ProjectContent); cu.ProjectContent.ReferencedContents.Add(ref2.ProjectContent); - cu.Usings.Add(new DefaultUsing(cu.ProjectContent) { Usings = { "NS1", "NS2" } }); + cu.UsingScope.Usings.Add(new DefaultUsing(cu.ProjectContent) { Usings = { "NS1", "NS2" } }); SearchTypeResult r = cu.ProjectContent.SearchType(new SearchTypeRequest("ClassName", 0, null, cu, 1, 1)); Assert.AreEqual(ModifierEnum.Public, r.Result.GetUnderlyingClass().Modifiers); diff --git a/src/Main/Base/Test/SearchGenericClassTests.cs b/src/Main/Base/Test/SearchGenericClassTests.cs index 5be3bcfc56..9a4592ed16 100644 --- a/src/Main/Base/Test/SearchGenericClassTests.cs +++ b/src/Main/Base/Test/SearchGenericClassTests.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.SharpDevelop.Tests pc.Language = language; DefaultCompilationUnit cu = new DefaultCompilationUnit(pc); if (usingMode == 1) { - cu.Usings.Add(CreateUsing(pc, "syStEm.coLLectIons")); + cu.UsingScope.Usings.Add(CreateUsing(pc, "syStEm.coLLectIons")); pc.DefaultImports = new DefaultUsing(pc); pc.DefaultImports.Usings.Add("syStEm"); pc.DefaultImports.Usings.Add("syStEm.coLLEctionS.GeNeRic"); @@ -39,9 +39,9 @@ namespace ICSharpCode.SharpDevelop.Tests pc.DefaultImports.Usings.Add("syStEm.coLLEctioNs"); pc.DefaultImports.Usings.Add("syStEm.coLLEctionS.GeNeRic"); } else { // usingMode == 0 - cu.Usings.Add(CreateUsing(pc, "System")); - cu.Usings.Add(CreateUsing(pc, "System.Collections")); - cu.Usings.Add(CreateUsing(pc, "System.Collections.Generic")); + cu.UsingScope.Usings.Add(CreateUsing(pc, "System")); + cu.UsingScope.Usings.Add(CreateUsing(pc, "System.Collections")); + cu.UsingScope.Usings.Add(CreateUsing(pc, "System.Collections.Generic")); } return cu; } diff --git a/src/Main/Base/Test/Utils/MockClass.cs b/src/Main/Base/Test/Utils/MockClass.cs index a755da9d8c..168a6dc659 100644 --- a/src/Main/Base/Test/Utils/MockClass.cs +++ b/src/Main/Base/Test/Utils/MockClass.cs @@ -61,6 +61,12 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils } } + public IUsingScope UsingScope { + get { + throw new NotImplementedException(); + } + } + public DomRegion Region { get { throw new NotImplementedException(); diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj index 884f25252e..ce66364903 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj @@ -88,6 +88,7 @@ + @@ -102,6 +103,7 @@ + diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CtrlSpaceResolveHelper.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CtrlSpaceResolveHelper.cs index 2f31ce0dd1..c45c425c57 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CtrlSpaceResolveHelper.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CtrlSpaceResolveHelper.cs @@ -84,7 +84,7 @@ namespace ICSharpCode.SharpDevelop.Dom { IProjectContent projectContent = cu.ProjectContent; projectContent.AddNamespaceContents(result, "", projectContent.Language, true); - foreach (IUsing u in cu.Usings) { + foreach (IUsing u in cu.GetAllUsings()) { AddUsing(result, u, projectContent); } AddUsing(result, projectContent.DefaultImports, projectContent); diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ExtensionMethods.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ExtensionMethods.cs index b392ca692d..05743586b8 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ExtensionMethods.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ExtensionMethods.cs @@ -8,6 +8,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Linq; namespace ICSharpCode.SharpDevelop.Dom { @@ -27,5 +28,33 @@ namespace ICSharpCode.SharpDevelop.Dom foreach (T o in elements) list.Add(o); } + + public static IEnumerable Flatten(this IEnumerable input, Func> recursion) + { + Stack> stack = new Stack>(); + try { + stack.Push(input.GetEnumerator()); + while (stack.Count > 0) { + while (stack.Peek().MoveNext()) { + T element = stack.Peek().Current; + yield return element; + IEnumerable children = recursion(element); + if (children != null) { + stack.Push(children.GetEnumerator()); + } + } + stack.Pop(); + } + } finally { + while (stack.Count > 0) { + stack.Pop().Dispose(); + } + } + } + + public static IEnumerable GetAllUsings(this ICompilationUnit cu) + { + return (new[]{cu.UsingScope}).Flatten(s=>s.ChildScopes).SelectMany(s=>s.Usings); + } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractEntity.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractEntity.cs index 9854bcac23..0d7e2f2649 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractEntity.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractEntity.cs @@ -18,9 +18,9 @@ namespace ICSharpCode.SharpDevelop.Dom IClass declaringType; - string fullyQualifiedName = null; - string name = null; - string nspace = null; + string fullyQualifiedName; + string name; + string nspace; public AbstractEntity(IClass declaringType) { @@ -29,11 +29,10 @@ namespace ICSharpCode.SharpDevelop.Dom public AbstractEntity(IClass declaringType, string name) { - if (declaringType == null) - throw new ArgumentNullException("declaringType"); this.declaringType = declaringType; this.name = name; - nspace = declaringType.FullyQualifiedName; + if (declaringType != null) + nspace = declaringType.FullyQualifiedName; // lazy-computing the fully qualified name for class members saves ~7 MB RAM (when loading the SharpDevelop solution). //fullyQualifiedName = nspace + '.' + name; diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs index 05b2e505d7..20b8f45561 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs @@ -26,6 +26,7 @@ namespace ICSharpCode.SharpDevelop.Dom IList methods; IList events; IList typeParameters; + IUsingScope usingScope; protected override void FreezeInternal() { @@ -119,23 +120,47 @@ namespace ICSharpCode.SharpDevelop.Dom } } + /// + /// Gets the using scope of contains this class. + /// + public IUsingScope UsingScope { + get { return usingScope; } + set { + if (value == null) + throw new ArgumentNullException("UsingScope"); + CheckBeforeMutation(); + usingScope = value; + } + } + public DefaultClass(ICompilationUnit compilationUnit, string fullyQualifiedName) : base(null) { + if (compilationUnit == null) + throw new ArgumentNullException("compilationUnit"); + if (fullyQualifiedName == null) + throw new ArgumentNullException("fullyQualifiedName"); this.compilationUnit = compilationUnit; this.FullyQualifiedName = fullyQualifiedName; + this.UsingScope = compilationUnit.UsingScope; } public DefaultClass(ICompilationUnit compilationUnit, IClass declaringType) : base(declaringType) { + if (compilationUnit == null) + throw new ArgumentNullException("compilationUnit"); this.compilationUnit = compilationUnit; + this.UsingScope = compilationUnit.UsingScope; } public DefaultClass(ICompilationUnit compilationUnit, ClassType classType, ModifierEnum modifiers, DomRegion region, IClass declaringType) : base(declaringType) { + if (compilationUnit == null) + throw new ArgumentNullException("compilationUnit"); this.compilationUnit = compilationUnit; this.region = region; this.classType = classType; Modifiers = modifiers; + this.UsingScope = compilationUnit.UsingScope; } // fields must be volatile to ensure that the optimizer doesn't reorder accesses to it diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultCompilationUnit.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultCompilationUnit.cs index ebdab76fbc..6d04376cb0 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultCompilationUnit.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultCompilationUnit.cs @@ -21,7 +21,7 @@ namespace ICSharpCode.SharpDevelop.Dom return this; } - IList usings = new List(); + IUsingScope usingScope = new DefaultUsingScope(); IList classes = new List(); IList attributes = new List(); IList foldingRegions = new List(); @@ -30,11 +30,11 @@ namespace ICSharpCode.SharpDevelop.Dom protected override void FreezeInternal() { // Deep Freeze: freeze lists and their contents - usings = FreezeList(usings); classes = FreezeList(classes); attributes = FreezeList(attributes); foldingRegions = FreezeList(foldingRegions); tagComments = FreezeList(tagComments); + usingScope.Freeze(); base.FreezeInternal(); } @@ -85,9 +85,13 @@ namespace ICSharpCode.SharpDevelop.Dom } } - public virtual IList Usings { - get { - return usings; + public virtual IUsingScope UsingScope { + get { return usingScope; } + set { + if (value == null) + throw new ArgumentNullException("UsingScope"); + CheckBeforeMutation(); + usingScope = value; } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultUsingScope.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultUsingScope.cs new file mode 100644 index 0000000000..2d71d369a1 --- /dev/null +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultUsingScope.cs @@ -0,0 +1,70 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.SharpDevelop.Dom +{ + public class DefaultUsingScope : AbstractFreezable, IUsingScope + { + DomRegion region; + IUsingScope parent; + IList usings; + IList childScopes; + string namespaceName = ""; + + protected override void FreezeInternal() + { + base.FreezeInternal(); + usings = FreezeList(usings); + childScopes = FreezeList(childScopes); + } + + public DomRegion Region { + get { return region; } + set { + CheckBeforeMutation(); + region = value; + } + } + + public IUsingScope Parent { + get { return parent; } + set { + CheckBeforeMutation(); + parent = value; + } + } + + public virtual IList Usings { + get { + if (usings == null) + usings = new List(); + return usings; + } + } + + public virtual IList ChildScopes { + get { + if (childScopes == null) + childScopes = new List(); + return childScopes; + } + } + + public string NamespaceName { + get { return namespaceName; } + set { + if (value == null) + throw new ArgumentNullException("NamespaceName"); + CheckBeforeMutation(); + namespaceName = value; + } + } + } +} diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IClass.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IClass.cs index 33d5c68160..591a3bc333 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IClass.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IClass.cs @@ -43,6 +43,13 @@ namespace ICSharpCode.SharpDevelop.Dom get; } + /// + /// Gets the using scope of contains this class. + /// + IUsingScope UsingScope { + get; + } + IList BaseTypes { get; } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/ICompilationUnit.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/ICompilationUnit.cs index 565a8fa39a..a8e8076f13 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/ICompilationUnit.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/ICompilationUnit.cs @@ -30,7 +30,11 @@ namespace ICSharpCode.SharpDevelop.Dom get; } - IList Usings { + /// + /// Gets the main using scope of the compilation unit. + /// That scope usually represents the root namespace. + /// + IUsingScope UsingScope { get; } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IUsingScope.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IUsingScope.cs new file mode 100644 index 0000000000..bde090311a --- /dev/null +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IUsingScope.cs @@ -0,0 +1,46 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.SharpDevelop.Dom +{ + /// + /// A scope that can contain using declarations. + /// In C#, every file is a using scope, and every "namespace" declaration inside + /// the file is a nested using scope. + /// + public interface IUsingScope : IFreezable + { + /// + /// Gets the region of the using scope. + /// + DomRegion Region { get; } + + /// + /// Gets the parent scope. + /// Returns null if this is a root scope. + /// + IUsingScope Parent { get; } + + /// + /// Gets the usings in this using scope. + /// + IList Usings { get; } + + /// + /// Gets the list of child scopes. Child scopes usually represent "namespace" declarations. + /// + IList ChildScopes { get; } + + /// + /// Gets the name of the namespace represented by the using scope. + /// + string NamespaceName { get; } + } +} diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs index 70f8221ac4..163e7bba92 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs @@ -19,8 +19,8 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver { public class NRefactoryASTConvertVisitor : AbstractAstVisitor { - ICompilationUnit cu; - Stack currentNamespace = new Stack(); + DefaultCompilationUnit cu; + DefaultUsingScope currentNamespace; Stack currentClass = new Stack(); public string VBRootNamespace { get; set; } @@ -181,13 +181,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (compilationUnit == null) { return null; } + currentNamespace = new DefaultUsingScope(); if (!string.IsNullOrEmpty(VBRootNamespace)) { - currentNamespace.Push(VBRootNamespace); - compilationUnit.AcceptChildren(this, data); - currentNamespace.Pop(); - } else { - compilationUnit.AcceptChildren(this, data); + currentNamespace.NamespaceName = VBRootNamespace; } + cu.UsingScope = currentNamespace; + compilationUnit.AcceptChildren(this, data); return cu; } @@ -197,7 +196,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver foreach (AST.Using u in usingDeclaration.Usings) { u.AcceptVisitor(this, us); } - cu.Usings.Add(us); + currentNamespace.Usings.Add(us); return data; } @@ -313,18 +312,24 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return null; } + string PrependCurrentNamespace(string name) + { + if (string.IsNullOrEmpty(currentNamespace.NamespaceName)) + return name; + else + return currentNamespace.NamespaceName + "." + name; + } + public override object VisitNamespaceDeclaration(AST.NamespaceDeclaration namespaceDeclaration, object data) { - string name; - if (currentNamespace.Count == 0) { - name = namespaceDeclaration.Name; - } else { - name = currentNamespace.Peek() + '.' + namespaceDeclaration.Name; - } - - currentNamespace.Push(name); + DefaultUsingScope oldNamespace = currentNamespace; + currentNamespace = new DefaultUsingScope { + Parent = oldNamespace, + NamespaceName = PrependCurrentNamespace(namespaceDeclaration.Name), + }; + oldNamespace.ChildScopes.Add(currentNamespace); object ret = namespaceDeclaration.AcceptChildren(this, data); - currentNamespace.Pop(); + currentNamespace = oldNamespace; return ret; } @@ -364,13 +369,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver cur.InnerClasses.Add(c); c.FullyQualifiedName = cur.FullyQualifiedName + '.' + typeDeclaration.Name; } else { - if (currentNamespace.Count == 0) { - c.FullyQualifiedName = typeDeclaration.Name; - } else { - c.FullyQualifiedName = currentNamespace.Peek() + '.' + typeDeclaration.Name; - } + c.FullyQualifiedName = PrependCurrentNamespace(typeDeclaration.Name); cu.Classes.Add(c); } + c.UsingScope = currentNamespace; currentClass.Push(c); ConvertTemplates(typeDeclaration.Templates, c); // resolve constrains in context of the class @@ -468,13 +470,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver cur.InnerClasses.Add(c); c.FullyQualifiedName = cur.FullyQualifiedName + '.' + name; } else { - if (currentNamespace.Count == 0) { - c.FullyQualifiedName = name; - } else { - c.FullyQualifiedName = currentNamespace.Peek() + '.' + name; - } + c.FullyQualifiedName = PrependCurrentNamespace(name); cu.Classes.Add(c); } + c.UsingScope = currentNamespace; currentClass.Push(c); // necessary for CreateReturnType ConvertTemplates(templates, c); diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs index 4d4744c509..54629bb82e 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs @@ -205,7 +205,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } else if ("global".Equals(expression, StringComparison.InvariantCultureIgnoreCase)) { return new NamespaceResolveResult(null, null, ""); } - // array + // array } else if (language == NR.SupportedLanguage.CSharp && expressionResult.Context.IsTypeContext && !expressionResult.Context.IsObjectCreation) { expr = ParseTypeReference(expression); } @@ -596,16 +596,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } if (languageProperties.CanImportClasses) { - foreach (IUsing @using in cu.Usings) { - foreach (string import in @using.Usings) { - IClass c = GetClass(import, 0); - if (c != null) { - ResolveResult rr = ResolveMember(c.DefaultReturnType, identifier, - identifierExpression.TypeArguments, - IsInvoked(identifierExpression), - false, null); - if (rr != null && rr.IsValid) - return rr; + IUsingScope scope = callingClass != null ? callingClass.UsingScope : cu.UsingScope; + for (; scope != null; scope = scope.Parent) { + foreach (IUsing @using in scope.Usings) { + foreach (string import in @using.Usings) { + IClass c = GetClass(import, 0); + if (c != null) { + ResolveResult rr = ResolveMember(c.DefaultReturnType, identifier, + identifierExpression.TypeArguments, + IsInvoked(identifierExpression), + false, null); + if (rr != null && rr.IsValid) + return rr; + } } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs index a9d66b7090..fbdeaf2a62 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs @@ -238,7 +238,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// private class GenericClassContainer : DefaultClass { - public GenericClassContainer(string fullyQualifiedName) : base(null, fullyQualifiedName) {} + public GenericClassContainer(string fullyQualifiedName) : base(DefaultCompilationUnit.DummyCompilationUnit, fullyQualifiedName) {} IClass[] realClasses = new IClass[4]; @@ -744,7 +744,7 @@ namespace ICSharpCode.SharpDevelop.Dom return null; } - foreach (IUsing u in unit.Usings) { + foreach (IUsing u in unit.GetAllUsings()) { if (u != null) { string nameSpace = u.SearchNamespace(name); if (nameSpace != null) { @@ -854,7 +854,7 @@ namespace ICSharpCode.SharpDevelop.Dom } if (request.CurrentCompilationUnit != null) { // Combine name with usings - foreach (IUsing u in request.CurrentCompilationUnit.Usings) { + foreach (IUsing u in request.CurrentCompilationUnit.GetAllUsings()) { if (u != null) { foreach (IReturnType r in u.SearchType(name, request.TypeParameterCount)) { if (MatchesRequest(ref request, r)) { diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/NRefactoryRefactoringProvider.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/NRefactoryRefactoringProvider.cs index bd76590c25..e5a1a0462a 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/NRefactoryRefactoringProvider.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/NRefactoryRefactoringProvider.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using ICSharpCode.NRefactory.Ast; @@ -510,7 +511,8 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring if (tr.ExtensionMethod != null) { // the invocation of an extension method can implicitly use a using StringComparer nameComparer = cu.ProjectContent.Language.NameComparer; - foreach (IUsing import in cu.Usings) { + // go through all usings in all nested child scopes + foreach (IUsing import in cu.GetAllUsings()) { foreach (string i in import.Usings) { if (nameComparer.Equals(tr.ExtensionMethod.DeclaringType.Namespace, i)) { usedUsings.Add(import); @@ -528,7 +530,7 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring } List unusedUsings = new List(); - foreach (IUsing import in cu.Usings) { + foreach (IUsing import in cu.GetAllUsings()) { if (!usedUsings.Contains(import)) { if (import.HasAliases) { foreach (string key in import.Aliases.Keys) {