diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 502f042b6b..3b260cf8bc 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -1,4 +1,4 @@ - + Debug AnyCPU @@ -618,6 +618,7 @@ + @@ -642,4 +643,4 @@ - \ No newline at end of file + diff --git a/src/Main/Base/Project/Src/Dom/IParser.cs b/src/Main/Base/Project/Src/Dom/IParser.cs index fd73f7fec5..976b1dcf29 100644 --- a/src/Main/Base/Project/Src/Dom/IParser.cs +++ b/src/Main/Base/Project/Src/Dom/IParser.cs @@ -14,110 +14,9 @@ using ICSharpCode.Core; namespace ICSharpCode.SharpDevelop.Dom { -// [Flags] -// public enum ShowMembers { -// Public = 1, -// Protected = 2, -// Private = 4, -// Static = 8 -// } - - public class ResolveResult - { - IClass type; - ArrayList members; - List namespaces; - - public IClass Type { - get { - return type; - } - } - - public ArrayList Members { - get { - return members; - } - } - - public List Namespaces { - get { - return namespaces; - } - } - - public ResolveResult(string[] namespaces) { - this.namespaces = new List(); - this.namespaces.AddRange(namespaces); - members = new ArrayList(); - } - - public ResolveResult(string[] namespaces, ArrayList classes) { - this.namespaces = new List(); - this.namespaces.AddRange(namespaces); - members = classes; - } - - public ResolveResult(List namespaces) { - this.namespaces = namespaces; - members = new ArrayList(); - } - - public ResolveResult(IClass type, ArrayList members) { - this.type = type; - this.members = members; - namespaces = new List(); - } -// object[] resolveContents; -// ShowMembers showMembers; -// -// public bool ShowPublic { -// get { -// return (showMembers & ShowMembers.Public) == ShowMembers.Public; -// } -// } -// -// public bool ShowProtected { -// get { -// return (showMembers & ShowMembers.Protected) == ShowMembers.Protected; -// } -// } -// -// public bool ShowPrivate { -// get { -// return (showMembers & ShowMembers.Private) == ShowMembers.Private; -// } -// } -// -// public bool ShowStatic { -// get { -// return (showMembers & ShowMembers.Static) == ShowMembers.Static; -// } -// } -// -// public object[] ResolveContents { -// get { -// return resolveContents; -// } -// } -// -// public ShowMembers ShowMembers { -// get { -// return showMembers; -// } -// } -// -// public ResolveResult(object[] resolveContents, ShowMembers showMembers) -// { -// this.resolveContents = resolveContents; -// this.showMembers = showMembers; -// } - } - public interface IParser { string[] LexerTags { -//// Alex - need to have get accessor too get; set; } @@ -132,6 +31,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// extension. /// bool CanParse(string fileName); + /// /// Gets if the parser can parse the specified project. /// Only when no parser for a project is found, the assembly is loaded. diff --git a/src/Main/Base/Project/Src/Dom/Implementations/AbstractClass.cs b/src/Main/Base/Project/Src/Dom/Implementations/AbstractClass.cs index a09e604a19..c2fcdf918a 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/AbstractClass.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/AbstractClass.cs @@ -362,7 +362,9 @@ namespace ICSharpCode.SharpDevelop.Dom return members; } - bool isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(this); + bool isClassInInheritanceTree = false; + if (callingClass != null) + isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(this); if (showStatic) { foreach (IClass c in InnerClasses) { diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryASTConvertVisitor.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryASTConvertVisitor.cs index 9faa89e0d3..fd4128be84 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryASTConvertVisitor.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryASTConvertVisitor.cs @@ -136,7 +136,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver default: target = AttributeTarget.None; break; - + } } IAttributeSection s = new AttributeSection(target, resultAttributes); @@ -303,7 +303,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver for (int i = 0; i < fieldDeclaration.Fields.Count; ++i) { AST.VariableDeclaration field = (AST.VariableDeclaration)fieldDeclaration.Fields[i]; - Field f = new Field(new ReturnType(fieldDeclaration.GetTypeForField(i)), field.Name, fieldDeclaration.Modifier, region, GetCurrentClass()); + ReturnType retType; + if (c.ClassType == ClassType.Enum) + retType = new ReturnType(c.FullyQualifiedName); + else + retType = new ReturnType(fieldDeclaration.GetTypeForField(i)); + Field f = new Field(retType, field.Name, fieldDeclaration.Modifier, region, GetCurrentClass()); f.Attributes.AddRange(VisitAttributes(fieldDeclaration.Attributes)); if (c.ClassType == ClassType.Enum) { f.SetModifiers(ModifierEnum.Const | ModifierEnum.SpecialName); diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs index 5d5d1af509..5caf09ac13 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs @@ -21,12 +21,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver { ICompilationUnit cu; IClass callingClass; + IMember callingMember; ICSharpCode.NRefactory.Parser.LookupTableVisitor lookupTableVisitor; IProjectContent projectContent = null; - bool showStatic = false; - bool inNew = false; - bool caseSensitive = true; SupportedLanguages language = SupportedLanguages.CSharp; @@ -60,23 +58,13 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } } - public bool ShowStatic { - get { - return showStatic; - } - - set { - showStatic = value; - } - } - public NRefactoryResolver(SupportedLanguages language) { this.language = language; this.projectContent = ParserService.CurrentProjectContent; } - bool IsCaseSensitive(SupportedLanguages language) + bool IsCaseSensitive(SupportedLanguages language) { switch (language) { case SupportedLanguages.CSharp: @@ -88,9 +76,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } } - public ResolveResult Resolve(string expression, - int caretLineNumber, - int caretColumn, + public ResolveResult Resolve(string expression, + int caretLineNumber, + int caretColumn, string fileName) { caseSensitive = IsCaseSensitive(language); @@ -103,21 +91,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver expression = expression.ToLower(); } - // disable the code completion for numbers like 3.47 - if (IsNumber(expression)) { - return null; - } - - if (expression.StartsWith("new ")) { - inNew = true; - expression = expression.Substring(4); - } else { - inNew = false; - } - if (expression.StartsWith(GetUsingString())) { - return UsingResolve(expression); - } - this.caretLine = caretLineNumber; this.caretColumn = caretColumn; @@ -156,40 +129,147 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (cu != null) { callingClass = cu.GetInnermostClass(caretLine, caretColumn); } + callingMember = GetCurrentMember(); TypeVisitor typeVisitor = new TypeVisitor(this); + if (expr is InvocationExpression) { + IMethod method = typeVisitor.GetMethod((InvocationExpression)expr, null); + if (method != null) + return new MemberResolveResult(callingClass, callingMember, method); + } else if (expr is FieldReferenceExpression) { + FieldReferenceExpression fieldReferenceExpression = (FieldReferenceExpression)expr; + IReturnType returnType = fieldReferenceExpression.TargetObject.AcceptVisitor(typeVisitor, null) as IReturnType; + if (returnType != null) { + string name = SearchNamespace(returnType.FullyQualifiedName, this.CompilationUnit); + if (name != null) { + name += "." + fieldReferenceExpression.FieldName; + string n = SearchNamespace(name, null); + if (n != null) { + return new NamespaceResolveResult(callingClass, callingMember, n); + } + IClass c = SearchType(name, this.CallingClass, this.CompilationUnit); + if (c != null) { + return new TypeResolveResult(callingClass, callingMember, new ReturnType(c.FullyQualifiedName), c); + } + return null; + } + IMember member = GetMember(returnType, fieldReferenceExpression.FieldName); + if (member != null) + return new MemberResolveResult(callingClass, callingMember, member); + ResolveResult result = ResolveMethod(returnType, fieldReferenceExpression.FieldName); + if (result != null) + return result; + } + } else if (expr is IdentifierExpression) { + ResolveResult result = ResolveIdentifier(((IdentifierExpression)expr).Identifier); + if (result != null) + return result; + } IReturnType type = expr.AcceptVisitor(typeVisitor, null) as IReturnType; if (type == null || type.FullyQualifiedName == "" || type.PointerNestingLevel != 0) { return null; } - if (type.ArrayDimensions != null && type.ArrayDimensions.Length > 0) { - type = new ReturnType("System.Array"); + if (type.ArrayDimensions != null && type.ArrayDimensions.Length > 0) + return new ResolveResult(callingClass, callingMember, new ReturnType("System.Array")); + else { + return new ResolveResult(callingClass, callingMember, FixType(type)); } + } + + IReturnType FixType(IReturnType type) + { IClass returnClass = SearchType(type.FullyQualifiedName, callingClass, cu); - if (returnClass == null) { - return TryNamespace(type); + if (returnClass != null && returnClass.FullyQualifiedName != type.FullyQualifiedName) + return new ReturnType(returnClass.FullyQualifiedName); + else + return type; + } + + #region Resolve Identifier + ResolveResult ResolveIdentifier(string identifier) + { + string name = SearchNamespace(identifier, this.CompilationUnit); + if (name != null && name != "") { + return new NamespaceResolveResult(callingClass, callingMember, name); + } + IClass c = SearchType(identifier, this.CallingClass, this.CompilationUnit); + if (c != null) { + return new TypeResolveResult(callingClass, callingMember, new ReturnType(c.FullyQualifiedName), c); + } + LocalLookupVariable var = SearchVariable(identifier); + if (var != null) { + IReturnType type = GetVariableType(var); + IField field = new LocalVariableField(type, identifier, null, callingClass); + return new LocalResolveResult(callingClass, callingMember, field, false); + } + IParameter para = SearchMethodParameter(identifier); + if (para != null) { + IField field = new LocalVariableField(para.ReturnType, para.Name, para.Region, callingClass); + return new LocalResolveResult(callingClass, callingMember, field, true); + } + + IMember member = GetMember(callingClass, identifier); + if (member != null) { + return new MemberResolveResult(callingClass, callingMember, member); + } + + ResolveResult result = ResolveMethod(callingClass, identifier); + if (result != null) + return result; + + // try if there exists a static member in outer classes named typeName + List classes = cu.GetOuterClasses(caretLine, caretColumn); + foreach (IClass c2 in classes) { + member = GetMember(c2, identifier); + if (member != null && member.IsStatic) { + return new MemberResolveResult(callingClass, callingMember, member); + } + } + return null; + } + + private class LocalVariableField : AbstractField + { + public LocalVariableField(IReturnType type, string name, IRegion region, IClass declaringType) : base(declaringType) + { + this.returnType = type; + this.FullyQualifiedName = name; + this.region = region; + this.modifiers = ModifierEnum.Private; } - if (inNew) { - return new ResolveResult(returnClass, returnClass.GetAccessibleTypes(callingClass)); + } + #endregion + + #region ResolveMethod + ResolveResult ResolveMethod(IReturnType type, string identifier) + { + if (type == null || type.PointerNestingLevel != 0) { + return null; + } + IClass curType; + if (type.ArrayDimensions != null && type.ArrayDimensions.Length > 0) { + curType = SearchType("System.Array", null, null); } else { - ArrayList result = returnClass.GetAccessibleMembers(callingClass, showStatic); - if (!showStatic && language == SupportedLanguages.VBNet) { - result.AddRange(returnClass.GetAccessibleMembers(callingClass, true).ToArray()); + curType = SearchType(type.FullyQualifiedName, null, null); + if (curType == null) { + return null; } - return new ResolveResult(returnClass, result); } + return ResolveMethod(curType, identifier); } - bool IsNumber(string expression) + ResolveResult ResolveMethod(IClass c, string identifier) { - try { - int.Parse(expression); - return true; - } catch (Exception) { - return false; + foreach (IClass curType in c.ClassInheritanceTree) { + foreach (IMethod method in c.Methods) { + if (IsSameName(identifier, method.Name)) + return new MethodResolveResult(callingClass, callingMember, c, identifier); + } } + return null; } + #endregion Expression WithResolve() { @@ -197,7 +277,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return null; } Expression expr = null; -// TODO : + // TODO : // if (lookupTableVisitor.WithStatements != null) { // foreach (WithStatement with in lookupTableVisitor.WithStatements) { // if (IsInside(new Point(caretColumn, caretLine), with.StartLocation, with.EndLocation)) { @@ -208,121 +288,107 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return expr; } - string GetUsingString() + Expression SpecialConstructs(string expression) { - switch (language) { - case SupportedLanguages.CSharp: - return "using "; - case SupportedLanguages.VBNet: - return "imports "; - default: - throw new NotSupportedException("The language " + language + " is not supported in the resolver"); - } + if (language == SupportedLanguages.VBNet) { + // MyBase and MyClass are no expressions, only MyBase.Identifier and MyClass.Identifier + if (expression == "mybase") { + return new BaseReferenceExpression(); + } else if (expression == "myclass") { + return new ClassReferenceExpression(); + } + } + return null; } - ResolveResult ImportsResolve(string expression) + bool IsSameName(string name1, string name2) { - // expression[expression.Length - 1] != '.' - // the period that causes this Resove() is not part of the expression - if (expression[expression.Length - 1] == '.') { - return null; - } - int i; - for (i = expression.Length - 1; i >= 0; --i) { - if (!(Char.IsLetterOrDigit(expression[i]) || expression[i] == '_' || expression[i] == '.')) { - break; - } - } - // no Identifier before the period - if (i == expression.Length - 1) { - return null; - } - string t = expression.Substring(i + 1); - string[] namespaces = projectContent.GetNamespaceList(t); - if (namespaces == null || namespaces.Length <= 0) { - return null; + if (IsCaseSensitive(language)) { + return name1 == name2; + } else { + return name1.ToLower() == name2.ToLower(); } - return new ResolveResult(namespaces); } - ResolveResult UsingResolve(string expression) + bool IsInside(Point between, Point start, Point end) { - if (language == SupportedLanguages.VBNet) { - return ImportsResolve(expression); - } - // expression[expression.Length - 1] != '.' - // the period that causes this Resove() is not part of the expression - if (expression[expression.Length - 1] == '.') { - return null; + if (between.Y < start.Y || between.Y > end.Y) { + return false; } - int i; - for (i = expression.Length - 1; i >= 0; --i) { - if (!(Char.IsLetterOrDigit(expression[i]) || expression[i] == '_' || expression[i] == '.')) { - break; + if (between.Y > start.Y) { + if (between.Y < end.Y) { + return true; } + // between.Y == end.Y + return between.X <= end.X; } - // no Identifier before the period - if (i == expression.Length - 1) { - return null; - } - string t = expression.Substring(i + 1); - string[] namespaces = projectContent.GetNamespaceList(t); - if (namespaces == null || namespaces.Length <= 0) { - return null; + // between.Y == start.Y + if (between.X < start.X) { + return false; } - return new ResolveResult(namespaces); + // start is OK and between.Y <= end.Y + return between.Y < end.Y || between.X <= end.X; } - Expression SpecialConstructs(string expression) + IMember GetCurrentMember() { - if (language == SupportedLanguages.VBNet) { - // MyBase and MyClass are no expressions, only MyBase.Identifier and MyClass.Identifier - if (expression == "mybase") { - return new BaseReferenceExpression(); - } else if (expression == "myclass") { - return new ClassReferenceExpression(); + foreach (IProperty property in callingClass.Properties) { + if (property.BodyRegion != null && property.BodyRegion.IsInside(caretLine, caretColumn)) { + return property; + } + } + foreach (IMethod method in callingClass.Methods) { + if (method.BodyRegion != null && method.BodyRegion.IsInside(caretLine, caretColumn)) { + return method; } } return null; } - ResolveResult TryNamespace(IReturnType type) + /// + /// use the usings to find the correct name of a namespace + /// + public string SearchNamespace(string name, ICompilationUnit unit) { - string n = SearchNamespace(type.FullyQualifiedName, cu); - if (n == null) { - return null; + /*if (projectContent.NamespaceExists(name)) { + return name; } - ArrayList content = projectContent.GetNamespaceContents(n); - ArrayList classes = new ArrayList(); - for (int i = 0; i < content.Count; ++i) { - if (content[i] is IClass) { - if (inNew) { - IClass c = (IClass)content[i]; - if ((c.ClassType == ClassType.Class) || (c.ClassType == ClassType.Struct)) { - classes.Add(c); - } - } else { - classes.Add((IClass)content[i]); + + if (CallingClass != null) { + string callspace = this.CallingClass.Namespace; + for (int split = callspace.Length; split > 0; split = callspace.LastIndexOf('.', split - 1)) { + string fullname = callspace.Substring(0, split) + "." + name; + if (projectContent.NamespaceExists(fullname)) { + return fullname; } } } - string[] namespaces = projectContent.GetNamespaceList(n); - return new ResolveResult(namespaces, classes); + */ + // TODO: look if all the stuff before is nessessary + return projectContent.SearchNamespace(name, unit, caretLine, caretColumn); } - bool InStatic() + /// + /// use the usings and the name of the namespace to find a class + /// + public IClass SearchType(string name, IClass curType) { - IProperty property = GetProperty(); - if (property != null) { - return property.IsStatic; - } - IMethod method = GetMethod(caretLine, caretColumn); - if (method != null) { - return method.IsStatic; - } - return false; + return projectContent.SearchType(name, curType, caretLine, caretColumn); } + /// + /// use the usings and the name of the namespace to find a class + /// + public IClass SearchType(string name, IClass curType, ICompilationUnit unit) + { + return projectContent.SearchType(name, curType, unit, caretLine, caretColumn); + } + + #region Helper for TypeVisitor + #region SearchMethod + /// + /// Gets the list of methods on the return type that have the specified name. + /// public ArrayList SearchMethod(IReturnType type, string memberName) { if (type == null || type.PointerNestingLevel != 0) { @@ -340,22 +406,13 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return SearchMethod(new ArrayList(), curType, memberName); } - bool IsSameName(string name1, string name2) - { - if (IsCaseSensitive(language)) { - return name1 == name2; - } else { - return name1.ToLower() == name2.ToLower(); - } - } - ArrayList SearchMethod(ArrayList methods, IClass curType, string memberName) { bool isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(curType); foreach (IMethod m in curType.Methods) { if (IsSameName(m.Name, memberName) && - m.MustBeShown(callingClass, showStatic, isClassInInheritanceTree) && + m.MustBeShown(callingClass, true, isClassInInheritanceTree) && !((m.Modifiers & ModifierEnum.Override) == ModifierEnum.Override)) { methods.Add(m); } @@ -364,10 +421,11 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (baseClass != null) { return SearchMethod(methods, baseClass, memberName); } - showStatic = false; return methods; } + #endregion + #region SearchIndexer public ArrayList SearchIndexer(IReturnType type) { IClass curType = SearchType(type.FullyQualifiedName, null, null); @@ -377,11 +435,11 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return new ArrayList(1); } - public ArrayList SearchIndexer(ArrayList indexer, IClass curType) + ArrayList SearchIndexer(ArrayList indexer, IClass curType) { bool isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(curType); foreach (IIndexer i in curType.Indexer) { - if (i.MustBeShown(callingClass, showStatic, isClassInInheritanceTree) && !((i.Modifiers & ModifierEnum.Override) == ModifierEnum.Override)) { + if (i.MustBeShown(callingClass, true, isClassInInheritanceTree) && !((i.Modifiers & ModifierEnum.Override) == ModifierEnum.Override)) { indexer.Add(i); } } @@ -389,220 +447,137 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (baseClass != null) { return SearchIndexer(indexer, baseClass); } - showStatic = false; return indexer; } + #endregion + #region SearchMember // no methods or indexer public IReturnType SearchMember(IReturnType type, string memberName) { - // TODO: use SearchMember from ParserService if (type == null || memberName == null || memberName == "") { return null; } - IClass curType = SearchType(type.FullyQualifiedName, callingClass, cu); - bool isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(curType); - - if (curType == null) { - return null; - } if (type.PointerNestingLevel != 0) { return null; } + IClass curType; if (type.ArrayDimensions != null && type.ArrayDimensions.Length > 0) { curType = SearchType("System.Array", null, null); + } else { + curType = SearchType(type.FullyQualifiedName, callingClass, cu); } - if (curType.ClassType == ClassType.Enum) { - foreach (IField f in curType.Fields) { - if (IsSameName(f.Name, memberName) && f.MustBeShown(callingClass, showStatic, isClassInInheritanceTree)) { - showStatic = false; - return type; // enum members have the type of the enum - } - } - } - if (showStatic) { - foreach (IClass c in curType.InnerClasses) { - if (IsSameName(c.Name, memberName) && c.IsAccessible(callingClass, isClassInInheritanceTree)) { - return new ReturnType(c.FullyQualifiedName); - } - } - } - foreach (IProperty p in curType.Properties) { - if (IsSameName(p.Name, memberName) && p.MustBeShown(callingClass, showStatic, isClassInInheritanceTree)) { - showStatic = false; - return p.ReturnType; - } - } - foreach (IField f in curType.Fields) { - if (IsSameName(f.Name, memberName) && f.MustBeShown(callingClass, showStatic, isClassInInheritanceTree)) { - showStatic = false; - return f.ReturnType; - } - } - foreach (IEvent e in curType.Events) { - if (IsSameName(e.Name, memberName) && e.MustBeShown(callingClass, showStatic, isClassInInheritanceTree)) { - showStatic = false; - return e.ReturnType; - } - } - foreach (string baseType in curType.BaseTypes) { - IClass c = SearchType(baseType, curType); - if (c != null) { - IReturnType erg = SearchMember(new ReturnType(c.FullyQualifiedName), memberName); - if (erg != null) { - return erg; - } - } - } - return null; + if (curType == null) + return null; + else + return SearchMember(curType, memberName); } - bool IsInside(Point between, Point start, Point end) + public IMember GetMember(IReturnType type, string memberName) { - if (between.Y < start.Y || between.Y > end.Y) { - return false; + if (type == null || memberName == null || memberName == "") { + return null; } - if (between.Y > start.Y) { - if (between.Y < end.Y) { - return true; - } - // between.Y == end.Y - return between.X <= end.X; + if (type.PointerNestingLevel != 0) { + return null; } - // between.Y == start.Y - if (between.X < start.X) { - return false; + IClass curType; + if (type.ArrayDimensions != null && type.ArrayDimensions.Length > 0) { + curType = SearchType("System.Array", null, null); + } else { + curType = SearchType(type.FullyQualifiedName, callingClass, cu); } - // start is OK and between.Y <= end.Y - return between.Y < end.Y || between.X <= end.X; + if (curType == null) + return null; + else + return GetMember(curType, memberName); } - LocalLookupVariable SearchVariable(string name) + public IReturnType SearchMember(IClass curType, string memberName) { - ArrayList variables = (ArrayList)lookupTableVisitor.variables[IsCaseSensitive(language) ? name : name.ToLower()]; - if (variables == null || variables.Count <= 0) { - return null; - } - - foreach (LocalLookupVariable v in variables) { - if (IsInside(new Point(caretColumn, caretLine), v.StartPos, v.EndPos)) { - return v; + bool isClassInInheritanceTree = false; + if (callingClass != null) + isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(curType); + foreach (IClass c in curType.InnerClasses) { + if (IsSameName(c.Name, memberName) && c.IsAccessible(callingClass, isClassInInheritanceTree)) { + return new ReturnType(c.FullyQualifiedName); } } - return null; + IMember member = GetMember(curType, memberName); + if (member == null) + return null; + else + return member.ReturnType; } - IReturnType GetVariableType(LocalLookupVariable v) + private IMember GetMember(IClass c, string memberName) { - if (v == null) { - return null; - } - IClass c = SearchType(v.TypeRef.SystemType, callingClass, cu); - if (c != null) { - return new ReturnType(c.FullyQualifiedName, v.TypeRef.RankSpecifier, v.TypeRef.PointerNestingLevel); - } else { - return new ReturnType(v.TypeRef); + bool isClassInInheritanceTree = false; + if (callingClass != null) + isClassInInheritanceTree = callingClass.IsTypeInInheritanceTree(c); + foreach (IClass curType in c.ClassInheritanceTree) { + foreach (IProperty p in curType.Properties) { + if (IsSameName(p.Name, memberName) && p.MustBeShown(callingClass, true, isClassInInheritanceTree)) { + return p; + } + } + foreach (IField f in curType.Fields) { + if (IsSameName(f.Name, memberName) && f.MustBeShown(callingClass, true, isClassInInheritanceTree)) { + return f; + } + } + foreach (IEvent e in curType.Events) { + if (IsSameName(e.Name, memberName) && e.MustBeShown(callingClass, true, isClassInInheritanceTree)) { + return e; + } + } } + return null; } + #endregion + #region DynamicLookup /// - /// does the dynamic lookup for the typeName + /// does the dynamic lookup for the identifier /// public IReturnType DynamicLookup(string typeName) { // try if it exists a variable named typeName IReturnType variable = GetVariableType(SearchVariable(typeName)); if (variable != null) { - showStatic = false; return variable; } if (callingClass == null) { return null; } - + // try if typeName is a method parameter IParameter parameter = SearchMethodParameter(typeName); if (parameter != null) { - showStatic = false; return parameter.ReturnType; } // check if typeName == value in set method of a property if (typeName == "value") { - IProperty property = GetProperty(); + IProperty property = callingMember as IProperty; if (property != null && property.SetterRegion != null && property.SetterRegion.IsInside(caretLine, caretColumn)) { - showStatic = false; return property.ReturnType; } } // try if there exists a nonstatic member named typeName - showStatic = false; - IReturnType t = SearchMember(callingClass == null ? null : new ReturnType(callingClass.FullyQualifiedName), typeName); + IReturnType t = SearchMember(callingClass, typeName); if (t != null) { return t; } - // try if there exists a static member named typeName - showStatic = true; - t = SearchMember(callingClass == null ? null : new ReturnType(callingClass.FullyQualifiedName), typeName); - if (t != null) { - showStatic = false; - return t; - } - // try if there exists a static member in outer classes named typeName List classes = cu.GetOuterClasses(caretLine, caretColumn); foreach (IClass c in classes) { - t = SearchMember(callingClass == null ? null : new ReturnType(c.FullyQualifiedName), typeName); - if (t != null) { - showStatic = false; - return t; - } - } - - // Alex: look in namespaces - // Alex: look inside namespaces - string[] innamespaces = projectContent.GetNamespaceList(""); - foreach (string ns in innamespaces) { - ArrayList objs = projectContent.GetNamespaceContents(ns); - if (objs == null) continue; - foreach (object o in objs) { - if (o is IClass) { - IClass oc=(IClass)o; - if (IsSameName(oc.Name, typeName) || IsSameName(oc.FullyQualifiedName, typeName)) { - //Debug.WriteLine(((IClass)o).Name); - /// now we can set completion data - objs.Clear(); - objs = null; - return new ReturnType(oc.FullyQualifiedName); - } - } - } - if (objs == null) { - break; - } - } - innamespaces = null; - return null; - } - - IProperty GetProperty() - { - foreach (IProperty property in callingClass.Properties) { - if (property.BodyRegion != null && property.BodyRegion.IsInside(caretLine, caretColumn)) { - return property; - } - } - return null; - } - - IMethod GetMethod(int caretLine, int caretColumn) - { - foreach (IMethod method in callingClass.Methods) { - if (method.BodyRegion != null && method.BodyRegion.IsInside(caretLine, caretColumn)) { - return method; + IMember member = GetMember(c, typeName); + if (member != null && member.IsStatic) { + return member.ReturnType; } } return null; @@ -610,7 +585,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver IParameter SearchMethodParameter(string parameter) { - IMethod method = GetMethod(caretLine, caretColumn); + IMethod method = callingMember as IMethod; if (method == null) { return null; } @@ -622,116 +597,37 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return null; } - /// - /// use the usings to find the correct name of a namespace - /// - public string SearchNamespace(string name, ICompilationUnit unit) + IReturnType GetVariableType(LocalLookupVariable v) { - if (projectContent.NamespaceExists(name)) { - return name; + if (v == null) { + return null; } - - if (CallingClass != null) { - string callspace = this.CallingClass.Namespace; - for (int split = callspace.Length; split > 0; split = callspace.LastIndexOf('.', split - 1)) { - string fullname = callspace.Substring(0, split) + "." + name; - if (projectContent.NamespaceExists(fullname)) { - return fullname; - } - } + IClass c = SearchType(v.TypeRef.SystemType, callingClass, cu); + if (c != null) { + return new ReturnType(c.FullyQualifiedName, v.TypeRef.RankSpecifier, v.TypeRef.PointerNestingLevel); + } else { + return new ReturnType(v.TypeRef); } - - // TODO: look if all the stuff before is nessessary - return projectContent.SearchNamespace(name, unit, caretLine, caretColumn); - } - - /// - /// use the usings and the name of the namespace to find a class - /// - public IClass SearchType(string name, IClass curType) - { - return projectContent.SearchType(name, curType, caretLine, caretColumn); - } - - /// - /// use the usings and the name of the namespace to find a class - /// - public IClass SearchType(string name, IClass curType, ICompilationUnit unit) - { - return projectContent.SearchType(name, curType, unit, caretLine, caretColumn); } - public FilePosition SearchDefinition(string expression, - int caretLineNumber, - int caretColumn, - string fileName) + LocalLookupVariable SearchVariable(string name) { - this.caretLine = caretLineNumber; - this.caretColumn = caretColumn; - ICSharpCode.NRefactory.Parser.IParser p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(language, new System.IO.StringReader(expression)); - Expression expr = p.ParseExpression(); - ParseInformation parseInfo = ParserService.GetParseInformation(fileName); - if (parseInfo == null) { - return null; - } - NRefactoryASTConvertVisitor cSharpVisitor = new NRefactoryASTConvertVisitor(parseInfo.MostRecentCompilationUnit != null ? parseInfo.MostRecentCompilationUnit.ProjectContent : null); - ICSharpCode.NRefactory.Parser.AST.CompilationUnit fileCompilationUnit = parseInfo.MostRecentCompilationUnit.Tag as ICSharpCode.NRefactory.Parser.AST.CompilationUnit; - cu = (ICompilationUnit)cSharpVisitor.Visit(fileCompilationUnit, null); - if (cu != null) { - callingClass = cu.GetInnermostClass(caretLine, caretColumn); - } - if (callingClass == null) { - return null; - } - - if (expr is IdentifierExpression) { - lookupTableVisitor = new LookupTableVisitor(); - lookupTableVisitor.Visit(fileCompilationUnit, null); - - // try if it exists a variable named typeName - LocalLookupVariable variable = SearchVariable(expression); - if (variable != null) { - return new FilePosition(fileName, variable.StartPos); - } - - // try if typeName is a method parameter - IParameter parameter = SearchMethodParameter(expression); - if (parameter != null) { - return new FilePosition(fileName, new Point(parameter.Region.BeginColumn, parameter.Region.BeginLine)); - } + ArrayList variables = (ArrayList)lookupTableVisitor.variables[IsCaseSensitive(language) ? name : name.ToLower()]; + if (variables == null || variables.Count <= 0) { return null; } - string target = expression.Substring(0, expression.LastIndexOf('.')); - string member = expression.Substring(expression.LastIndexOf('.') + 1); - p = ICSharpCode.NRefactory.Parser.ParserFactory.CreateParser(language, new System.IO.StringReader(target)); - Expression targetExpr = p.ParseExpression(); - - TypeVisitor typeVisitor = new TypeVisitor(this); - IReturnType type = expr.AcceptVisitor(typeVisitor, null) as IReturnType; - if (type == null || type.FullyQualifiedName == "" || type.PointerNestingLevel != 0) { - return null; - } - if (type.ArrayDimensions != null && type.ArrayDimensions.Length > 0) { - type = new ReturnType("System.Array"); - } - IClass returnClass = SearchType(type.FullyQualifiedName, callingClass, cu); - if (returnClass == null) { - string n = SearchNamespace(type.FullyQualifiedName, cu); - if (n == null) { - return null; - } - returnClass = SearchType(n + '.' + member, callingClass, cu); - if (returnClass != null) { - return new FilePosition(fileName, new Point(returnClass.Region.BeginColumn, returnClass.Region.BeginLine)); + foreach (LocalLookupVariable v in variables) { + if (IsInside(new Point(caretColumn, caretLine), v.StartPos, v.EndPos)) { + return v; } - return null; } - return null; } - + #endregion + #endregion + /* public ArrayList NewCompletion(int caretLine, int caretColumn, string fileName) { if (!IsCaseSensitive(language)) { @@ -764,7 +660,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } } return result; - } + }*/ public ArrayList CtrlSpace(int caretLine, int caretColumn, string fileName) { @@ -785,14 +681,16 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (cu != null) { callingClass = cu.GetInnermostClass(caretLine, caretColumn); if (callingClass != null) { - IMethod method = GetMethod(caretLine, caretColumn); + IMethod method = callingMember as IMethod; if (method != null) { foreach (IParameter p in method.Parameters) { result.Add(new Field(new ReturnType(p.ReturnType.Name, p.ReturnType.ArrayDimensions, p.ReturnType.PointerNestingLevel), p.Name, Modifier.None, method.Region, callingClass)); } } result.AddRange(projectContent.GetNamespaceContents(callingClass.Namespace)); - bool inStatic = InStatic(); + bool inStatic = true; + if (callingMember != null) + inStatic = callingMember.IsStatic; result.AddRange(callingClass.GetAccessibleMembers(callingClass, inStatic).ToArray()); if (inStatic == false) { result.AddRange(callingClass.GetAccessibleMembers(callingClass, !inStatic).ToArray()); diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs index f2cad230be..17d869e9fd 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs @@ -43,36 +43,37 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } public override object Visit(InvocationExpression invocationExpression, object data) + { + IMethod m = GetMethod(invocationExpression, data); + if (m == null) + return null; + else + return m.ReturnType; + } + + public IMethod GetMethod(InvocationExpression invocationExpression, object data) { if (invocationExpression.TargetObject is FieldReferenceExpression) { FieldReferenceExpression field = (FieldReferenceExpression)invocationExpression.TargetObject; IReturnType type = field.TargetObject.AcceptVisitor(this, data) as IReturnType; - if (type.ArrayDimensions != null && type.ArrayDimensions.Length > 0) { - type = new ReturnType("System.Array"); - } ArrayList methods = resolver.SearchMethod(type, field.FieldName); - resolver.ShowStatic = false; if (methods.Count <= 0) { return null; } // TODO: Find the right method - return ((IMethod)methods[0]).ReturnType; + return (IMethod)methods[0]; } else if (invocationExpression.TargetObject is IdentifierExpression) { string id = ((IdentifierExpression)invocationExpression.TargetObject).Identifier; if (resolver.CallingClass == null) { return null; } IReturnType type = new ReturnType(resolver.CallingClass.FullyQualifiedName); - if (type.ArrayDimensions != null && type.ArrayDimensions.Length > 0) { - type = new ReturnType("System.Array"); - } ArrayList methods = resolver.SearchMethod(type, id); - resolver.ShowStatic = false; if (methods.Count <= 0) { return null; } // TODO: Find the right method - return ((IMethod)methods[0]).ReturnType; + return (IMethod)methods[0]; } // invocationExpression is delegate call IReturnType t = invocationExpression.AcceptChildren(this, data) as IReturnType; @@ -85,7 +86,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (methods.Count <= 0) { return null; } - return ((IMethod)methods[0]).ReturnType; + return (IMethod)methods[0]; } return null; } @@ -98,7 +99,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver // int. generates a FieldreferenceExpression with TargetObject TypeReferenceExpression and no FieldName if (fieldReferenceExpression.FieldName == null || fieldReferenceExpression.FieldName == "") { if (fieldReferenceExpression.TargetObject is TypeReferenceExpression) { - resolver.ShowStatic = true; return new ReturnType(((TypeReferenceExpression)fieldReferenceExpression.TargetObject).TypeReference); } } @@ -112,7 +112,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } IClass c = resolver.SearchType(name + "." + fieldReferenceExpression.FieldName, resolver.CallingClass, resolver.CompilationUnit); if (c != null) { - resolver.ShowStatic = true; return new ReturnType(c.FullyQualifiedName); } return null; @@ -147,7 +146,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } IClass c = resolver.SearchType(identifierExpression.Identifier, resolver.CallingClass, resolver.CompilationUnit); if (c != null) { - resolver.ShowStatic = true; return new ReturnType(c.FullyQualifiedName); } return resolver.DynamicLookup(identifierExpression.Identifier); diff --git a/src/Main/Base/Project/Src/Dom/ResolveResult.cs b/src/Main/Base/Project/Src/Dom/ResolveResult.cs new file mode 100644 index 0000000000..48cd4197fb --- /dev/null +++ b/src/Main/Base/Project/Src/Dom/ResolveResult.cs @@ -0,0 +1,295 @@ +// +// +// +// +// +// + +using System; +using System.Collections; +using System.Collections.Generic; + +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.Core; + + +namespace ICSharpCode.SharpDevelop.Dom +{ + #region ResolveResult + /// + /// The base class of all resolve results. + /// This class is used whenever an expression is not one of the special expressions + /// (having their own ResolveResult class). + /// The ResolveResult specified the location where Resolve was called (Class+Member) + /// and the type of the resolved expression. + /// + public class ResolveResult + { + IClass callingClass; + IMember callingMember; + IReturnType resolvedType; + + public ResolveResult(IClass callingClass, IMember callingMember, IReturnType resolvedType) + { +// if (callingMember != null && callingMember.DeclaringType != callingClass) +// throw new ArgumentException("callingMember.DeclaringType must be equal to callingClass"); + this.callingClass = callingClass; + this.callingMember = callingMember; + this.resolvedType = resolvedType; + } + + /// + /// Gets the class that contained the expression used to get this ResolveResult. + /// Can be null when the class is unknown. + /// + public IClass CallingClass { + get { + return callingClass; + } + } + + /// + /// Gets the member (method or property in ) that contained the + /// expression used to get this ResolveResult. + /// Can be null when the expression was not inside a member or the member is unknown. + /// + public IMember CallingMember { + get { + return callingMember; + } + } + + /// + /// Gets the type of the resolved expression. + /// Can be null when the type cannot be represented by a IReturnType (e.g. when the + /// expression was a namespace name). + /// + public IReturnType ResolvedType { + get { + return resolvedType; + } + } + + public virtual ArrayList GetCompletionData(IProjectContent projectContent) + { + if (resolvedType == null) + return null; + IClass c = projectContent.GetClass(resolvedType.FullyQualifiedName); + if (c == null) + return null; + return c.GetAccessibleMembers(callingClass, false); + } + } + #endregion + + #region LocalResolveResult + /// + /// The LocalResolveResult is used when an expression was a simple local variable + /// or parameter. + /// + /// + /// For fields in the current class, a MemberResolveResult is used, so "e" is not always + /// a LocalResolveResult. + /// + public class LocalResolveResult : ResolveResult + { + IField field; + bool isParameter; + + public LocalResolveResult(IClass callingClass, IMember callingMember, IField field, bool isParameter) + : base(callingClass, callingMember, field.ReturnType) + { + if (callingMember == null) + throw new ArgumentNullException("callingMember"); + if (field == null) + throw new ArgumentNullException("field"); + this.field = field; + this.isParameter = isParameter; + } + + /// + /// Gets the field representing the local variable. + /// + public IField Field { + get { + return field; + } + } + + /// + /// Gets if the variable is a parameter (true) or a local variable (false). + /// + public bool IsParameter { + get { + return isParameter; + } + } + } + #endregion + + #region NamespaceResolveResult + /// + /// The NamespaceResolveResult is used when an expression was the name of a namespace. + /// is always null on a NamespaceReturnType. + /// + /// + /// Example expressions: + /// "System" + /// "System.Windows.Forms" + /// "using Win = System.Windows; Win.Forms" + /// + public class NamespaceResolveResult : ResolveResult + { + string name; + + public NamespaceResolveResult(IClass callingClass, IMember callingMember, string name) + : base(callingClass, callingMember, null) + { + if (name == null) + throw new ArgumentNullException("name"); + this.name = name; + } + + /// + /// Gets the name of the namespace. + /// + public string Name { + get { + return name; + } + } + + public override ArrayList GetCompletionData(IProjectContent projectContent) + { + return projectContent.GetNamespaceContents(name); + } + } + #endregion + + #region TypeResolveResult + /// + /// The TypeResolveResult is used when an expression was the name of a type. + /// This resolve result makes code completion show the static members instead + /// of the instance members. + /// + /// + /// Example expressions: + /// "System.EventArgs" + /// "using System; EventArgs" + /// + public class TypeResolveResult : ResolveResult + { + IClass resolvedClass; + + public TypeResolveResult(IClass callingClass, IMember callingMember, IReturnType resolvedType, IClass resolvedClass) + : base(callingClass, callingMember, resolvedType) + { + this.resolvedClass = resolvedClass; + } + + /// + /// Gets the class corresponding to the resolved type. + /// + public IClass ResolvedClass { + get { + return resolvedClass; + } + } + + public override ArrayList GetCompletionData(IProjectContent projectContent) + { + if (resolvedClass == null) + return null; + else + return resolvedClass.GetAccessibleMembers(this.CallingClass, true); + } + } + #endregion + + #region MemberResolveResult + /// + /// The TypeResolveResult is used when an expression was a member + /// (field, property, event or method call). + /// + /// + /// Example expressions: + /// "(any expression).fieldName" + /// "(any expression).eventName" + /// "(any expression).propertyName" + /// "(any expression).methodName(arguments)" (methods only when method parameters are part of expression) + /// "using System; EventArgs.Empty" + /// "fieldName" (when fieldName is a field in the current class) + /// "new System.Windows.Forms.Button()" (constructors are also methods) + /// "SomeMethod()" (when SomeMethod is a method in the current class) + /// "System.Console.WriteLine(text)" + /// + public class MemberResolveResult : ResolveResult + { + IMember resolvedMember; + + public MemberResolveResult(IClass callingClass, IMember callingMember, IMember resolvedMember) + : base(callingClass, callingMember, resolvedMember.ReturnType) + { + if (resolvedMember == null) + throw new ArgumentNullException("resolvedMember"); + this.resolvedMember = resolvedMember; + } + + /// + /// Gets the member that was resolved. + /// + public IMember ResolvedMember { + get { + return resolvedMember; + } + } + } + #endregion + + #region MethodResolveResult + /// + /// The MethodResolveResult is used when an expression was the name of a method, + /// but there were no parameters specified so the exact overload could not be found. + /// is always null on a MethodReturnType. + /// + /// + /// Example expressions: + /// "System.Console.WriteLine" + /// "SomeMethod" (when SomeMethod is a method in the current class) + /// + public class MethodResolveResult : ResolveResult + { + string name; + IClass containingClass; + + public MethodResolveResult(IClass callingClass, IMember callingMember, IClass containingClass, string name) + : base(callingClass, callingMember, null) + { + if (containingClass == null) + throw new ArgumentNullException("containingClass"); + if (name == null) + throw new ArgumentNullException("name"); + this.containingClass = containingClass; + this.name = name; + } + + /// + /// Gets the name of the method. + /// + public string Name { + get { + return name; + } + } + + /// + /// Gets the class on that contains the method. + /// + public IClass ContainingClass { + get { + return containingClass; + } + } + } + #endregion +} diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index 063830e1d1..42cac07735 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -150,6 +150,8 @@ namespace ICSharpCode.Core } } } catch (Exception e) { + Console.Beep(); + Console.WriteLine(); Console.WriteLine(e); } Thread.Sleep(2000); diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/CodeCompletionDataProvider.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/CodeCompletionDataProvider.cs index 5f25f96bbd..9278b4fdd9 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/CodeCompletionDataProvider.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/CodeCompletionDataProvider.cs @@ -28,8 +28,8 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor /// public class CodeCompletionDataProvider : ICompletionDataProvider { - static - Hashtable insertedElements = new Hashtable(); + static + Hashtable insertedElements = new Hashtable(); Hashtable insertedPropertiesElements = new Hashtable(); Hashtable insertedEventElements = new Hashtable(); @@ -73,7 +73,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor string expression = expressionFinder == null ? TextUtilities.GetExpressionBeforeOffset(textArea, textArea.Caret.Offset) : expressionFinder.FindExpression(textArea.Document.GetText(0, textArea.Caret.Offset), textArea.Caret.Offset - 1); ResolveResult results; preSelection = null; - + if (ctrlSpace) { if (isNewCompletion && expression == null) { return null; @@ -86,7 +86,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor AddResolveResults(ParserService.CtrlSpace(caretLineNumber, caretColumn, fileName)); return (ICompletionData[])completionData.ToArray(typeof(ICompletionData)); } - + int idx = expression.LastIndexOf('.'); if (idx > 0) { preSelection = expression.Substring(idx + 1); @@ -204,16 +204,15 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } } } - + void AddResolveResults(ResolveResult results) { insertedElements.Clear(); insertedPropertiesElements.Clear(); insertedEventElements.Clear(); - + if (results != null) { - AddResolveResults(results.Namespaces); - AddResolveResults(results.Members); + AddResolveResults(results.GetCompletionData(ParserService.CurrentProjectContent)); } } } diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/CommentCompletionDataProvider.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/CommentCompletionDataProvider.cs index 7d46dac010..740b8aeb32 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/CommentCompletionDataProvider.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/CommentCompletionDataProvider.cs @@ -39,6 +39,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor new string[] {"item", "A list item"}, new string[] {"term", "A term in a list"}, new string[] {"description", "A description to a term in a list"}, + new string[] {"para", "A text paragraph"}, new string[] {"param name=\"\"", "A description for a parameter"}, new string[] {"paramref name=\"\"", "A reference to a parameter"}, new string[] {"permission cref=\"\"", ""}, diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/InsightWindow/IndexerInsightDataProvider.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/InsightWindow/IndexerInsightDataProvider.cs index bcbd51e15c..90a5865518 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/InsightWindow/IndexerInsightDataProvider.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/InsightWindow/IndexerInsightDataProvider.cs @@ -55,7 +55,9 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor this.textArea = textArea; initialOffset = textArea.Caret.Offset; + // TODO: Change this for the new resolver, or better merge IndexerInsight and MethodInsight. + /* IExpressionFinder expressionFinder = ParserService.GetExpressionFinder(fileName); string word = expressionFinder == null ? TextUtilities.GetExpressionBeforeOffset(textArea, textArea.Caret.Offset) : expressionFinder.FindExpression(textArea.Document.TextContent, textArea.Caret.Offset - 1); @@ -85,6 +87,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor // } // } } + */ } public bool CaretOffsetChanged() diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/InsightWindow/MethodInsightDataProvider.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/InsightWindow/MethodInsightDataProvider.cs index f50990a98f..c3888b9e9e 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/InsightWindow/MethodInsightDataProvider.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/InsightWindow/MethodInsightDataProvider.cs @@ -45,9 +45,9 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor IAmbience conv = AmbienceService.CurrentAmbience; conv.ConversionFlags = ConversionFlags.StandardConversionFlags; string documentation = ParserService.CurrentProjectContent.GetXmlDocumentation(method.DocumentationTag); - return conv.Convert(method) + - "\n" + - CodeCompletionData.GetDocumentation(documentation); // new (by G.B.) + return conv.Convert(method) + + "\n" + + CodeCompletionData.GetDocumentation(documentation); // new (by G.B.) } int initialOffset; @@ -59,90 +59,48 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor this.textArea = textArea; initialOffset = textArea.Caret.Offset; - IExpressionFinder expressionFinder = ParserService.GetExpressionFinder(fileName); - string word = expressionFinder == null ? TextUtilities.GetExpressionBeforeOffset(textArea, textArea.Caret.Offset) : expressionFinder.FindExpression(textArea.Document.TextContent, textArea.Caret.Offset- 1); - - string methodObject = word; - string methodName = null; - int idx = methodObject.LastIndexOf('.'); - if (idx >= 0) { - methodName = methodObject.Substring(idx + 1); - methodObject = methodObject.Substring(0, idx); - } else { - methodObject = fileName.EndsWith("vb") ? "Me" : "this"; - methodName = word; - } - if (methodName.Length == 0 || methodObject.Length == 0) { - return; - } + string word = expressionFinder == null ? TextUtilities.GetExpressionBeforeOffset(textArea, textArea.Caret.Offset) : expressionFinder.FindExpression(textArea.Document.TextContent, textArea.Caret.Offset - 1); + word = word.Trim(); // the parser works with 1 based coordinates caretLineNumber = document.GetLineNumberForOffset(textArea.Caret.Offset) + 1; caretColumn = textArea.Caret.Offset - document.GetLineSegment(caretLineNumber).Offset + 1; - string[] words = word.Split(' '); - bool contructorInsight = false; - if (words.Length > 1) { - contructorInsight = words[words.Length - 2] == "new"; - if (contructorInsight) { - methodObject = words[words.Length - 1]; - } + bool constructorInsight = false; + if (word.ToLower().StartsWith("new ")) { + constructorInsight = true; + word = word.Substring(4); } - ResolveResult results = ParserService.Resolve(methodObject, caretLineNumber, caretColumn, fileName, document.TextContent); - - if (results != null && results.Type != null) { - if (contructorInsight) { - AddConstructors(results.Type); - } else { - foreach (IClass c in results.Type.ClassInheritanceTree) { - AddMethods(c, methodName, false); + ResolveResult results = ParserService.Resolve(word, caretLineNumber, caretColumn, fileName, document.TextContent); + if (constructorInsight) { + TypeResolveResult result = results as TypeResolveResult; + if (result == null) + return; + IClass c = result.ResolvedClass; + bool canViewProtected = c.IsTypeInInheritanceTree(result.CallingClass); + foreach (IMethod method in c.Methods) { + if (method.IsConstructor) { + if (method.IsAccessible(result.CallingClass, canViewProtected)) { + methods.Add(method); + } } } - } - } - Hashtable includedMethods = new Hashtable(); - bool IsAlreadyIncluded(IMethod newMethod) - { - foreach (IMethod method in methods) { - if (method.Name == newMethod.Name) { - if (newMethod.Parameters.Count != method.Parameters.Count) { - return false; - } - - for (int i = 0; i < newMethod.Parameters.Count; ++i) { - if (newMethod.Parameters[i].ReturnType != method.Parameters[i].ReturnType) { - return false; + } else { + MethodResolveResult result = results as MethodResolveResult; + if (result == null) + return; + IClass c = result.ContainingClass; + bool canViewProtected = c.IsTypeInInheritanceTree(result.CallingClass); + foreach (IClass curType in c.ClassInheritanceTree) { + foreach (IMethod method in curType.Methods) { + if (method.Name == result.Name) { + if (method.IsAccessible(result.CallingClass, canViewProtected)) { + // TODO: exclude methods that were overridden + methods.Add(method); + } } } - -// // take out old method, when it isn't documented. -// if (method.Documentation == null || method.Documentation.Length == 0) { -// methods.Remove(method); -// return false; -// } - return true; - } - } - return false; - } - - void AddConstructors(IClass c) - { - foreach (IMethod method in c.Methods) { - if (method.IsConstructor && !method.IsStatic) { - methods.Add(method); - } - } - } - - void AddMethods(IClass c, string methodName, bool discardPrivate) - { - foreach (IMethod method in c.Methods) { - if (!(method.IsPrivate && discardPrivate) && - method.Name == methodName && - !IsAlreadyIncluded(method)) { - methods.Add(method); } } } diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs index cc3eb219b1..f77cd41c64 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/SharpDevelopTextAreaControl.cs @@ -137,28 +137,28 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor if (sdtep != null) { if (!sdtep.ShowQuickClassBrowserPanel) { - RemoveQuickClassBrowserPanel(); + RemoveQuickClassBrowserPanel(); } else { ActivateQuickClassBrowserOnDemand(); } } } - + // void IconBarMouseDown(AbstractMargin iconBar, Point mousepos, MouseButtons mouseButtons) // { // int realline = iconBar.TextArea.TextView.GetLogicalLine(mousepos); // if (realline >= 0 && realline < iconBar.TextArea.Document.TotalNumberOfLines) { -// + // // if (DebuggerService.CurrentDebugger.SupportsExecutionControl) { // DebuggerService.ToggleBreakpointAt(FileName, realline + 1, 0); // iconBar.TextArea.Refresh(iconBar); // } // } // } -// + // // void PaintIconBarBreakPoints(AbstractMargin iconBar, Graphics g, Rectangle rect) // { -// + // // lock (DebuggerService.Breakpoints) { // foreach (Breakpoint breakpoint in DebuggerService.Breakpoints) { // try { @@ -231,13 +231,13 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor ActivateQuickClassBrowserOnDemand(); } -//// Alex: routine for pulsing parser thread + //// Alex: routine for pulsing parser thread // protected void PulseParser() { // lock(DefaultParserService.ParserPulse) { // Monitor.Pulse(DefaultParserService.ParserPulse); // } // } -//// ALex: end of mod + //// ALex: end of mod InsightWindow insightWindow = null; internal CodeCompletionWindow codeCompletionWindow = null; @@ -255,7 +255,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor return false; } } - + // some other languages could support it protected virtual bool SupportsRoundBracket { get { @@ -273,7 +273,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor switch (ch) { case ' ': - //TextEditorProperties.AutoInsertTemplates + //TextEditorProperties.AutoInsertTemplates string word = GetWordBeforeCaret(); try { if ((isCSharpOrVBNet||SupportsNew) && word.ToLower() == "new") { @@ -304,8 +304,8 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } } } - } catch (Exception e) { - Console.WriteLine("EXCEPTION: " + e); + } catch (Exception e) { + LogException(e); } goto case '.'; case '<': @@ -317,7 +317,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } } } catch (Exception e) { - Console.WriteLine("EXCEPTION: " + e); + LogException(e); } return false; case '(': @@ -335,7 +335,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } } } catch (Exception e) { - Console.WriteLine("EXCEPTION: " + e); + LogException(e); } return false; case '[': @@ -355,7 +355,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } } catch (Exception e) { - Console.WriteLine("EXCEPTION: " + e); + LogException(e); } return false; case '.': @@ -369,20 +369,26 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } // TextAreaPainter.IHaveTheFocusLock = false; } catch (Exception e) { - Console.WriteLine("EXCEPTION: " + e); + LogException(e); } return false; -//// Alex: reparse file on ; - end of statement + //// Alex: reparse file on ; - end of statement // case '}': // case ';': // case ')': // reparse on closing bracket for foreach and for definitions // PulseParser(); // return false; -//// Alex: end of mod + //// Alex: end of mod } return false; } + private void LogException(Exception ex) + { + Console.WriteLine(); + Console.WriteLine("EXCEPTION: " + ex); + Console.Beep(); // notify user + } public string GetWordBeforeCaret() { @@ -480,6 +486,6 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor // { // return new HtmlDeclarationViewWindow(); // } -// + // } } diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs index fd7aec8a38..11ca065e9a 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs @@ -392,8 +392,6 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor parseInfo = ParserService.GetParseInformation(fileName); } textAreaControl.Document.FoldingManager.UpdateFoldings(fileName, parseInfo); -//// Alex free parsings - not sure if better place is in UpdateFoldings asap - parseInfo=null; } } @@ -401,8 +399,6 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor { if (textAreaControl.TextEditorProperties.EnableFolding) { textAreaControl.Document.FoldingManager.UpdateFoldings(TitleName, parseInfo); -//// Alex free parsings - parseInfo=null; textAreaControl.ActiveTextAreaControl.TextArea.Invoke(new VoidDelegate(textAreaControl.ActiveTextAreaControl.TextArea.Refresh), new object[] { textAreaControl.ActiveTextAreaControl.TextArea.FoldMargin}); } }