From 588845f7e7ac6f71adfe0aa77f39f5940e39c227 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 28 Jul 2005 15:08:45 +0000 Subject: [PATCH] Keyword completion is not activated in comments anymore. VB lexer now reads documentation comments. Resolver now distinguishes between Type and Default context -> property declarations like "public Size Size {" resolve properly (TypeResolveResult for the first Size, MixedResolveResult for the second) git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@267 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/CSharpCompletionBinding.cs | 14 ++++++++++++-- .../Project/Src/Parser/ExpressionFinder.cs | 10 ++++++++-- .../Project/Src/Parser/ExpressionFinder.cs | 5 +++++ .../VBNetBinding/Project/Src/Parser/Parser.cs | 1 + .../Project/Src/Lexer/VBNet/Lexer.cs | 19 ++++++++++++++++++- .../NRefactoryResolver/NRefactoryResolver.cs | 12 +++++++----- .../Base/Project/Src/Dom/ResolveResult.cs | 11 +++++++++++ .../Src/Services/Debugger/DebuggerService.cs | 2 ++ .../CommentCompletionDataProvider.cs | 2 +- 9 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs index 1cb3eede32..c978ab292e 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs @@ -54,6 +54,7 @@ namespace CSharpBinding } } if (context != null) { + if (IsInComment(editor)) return false; editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(context), ch); return true; } else if (EnableMethodInsight && CodeCompletionOptions.InsightEnabled) { @@ -160,6 +161,13 @@ namespace CSharpBinding } } + bool IsInComment(SharpDevelopTextAreaControl editor) + { + Parser.ExpressionFinder ef = new Parser.ExpressionFinder(editor.FileName); + int cursor = editor.ActiveTextAreaControl.Caret.Offset; + return ef.FilterComments(editor.Document.GetText(0, cursor + 1), ref cursor) == null; + } + public override bool HandleKeyword(SharpDevelopTextAreaControl editor, string word) { // TODO: Assistance writing Methods/Fields/Properties/Events: @@ -167,18 +175,20 @@ namespace CSharpBinding // and possible return types. switch (word) { case "using": + if (IsInComment(editor)) return false; // TODO: check if we are inside class/namespace editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(ExpressionContext.Namespace), ' '); return true; case "as": case "is": + if (IsInComment(editor)) return false; editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(ExpressionContext.Type), ' '); return true; - case "new": - return ShowNewCompletion(editor); case "override": // TODO: Suggest list of virtual methods to override return false; + case "new": + return ShowNewCompletion(editor); default: return base.HandleKeyword(editor, word); } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs index a1071e98f1..2909a86546 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs @@ -192,11 +192,14 @@ namespace CSharpBinding.Parser return CreateResult(null, textWithoutComments, offsetWithoutComments); StringBuilder b = new StringBuilder(expressionBeforeOffset); // append characters after expression + bool wordFollowing = false; for (int i = offset + 1; i < inText.Length; ++i) { char c = inText[i]; if (Char.IsLetterOrDigit(c)) { - if (Char.IsWhiteSpace(inText, i - 1)) + if (Char.IsWhiteSpace(inText, i - 1)) { + wordFollowing = true; break; + } b.Append(c); } else if (Char.IsWhiteSpace(c)) { // ignore whitespace @@ -217,7 +220,10 @@ namespace CSharpBinding.Parser break; } } - return CreateResult(b.ToString(), textWithoutComments, offsetWithoutComments); + ExpressionResult res = CreateResult(b.ToString(), textWithoutComments, offsetWithoutComments); + if (res.Context == ExpressionContext.Default && wordFollowing) + res.Context = ExpressionContext.Type; + return res; } int FindEndOfTypeParameters(string inText, int offset) diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/ExpressionFinder.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/ExpressionFinder.cs index 7718388afc..097102e364 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/ExpressionFinder.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/ExpressionFinder.cs @@ -24,6 +24,8 @@ namespace VBNetBinding.Parser return new ExpressionResult(expression.Substring(8).TrimStart(), ExpressionContext.Namespace, null); if (expression.Length > 4 && expression.Substring(0, 4).Equals("New ", StringComparison.InvariantCultureIgnoreCase)) return new ExpressionResult(expression.Substring(4).TrimStart(), ExpressionContext.ObjectCreation, null); + if (curTokenType == Ident && lastIdentifier.Equals("as", StringComparison.InvariantCultureIgnoreCase)) + return new ExpressionResult(expression, ExpressionContext.Type); return new ExpressionResult(expression); } @@ -291,6 +293,8 @@ namespace VBNetBinding.Parser return tokenStateName[state]; } + string lastIdentifier; + void ReadNextToken() { char ch = GetNext(); @@ -354,6 +358,7 @@ namespace VBNetBinding.Parser curTokenType = Using; break; default: + lastIdentifier = ident; curTokenType = Ident; break; } diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs index edabed1545..e89d9b83bd 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/Parser/Parser.cs @@ -109,6 +109,7 @@ namespace VBNetBinding.Parser p.Parse(); NRefactoryASTConvertVisitor visitor = new NRefactoryASTConvertVisitor(projectContent); + visitor.Specials = p.Lexer.SpecialTracker.CurrentSpecials; visitor.Visit(p.CompilationUnit, null); visitor.Cu.FileName = fileName; visitor.Cu.ErrorsDuringCompile = p.Errors.count > 0; diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs index b89248e017..fe9ac11198 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs @@ -552,9 +552,10 @@ namespace ICSharpCode.NRefactory.Parser.VB void ReadComment() { - specialTracker.StartComment(CommentType.SingleLine, new Point(col, line)); + Point startPos = new Point(col, line); sb.Length = 0; StringBuilder curWord = specialCommentHash != null ? new StringBuilder() : null; + int missingApostrophes = 2; // no. of ' missing until it is a documentation comment int x = col; int y = line; int nextChar; @@ -567,6 +568,19 @@ namespace ICSharpCode.NRefactory.Parser.VB } sb.Append(ch); + + if (missingApostrophes > 0) { + if (ch == '\'' || ch == '\u2018' || ch == '\u2019') { + if (--missingApostrophes == 0) { + specialTracker.StartComment(CommentType.Documentation, startPos); + sb.Length = 0; + } + } else { + specialTracker.StartComment(CommentType.SingleLine, startPos); + missingApostrophes = 0; + } + } + if (specialCommentHash != null) { if (Char.IsLetter(ch)) { curWord.Append(ch); @@ -583,6 +597,9 @@ namespace ICSharpCode.NRefactory.Parser.VB } } } + if (missingApostrophes > 0) { + specialTracker.StartComment(CommentType.SingleLine, startPos); + } specialTracker.AddString(sb.ToString()); specialTracker.FinishComment(new Point(col, line)); } diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs index cccf7c884c..d337ec9c03 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs @@ -172,7 +172,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } } - return ResolveInternal(expr); + return ResolveInternal(expr, expressionResult.Context); } string GetAttributeName(Expression expr) @@ -225,7 +225,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return null; } - ResolveResult ResolveInternal(Expression expr) + ResolveResult ResolveInternal(Expression expr, ExpressionContext context) { TypeVisitor typeVisitor = new TypeVisitor(this); IReturnType type; @@ -239,7 +239,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return CreateMemberResolveResult(method); } else { // InvocationExpression can also be a delegate/event call - ResolveResult invocationTarget = ResolveInternal((expr as InvocationExpression).TargetObject); + ResolveResult invocationTarget = ResolveInternal((expr as InvocationExpression).TargetObject, ExpressionContext.Default); if (invocationTarget == null) return null; type = invocationTarget.ResolvedType; @@ -278,7 +278,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return result; } } else if (expr is IdentifierExpression) { - ResolveResult result = ResolveIdentifier(((IdentifierExpression)expr).Identifier); + ResolveResult result = ResolveIdentifier(((IdentifierExpression)expr).Identifier, context); if (result != null) return result; } else if (expr is TypeReferenceExpression) { @@ -434,7 +434,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver } #region Resolve Identifier - ResolveResult ResolveIdentifier(string identifier) + ResolveResult ResolveIdentifier(string identifier, ExpressionContext context) { ResolveResult result = ResolveIdentifierInternal(identifier); if (result is TypeResolveResult) @@ -464,6 +464,8 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (result == null) return result2; if (result2 == null) return result; + if (context == ExpressionContext.Type) + return result2; return new MixedResolveResult(result, result2); } diff --git a/src/Main/Base/Project/Src/Dom/ResolveResult.cs b/src/Main/Base/Project/Src/Dom/ResolveResult.cs index 2880be988e..0db520c578 100644 --- a/src/Main/Base/Project/Src/Dom/ResolveResult.cs +++ b/src/Main/Base/Project/Src/Dom/ResolveResult.cs @@ -121,6 +121,12 @@ namespace ICSharpCode.SharpDevelop.Dom public class MixedResolveResult : ResolveResult { ResolveResult primaryResult, secondaryResult; + + public ResolveResult PrimaryResult { + get { + return primaryResult; + } + } public MixedResolveResult(ResolveResult primaryResult, ResolveResult secondaryResult) : base(primaryResult.CallingClass, primaryResult.CallingMember, primaryResult.ResolvedType) @@ -129,6 +135,11 @@ namespace ICSharpCode.SharpDevelop.Dom this.secondaryResult = secondaryResult; } + public override FilePosition GetDefinitionPosition() + { + return primaryResult.GetDefinitionPosition(); + } + public override ArrayList GetCompletionData(IProjectContent projectContent) { ArrayList result = primaryResult.GetCompletionData(projectContent); diff --git a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs index e1d88b1d94..06b882038e 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs @@ -329,6 +329,8 @@ namespace ICSharpCode.Core { if (result == null) return null; + if (result is MixedResolveResult) + return GetText(((MixedResolveResult)result).PrimaryResult); IAmbience ambience = AmbienceService.CurrentAmbience; ambience.ConversionFlags = ConversionFlags.StandardConversionFlags | ConversionFlags.ShowAccessibility; if (result is MemberResolveResult) { 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 724c4c4ad2..f6faa7554c 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 @@ -84,7 +84,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor caretColumn = textArea.Caret.Column; LineSegment caretLine = textArea.Document.GetLineSegment(caretLineNumber); string lineText = textArea.Document.GetText(caretLine.Offset, caretLine.Length); - if (!lineText.Trim().StartsWith("///")) { + if (!lineText.Trim().StartsWith("///") && !lineText.Trim().StartsWith("'''")) { return null; }