From 4c1a238309296b13aefc790598aafddc46190765 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 25 Jul 2005 09:20:43 +0000 Subject: [PATCH] Improved support for partial classes. Improved C# new completion. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@247 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/CSharpCompletionBinding.cs | 20 +++- .../Project/Src/Parser/ExpressionFinder.cs | 97 ++++++++++++++++-- .../Project/Src/Parser/Parser.cs | 7 +- .../Project/Src/MyNamespaceBuilder.cs | 8 +- .../VBNetBinding/Project/Src/Parser/Parser.cs | 7 +- .../Project/ICSharpCode.SharpDevelop.csproj | 9 +- src/Main/Base/Project/Src/Dom/ClassFinder.cs | 78 +++++++++++++++ src/Main/Base/Project/Src/Dom/IClass.cs | 2 +- src/Main/Base/Project/Src/Dom/IParser.cs | 4 +- .../Implementations/AbstractNamedEntity.cs | 7 ++ .../Src/Dom/Implementations/CompoundClass.cs | 8 ++ .../Src/Dom/Implementations/DefaultClass.cs | 57 +++++++++-- .../Dom/Implementations/GetClassReturnType.cs | 19 ++-- .../NRefactoryResolver/NRefactoryResolver.cs | 15 +-- .../Src/Dom/NRefactoryResolver/TypeVisitor.cs | 2 +- .../Dom/ReflectionLayer/ReflectionClass.cs | 2 + .../Services/ParserService/ParserService.cs | 19 +++- .../Gui/Editor/QuickClassBrowserPanel.cs | 98 +++++++++++++------ 18 files changed, 371 insertions(+), 88 deletions(-) create mode 100644 src/Main/Base/Project/Src/Dom/ClassFinder.cs diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs index fcc54d9561..1cb3eede32 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs @@ -29,7 +29,7 @@ namespace CSharpBinding { if (!CheckExtension(editor)) return false; - CSharpBinding.Parser.ExpressionFinder ef = new CSharpBinding.Parser.ExpressionFinder(); + Parser.ExpressionFinder ef = new Parser.ExpressionFinder(editor.FileName); int cursor = editor.ActiveTextAreaControl.Caret.Offset; ExpressionContext context = null; if (ch == '(') { @@ -175,11 +175,25 @@ namespace CSharpBinding editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(ExpressionContext.Type), ' '); return true; case "new": - editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(ExpressionContext.ObjectCreation), ' '); - return true; + return ShowNewCompletion(editor); + case "override": + // TODO: Suggest list of virtual methods to override + return false; default: return base.HandleKeyword(editor, word); } } + + bool ShowNewCompletion(SharpDevelopTextAreaControl editor) + { + Parser.ExpressionFinder ef = new Parser.ExpressionFinder(editor.FileName); + int cursor = editor.ActiveTextAreaControl.Caret.Offset; + ExpressionContext context = ef.FindExpression(editor.Document.GetText(0, cursor) + " T.", cursor + 2).Context; + if (context.IsObjectCreation) { + editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(context), ' '); + return true; + } + return false; + } } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs index e08c6b22f4..8d6458cd48 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs @@ -7,6 +7,7 @@ using System; using System.Text; +using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Dom; namespace CSharpBinding.Parser @@ -16,6 +17,13 @@ namespace CSharpBinding.Parser /// public class ExpressionFinder : IExpressionFinder { + string fileName; + + public ExpressionFinder(string fileName) + { + this.fileName = fileName; + } + #region Capture Context ExpressionResult CreateResult(string expression, string inText, int offset) { @@ -23,13 +31,60 @@ namespace CSharpBinding.Parser return new ExpressionResult(null); if (expression.StartsWith("using ")) return new ExpressionResult(expression.Substring(6).TrimStart(), ExpressionContext.Namespace, null); - if (!hadParenthesis && expression.StartsWith("new ")) - return new ExpressionResult(expression.Substring(4).TrimStart(), ExpressionContext.ObjectCreation, null); + if (!hadParenthesis && expression.StartsWith("new ")) { + return new ExpressionResult(expression.Substring(4).TrimStart(), GetCreationContext(), null); + } if (IsInAttribute(inText, offset)) return new ExpressionResult(expression, ExpressionContext.Attribute); return new ExpressionResult(expression); } + ExpressionContext GetCreationContext() + { + UnGetToken(); + if (GetNextNonWhiteSpace() == '=') { // was: "= new" + ReadNextToken(); + if (curTokenType == Ident) { // was: "ident = new" + int typeEnd = offset; + ReadNextToken(); + int typeStart = -1; + while (curTokenType == Ident) { + typeStart = offset + 1; + ReadNextToken(); + if (curTokenType == Dot) { + ReadNextToken(); + } else { + break; + } + } + if (typeStart >= 0) { + string className = text.Substring(typeStart, typeEnd - typeStart); + int pos = className.IndexOf('<'); + string nonGenericClassName; + if (pos > 0) + nonGenericClassName = className.Substring(0, pos); + else + nonGenericClassName = className; + ClassFinder finder = new ClassFinder(fileName, text, typeStart); + IClass c = finder.SearchClass(nonGenericClassName); + if (c != null) { + ExpressionContext context = ExpressionContext.TypeDerivingFrom(c, true); + if (context.ShowEntry(c)) + context.SuggestedItem = c; + return context; + } + } + } + } else { + UnGet(); + ReadNextToken(); + if (curTokenType == Ident && lastIdentifier == "throw") { + return ExpressionContext.TypeDerivingFrom(ProjectContentRegistry.Mscorlib.GetClass("System.Exception"), true); + } + } + return ExpressionContext.ObjectCreation; + } + bool IsInAttribute(string txt, int offset) { // Get line start: @@ -93,6 +148,7 @@ namespace CSharpBinding.Parser lastAccept = this.offset; } if (state == ACCEPTNOMORE) { + lastExpressionStartPosition = offset + 1; return this.text.Substring(this.offset + 1, offset - this.offset); } } @@ -100,12 +156,16 @@ namespace CSharpBinding.Parser if (lastAccept < 0) return null; + lastExpressionStartPosition = lastAccept + 1; + return this.text.Substring(this.lastAccept + 1, offset - this.lastAccept); } + int lastExpressionStartPosition; + internal int LastExpressionStartPosition { get { - return ((state == ACCEPTNOMORE) ? offset : lastAccept) + 1; + return lastExpressionStartPosition; } } #endregion @@ -421,6 +481,15 @@ namespace CSharpBinding.Parser return '\0'; } + char GetNextNonWhiteSpace() + { + char ch; + do { + ch = GetNext(); + } while (char.IsWhiteSpace(ch)); + return ch; + } + char Peek(int n) { if (offset - n >= 0) { @@ -442,6 +511,13 @@ namespace CSharpBinding.Parser ++offset; } + void UnGetToken() + { + do { + UnGet(); + } while (char.IsLetterOrDigit(Peek())); + } + // tokens for our lexer static int Err = 0; static int Dot = 1; @@ -470,17 +546,17 @@ namespace CSharpBinding.Parser /// bool hadParenthesis; + string lastIdentifier; + void ReadNextToken() { - char ch; + curTokenType = Err; - do { - ch = GetNext(); - if (ch == '\0') { - return; - } - } while (Char.IsWhiteSpace(ch)); + char ch = GetNextNonWhiteSpace(); + if (ch == '\0') { + return; + } switch (ch) { @@ -537,6 +613,7 @@ namespace CSharpBinding.Parser break; default: curTokenType = Ident; + lastIdentifier = ident; break; } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs index 3468bae754..710f5ec027 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs @@ -32,10 +32,9 @@ namespace CSharpBinding.Parser } } - public IExpressionFinder ExpressionFinder { - get { - return new ExpressionFinder(); - } + public IExpressionFinder CreateExpressionFinder(string fileName) + { + return new ExpressionFinder(fileName); } public bool CanParse(string fileName) diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs index eaf4953c52..797a722d70 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs @@ -114,8 +114,14 @@ namespace VBNetBinding public override List Properties { get { List properties = new List(); + IProjectContent pc = ProjectContentRegistry.GetExistingProjectContent(new System.Reflection.AssemblyName("System.Windows.Forms")); + if (pc == null) + return properties; + IClass formClass = pc.GetClass("System.Windows.Forms.Form"); + if (formClass == null) + return properties; foreach (IClass c in this.ProjectContent.Classes) { - if (c.BaseTypes.Contains("System.Windows.Forms.Form")) { + if (c.BaseClass == formClass) { properties.Add(new DefaultProperty(c.Name, new GetClassReturnType(this.ProjectContent, c.FullyQualifiedName), ModifierEnum.Public | ModifierEnum.Static, diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs index 76e6a07811..edabed1545 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs @@ -35,12 +35,9 @@ namespace VBNetBinding.Parser } } - public IExpressionFinder ExpressionFinder + public IExpressionFinder CreateExpressionFinder(string fileName) { - get - { - return new ExpressionFinder(); - } + return new ExpressionFinder(); } public bool CanParse(string fileName) diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 84accce237..56e86eb28f 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -183,7 +183,7 @@ UserControl - Form + UserControl @@ -202,7 +202,7 @@ Form - Component + Form Form @@ -267,7 +267,7 @@ Form - UserControl + Component @@ -682,6 +682,7 @@ + @@ -702,4 +703,4 @@ - \ No newline at end of file + diff --git a/src/Main/Base/Project/Src/Dom/ClassFinder.cs b/src/Main/Base/Project/Src/Dom/ClassFinder.cs new file mode 100644 index 0000000000..9028ed4b04 --- /dev/null +++ b/src/Main/Base/Project/Src/Dom/ClassFinder.cs @@ -0,0 +1,78 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using ICSharpCode.Core; + +namespace ICSharpCode.SharpDevelop.Dom +{ + /// + /// Interface for objects that can find classes. + /// + public class ClassFinder + { + int caretLine, caretColumn; + ICompilationUnit cu; + IClass callingClass; + IProjectContent projectContent; + + public ClassFinder(string fileName, string fileContent, int offset) + { + caretLine = 0; + caretColumn = 0; + for (int i = 0; i < offset; i++) { + if (fileContent[i] == '\n') { + caretLine++; + caretColumn = 0; + } else { + caretColumn++; + } + } + Init(fileName); + } + + public ClassFinder(string fileName, int caretLineNumber, int caretColumn) + { + this.caretLine = caretLineNumber; + this.caretColumn = caretColumn; + + Init(fileName); + } + + void Init(string fileName) + { + ParseInformation parseInfo = ParserService.GetParseInformation(fileName); + if (parseInfo == null) { + return; + } + + cu = parseInfo.MostRecentCompilationUnit; + + if (cu != null) { + callingClass = cu.GetInnermostClass(caretLine, caretColumn); + projectContent = cu.ProjectContent; + } else { + projectContent = ParserService.CurrentProjectContent; + } + } + + public IClass GetClass(string fullName) + { + return projectContent.GetClass(fullName); + } + + public IClass SearchClass(string name) + { + return projectContent.SearchType(name, callingClass, cu, caretLine, caretColumn); + } + + public string SearchNamespace(string name) + { + return projectContent.SearchNamespace(name, callingClass, cu, caretLine, caretColumn); + } + } +} diff --git a/src/Main/Base/Project/Src/Dom/IClass.cs b/src/Main/Base/Project/Src/Dom/IClass.cs index e644d8ef2b..d0e94afd65 100644 --- a/src/Main/Base/Project/Src/Dom/IClass.cs +++ b/src/Main/Base/Project/Src/Dom/IClass.cs @@ -94,7 +94,7 @@ namespace ICSharpCode.SharpDevelop.Dom get; } - IEnumerable ClassInheritanceTree { + IEnumerable ClassInheritanceTree { get; } diff --git a/src/Main/Base/Project/Src/Dom/IParser.cs b/src/Main/Base/Project/Src/Dom/IParser.cs index 10cc49e47b..718837162a 100644 --- a/src/Main/Base/Project/Src/Dom/IParser.cs +++ b/src/Main/Base/Project/Src/Dom/IParser.cs @@ -21,9 +21,7 @@ namespace ICSharpCode.SharpDevelop.Dom set; } - IExpressionFinder ExpressionFinder { - get; - } + IExpressionFinder CreateExpressionFinder(string fileName); /// /// Gets if the parser can parse the specified file. diff --git a/src/Main/Base/Project/Src/Dom/Implementations/AbstractNamedEntity.cs b/src/Main/Base/Project/Src/Dom/Implementations/AbstractNamedEntity.cs index ba94ad2241..c693e2c708 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/AbstractNamedEntity.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/AbstractNamedEntity.cs @@ -27,12 +27,19 @@ namespace ICSharpCode.SharpDevelop.Dom return fullyQualifiedName; } set { + if (fullyQualifiedName == value) + return; fullyQualifiedName = value; name = null; nspace = null; + OnFullyQualifiedNameChanged(EventArgs.Empty); } } + protected virtual void OnFullyQualifiedNameChanged(EventArgs e) + { + } + public virtual string DotNetName { get { if (this.DeclaringType != null) { diff --git a/src/Main/Base/Project/Src/Dom/Implementations/CompoundClass.cs b/src/Main/Base/Project/Src/Dom/Implementations/CompoundClass.cs index 0f8d044b74..1016b5e416 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/CompoundClass.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/CompoundClass.cs @@ -61,6 +61,14 @@ namespace ICSharpCode.SharpDevelop.Dom this.Modifiers = modifier; } + /// + /// CompoundClass has a normal return type even though IsPartial is set. + /// + protected override IReturnType CreateDefaultReturnType() + { + return new DefaultReturnType(this); + } + public override List InnerClasses { get { List l = new List(); diff --git a/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs b/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs index 3e0ff92ba1..3444ad694b 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs @@ -64,7 +64,20 @@ namespace ICSharpCode.SharpDevelop.Dom protected virtual IReturnType CreateDefaultReturnType() { - return new DefaultReturnType(this); + if (IsPartial) { + return new GetClassReturnType(ProjectContent, FullyQualifiedName); + } else { + return new DefaultReturnType(this); + } + } + + protected override void OnFullyQualifiedNameChanged(EventArgs e) + { + base.OnFullyQualifiedNameChanged(e); + GetClassReturnType rt = defaultReturnType as GetClassReturnType; + if (rt != null) { + rt.SetFullyQualifiedName(FullyQualifiedName); + } } public ICompilationUnit CompilationUnit { @@ -207,16 +220,23 @@ namespace ICSharpCode.SharpDevelop.Dom return CompareTo((IClass)o); } - // TODO: Cache ClassInheritanceTree as it is called many times (for GetFields(), GetProperties() etc.) - // and it is expensive to execute SearchType so often. - // ReflectionClass should cache it forever; DefaultClass only as long as no new CompilationUnits - // are created. - public IEnumerable ClassInheritanceTree { + List inheritanceTreeCache; + + public IEnumerable ClassInheritanceTree { get { - return new ClassInheritanceEnumerator(this); + if (UseInheritanceCache) { + if (inheritanceTreeCache == null) { + inheritanceTreeCache = new List(new ClassInheritanceEnumerator(this)); + } + return inheritanceTreeCache; + } else { + return new ClassInheritanceEnumerator(this); + } } } + protected bool UseInheritanceCache = false; + protected override bool CanBeSubclass { get { return true; @@ -238,13 +258,19 @@ namespace ICSharpCode.SharpDevelop.Dom } } + IClass cachedBaseClass; + public IClass BaseClass { get { Debug.Assert(ProjectContent != null); if (BaseTypes.Count > 0) { + if (UseInheritanceCache && cachedBaseClass != null) + return cachedBaseClass; IClass baseClass = GetBaseClass(0); if (baseClass != null && baseClass.ClassType != ClassType.Interface) { + if (UseInheritanceCache) + cachedBaseClass = baseClass; return baseClass; } } @@ -397,7 +423,7 @@ namespace ICSharpCode.SharpDevelop.Dom return members; } - public class ClassInheritanceEnumerator : IEnumerator, IEnumerable + public class ClassInheritanceEnumerator : IEnumerator, IEnumerable { IClass topLevelClass; IClass currentClass = null; @@ -423,7 +449,12 @@ namespace ICSharpCode.SharpDevelop.Dom baseTypeQueue.Enqueue(new BaseType(null, "System.Object")); } - public IEnumerator GetEnumerator() + public IEnumerator GetEnumerator() + { + return this; + } + + IEnumerator IEnumerable.GetEnumerator() { return this; } @@ -494,6 +525,14 @@ namespace ICSharpCode.SharpDevelop.Dom PutBaseClassesOnStack(topLevelClass); baseTypeQueue.Enqueue(new BaseType(null, "System.Object")); } + + public void Dispose() + { + baseTypeQueue = null; + finishedClasses = null; + topLevelClass = null; + currentClass = null; + } } } } diff --git a/src/Main/Base/Project/Src/Dom/Implementations/GetClassReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/GetClassReturnType.cs index 7f60036b83..9c926d3fd1 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/GetClassReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/GetClassReturnType.cs @@ -24,12 +24,7 @@ namespace ICSharpCode.SharpDevelop.Dom public GetClassReturnType(IProjectContent content, string fullName) { this.content = content; - this.fullName = fullName; - int pos = fullName.LastIndexOf('.'); - if (pos < 0) - shortName = fullName; - else - shortName = fullName.Substring(pos + 1); + SetFullyQualifiedName(fullName); } public override bool IsDefaultReturnType { @@ -70,6 +65,18 @@ namespace ICSharpCode.SharpDevelop.Dom } } + public void SetFullyQualifiedName(string fullName) + { + if (fullName == null) + throw new ArgumentNullException("fullName"); + this.fullName = fullName; + int pos = fullName.LastIndexOf('.'); + if (pos < 0) + shortName = fullName; + else + shortName = fullName.Substring(pos + 1); + } + public override string Name { get { return shortName; diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs index 69ba59245d..cccf7c884c 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs @@ -134,7 +134,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (cu != null) { callingClass = cu.GetInnermostClass(caretLine, caretColumn); - cu.FileName = fileName; } Expression expr = null; @@ -195,12 +194,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver { if (name == null) return null; - IClass c = SearchType(name); + IClass c = SearchClass(name); if (c != null) { if (c.IsTypeInInheritanceTree(ProjectContentRegistry.Mscorlib.GetClass("System.Attribute"))) return c; } - return SearchType(name + "Attribute"); + return SearchClass(name + "Attribute"); } ResolveResult ResolveAttribute(Expression expr) @@ -443,7 +442,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver ResolveResult result2 = null; - IClass c = SearchType(identifier); + IClass c = SearchClass(identifier); if (c != null) { result2 = new TypeResolveResult(callingClass, callingMember, c); } else { @@ -643,10 +642,15 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return projectContent.SearchNamespace(name, callingClass, cu, caretLine, caretColumn); } + public IClass GetClass(string fullName) + { + return projectContent.GetClass(fullName); + } + /// /// use the usings and the name of the namespace to find a class /// - public IClass SearchType(string name) + public IClass SearchClass(string name) { return projectContent.SearchType(name, callingClass, cu, caretLine, caretColumn); } @@ -869,7 +873,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (cu != null) { callingClass = cu.GetInnermostClass(caretLine, caretColumn); - cu.FileName = fileName; } callingMember = GetCurrentMember(); diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs index 9de72f6249..03c7acdc60 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs @@ -290,7 +290,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (name != null && name.Length > 0) { return new NamespaceReturnType(name); } - IClass c = resolver.SearchType(identifierExpression.Identifier); + IClass c = resolver.SearchClass(identifierExpression.Identifier); if (c != null) { return c.DefaultReturnType; } diff --git a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionClass.cs b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionClass.cs index bd43e21d9f..6653ea4533 100644 --- a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionClass.cs +++ b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionClass.cs @@ -182,6 +182,8 @@ namespace ICSharpCode.SharpDevelop.Dom FullyQualifiedName = name; } + this.UseInheritanceCache = true; + try { AddAttributes(compilationUnit.ProjectContent, this.Attributes, CustomAttributeData.GetCustomAttributes(type)); } catch (Exception ex) { diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index ed39362322..33be0e5b0e 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -128,7 +128,7 @@ namespace ICSharpCode.Core ParseProjectContent newContent = project.CreateProjectContent(); lock (projectContents) { projectContents[project] = newContent; - } + } createdContents.Add(newContent); } catch (Exception e) { Console.WriteLine("Error while retrieving project contents from {0}:", project); @@ -399,7 +399,7 @@ namespace ICSharpCode.Core { IParser parser = GetParser(fileName); if (parser != null) { - return parser.ExpressionFinder; + return parser.CreateExpressionFinder(fileName); } return null; } @@ -434,15 +434,24 @@ namespace ICSharpCode.Core return null; } + public static IResolver CreateResolver(string fileName) + { + IParser parser = GetParser(fileName); + if (parser != null) { + return parser.CreateResolver(); + } + return null; + } + public static ResolveResult Resolve(ExpressionResult expressionResult, int caretLineNumber, int caretColumn, string fileName, string fileContent) { - IParser parser = GetParser(fileName); - if (parser != null) { - return parser.CreateResolver().Resolve(expressionResult, caretLineNumber, caretColumn, fileName, fileContent); + IResolver resolver = CreateResolver(fileName); + if (resolver != null) { + return resolver.Resolve(expressionResult, caretLineNumber, caretColumn, fileName, fileContent); } return null; } diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/QuickClassBrowserPanel.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/QuickClassBrowserPanel.cs index ff06678b2a..4ebf566a32 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/QuickClassBrowserPanel.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/QuickClassBrowserPanel.cs @@ -31,6 +31,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor object item; string text; int iconIndex; + bool isInCurrentPart; public int IconIndex { get { @@ -44,6 +45,12 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } } + public bool IsInCurrentPart { + get { + return isInCurrentPart; + } + } + public IRegion ItemRegion { get { IClass classItem = item as IClass; @@ -86,15 +93,18 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } } - public ComboBoxItem(object item, string text, int iconIndex) + public ComboBoxItem(object item, string text, int iconIndex, bool isInCurrentPart) { this.item = item; this.text = text; this.iconIndex = iconIndex; + this.isInCurrentPart = isInCurrentPart; } public bool IsInside(int lineNumber) { + if (!isInCurrentPart) + return false; IClass classItem = item as IClass; if (classItem != null) { if (classItem.Region == null) @@ -224,7 +234,9 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor UpdateClassComboBox(); UpdateMembersComboBox(); } - } catch (Exception) {} + } catch (Exception ex) { + MessageService.ShowError(ex); + } } bool membersComboBoxSelectedMember = false; @@ -323,51 +335,62 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor return false; } + IClass lastClassInMembersComboBox; + void FillMembersComboBox() { IClass c = GetCurrentSelectedClass(); - if (c != null) { + if (c != null && lastClassInMembersComboBox != c) { + lastClassInMembersComboBox = c; ArrayList items = new ArrayList(); + bool partialMode = false; + IClass currentPart = c; + if (c.IsPartial) { + CompoundClass cc = c.ProjectContent.GetClass(c.FullyQualifiedName) as CompoundClass; + if (cc != null && cc.Parts.Count > 0) { + partialMode = true; + c = cc; + } + } int lastIndex = 0; IComparer comparer = new Comparer(System.Globalization.CultureInfo.InvariantCulture); + foreach (IMethod m in c.Methods) { - items.Add(new ComboBoxItem(m, m.Name, ClassBrowserIconService.GetIcon(m))); + items.Add(new ComboBoxItem(m, m.Name, ClassBrowserIconService.GetIcon(m), partialMode ? currentPart.Methods.Contains(m) : true)); } items.Sort(lastIndex, c.Methods.Count, comparer); lastIndex = items.Count; foreach (IProperty p in c.Properties) { - items.Add(new ComboBoxItem(p, p.Name, ClassBrowserIconService.GetIcon(p))); + items.Add(new ComboBoxItem(p, p.Name, ClassBrowserIconService.GetIcon(p), partialMode ? currentPart.Properties.Contains(p) : true)); } items.Sort(lastIndex, c.Properties.Count, comparer); lastIndex = items.Count; foreach (IIndexer indexer in c.Indexer) { - items.Add(new ComboBoxItem(indexer, indexer.Name, ClassBrowserIconService.GetIcon(indexer))); + items.Add(new ComboBoxItem(indexer, indexer.Name, ClassBrowserIconService.GetIcon(indexer), partialMode ? currentPart.Indexer.Contains(indexer) : true)); } items.Sort(lastIndex, c.Indexer.Count, comparer); lastIndex = items.Count; foreach (IField f in c.Fields) { - items.Add(new ComboBoxItem(f, f.Name, ClassBrowserIconService.GetIcon(f))); + items.Add(new ComboBoxItem(f, f.Name, ClassBrowserIconService.GetIcon(f), partialMode ? currentPart.Fields.Contains(f) : true)); } items.Sort(lastIndex, c.Fields.Count, comparer); lastIndex = items.Count; foreach (IEvent evt in c.Events) { - items.Add(new ComboBoxItem(evt, evt.Name, ClassBrowserIconService.GetIcon(evt))); + items.Add(new ComboBoxItem(evt, evt.Name, ClassBrowserIconService.GetIcon(evt), partialMode ? currentPart.Events.Contains(evt) : true)); } items.Sort(lastIndex, c.Events.Count, comparer); lastIndex = items.Count; - if (NeedtoUpdate(items, membersComboBox)) { - membersComboBox.BeginUpdate(); - membersComboBox.Items.Clear(); - membersComboBox.Items.AddRange(items.ToArray()); - membersComboBox.EndUpdate(); - UpdateMembersComboBox(); - } + membersComboBox.BeginUpdate(); + membersComboBox.Items.Clear(); + membersComboBox.Items.AddRange(items.ToArray()); + membersComboBox.EndUpdate(); + UpdateMembersComboBox(); } else { if (membersComboBox.Items.Count > 0) { membersComboBox.Items.Clear(); @@ -377,9 +400,8 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor void AddClasses(ArrayList items, ICollection classes) { - foreach (IClass c in classes) { - items.Add(new ComboBoxItem(c, c.FullyQualifiedName, ClassBrowserIconService.GetIcon(c))); + items.Add(new ComboBoxItem(c, c.FullyQualifiedName, ClassBrowserIconService.GetIcon(c), true)); AddClasses(items, c.InnerClasses); } } @@ -388,17 +410,23 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor { ArrayList items = new ArrayList(); AddClasses(items, currentCompilationUnit.Classes); - if (NeedtoUpdate(items, classComboBox)) { - if (isUpdateRequired) { - classComboBox.BeginUpdate(); - } - classComboBox.Items.Clear(); - classComboBox.Items.AddRange(items.ToArray()); - if (isUpdateRequired) { - classComboBox.EndUpdate(); + if (isUpdateRequired) { + classComboBox.BeginUpdate(); + } + classComboBox.Items.Clear(); + classComboBox.Items.AddRange(items.ToArray()); + if (items.Count == 1) { + try { + autoselect = false; + classComboBox.SelectedIndex = 0; + } finally { + autoselect = true; } - UpdateClassComboBox(); } + if (isUpdateRequired) { + classComboBox.EndUpdate(); + } + UpdateClassComboBox(); } @@ -462,9 +490,17 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor if (comboBox.SelectedIndex < 0) { membersComboBox.Items.Clear(); } else if (autoselect) { - textAreaControl.ActiveTextAreaControl.Caret.Position = new Point(((ComboBoxItem)comboBox.Items[comboBox.SelectedIndex]).Column, - ((ComboBoxItem)comboBox.Items[comboBox.SelectedIndex]).Line); - textAreaControl.ActiveTextAreaControl.TextArea.Focus(); + ComboBoxItem item = (ComboBoxItem)comboBox.Items[comboBox.SelectedIndex]; + if (item.IsInCurrentPart) { + textAreaControl.ActiveTextAreaControl.Caret.Position = new Point(item.Column, item.Line); + textAreaControl.ActiveTextAreaControl.TextArea.Focus(); + } else { + IMember m = item.Item as IMember; + if (m != null) { + string fileName = m.DeclaringType.CompilationUnit.FileName; + FileService.JumpToFilePosition(fileName, item.Line, item.Column); + } + } } } @@ -493,7 +529,9 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) { drawItemBrush = SystemBrushes.HighlightText; } - if (e.State == DrawItemState.ComboBoxEdit && !item.IsInside(textAreaControl.ActiveTextAreaControl.Caret.Line)) { + if (!item.IsInCurrentPart) { + drawItemBrush = SystemBrushes.ControlDark; + } else if (e.State == DrawItemState.ComboBoxEdit && !item.IsInside(textAreaControl.ActiveTextAreaControl.Caret.Line)) { drawItemBrush = SystemBrushes.ControlDark; } e.Graphics.DrawString(item.ToString(),