Browse Source

Implemented SD2-572: Enum autocomplete

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1587 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
94832e929a
  1. 66
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs
  2. 84
      src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs

66
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs

@ -16,6 +16,7 @@ using ICSharpCode.SharpDevelop.Dom; @@ -16,6 +16,7 @@ using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver;
using ICSharpCode.NRefactory.Parser;
using AST = ICSharpCode.NRefactory.Parser.AST;
using CSTokens = ICSharpCode.NRefactory.Parser.CSharp.Tokens;
namespace CSharpBinding
@ -115,6 +116,17 @@ namespace CSharpBinding @@ -115,6 +116,17 @@ namespace CSharpBinding
}
}
}
} else if (position > 0) {
ExpressionResult result = ef.FindFullExpression(documentText, position);
if(result.Expression != null) {
ResolveResult resolveResult = ParserService.Resolve(result, editor.ActiveTextAreaControl.Caret.Line + 1, editor.ActiveTextAreaControl.Caret.Column + 1, editor.FileName, documentText);
if (resolveResult != null && resolveResult.ResolvedType != null) {
if (ProvideContextCompletion(editor, resolveResult.ResolvedType, ch)) {
return true;
}
}
}
}
} else if (ch == ';') {
LineSegment curLine = editor.Document.GetLineSegmentForOffset(cursor);
@ -157,6 +169,7 @@ namespace CSharpBinding @@ -157,6 +169,7 @@ namespace CSharpBinding
return false;
}
#region Re-show insight window
void ShowInsight(SharpDevelopTextAreaControl editor, MethodInsightDataProvider dp, Stack<ResolveResult> parameters, char charTyped)
{
int paramCount = parameters.Count;
@ -202,10 +215,10 @@ namespace CSharpBinding @@ -202,10 +215,10 @@ namespace CSharpBinding
}
}
void ProvideContextCompletion(SharpDevelopTextAreaControl editor, IReturnType expected, char charTyped)
bool ProvideContextCompletion(SharpDevelopTextAreaControl editor, IReturnType expected, char charTyped)
{
IClass c = expected.GetUnderlyingClass();
if (c == null) return;
if (c == null) return false;
if (c.ClassType == ClassType.Enum) {
CtrlSpaceCompletionDataProvider cdp = new CtrlSpaceCompletionDataProvider();
cdp.ForceNewExpression = true;
@ -223,11 +236,14 @@ namespace CSharpBinding @@ -223,11 +236,14 @@ namespace CSharpBinding
}
}
if (cache.DefaultIndex >= 0) {
cache.InsertSpace = true;
if (charTyped != ' ') cache.InsertSpace = true;
editor.ShowCompletionWindow(cache, charTyped);
return true;
}
}
return false;
}
#endregion
bool IsInComment(SharpDevelopTextAreaControl editor)
{
@ -258,6 +274,8 @@ namespace CSharpBinding @@ -258,6 +274,8 @@ namespace CSharpBinding
return true;
case "new":
return ShowNewCompletion(editor);
case "case":
return DoCaseCompletion(editor);
default:
return base.HandleKeyword(editor, word);
}
@ -274,5 +292,47 @@ namespace CSharpBinding @@ -274,5 +292,47 @@ namespace CSharpBinding
}
return false;
}
#region "case"-keyword completion
bool DoCaseCompletion(SharpDevelopTextAreaControl editor)
{
ICSharpCode.TextEditor.Caret caret = editor.ActiveTextAreaControl.Caret;
NRefactoryResolver r = new NRefactoryResolver(SupportedLanguage.CSharp);
if (r.Initialize(editor.FileName, caret.Line + 1, caret.Column + 1)) {
AST.INode currentMember = r.ParseCurrentMember(editor.Text);
if (currentMember != null) {
CaseCompletionSwitchFinder ccsf = new CaseCompletionSwitchFinder(caret.Line + 1, caret.Column + 1);
currentMember.AcceptVisitor(ccsf, null);
if (ccsf.bestStatement != null) {
r.RunLookupTableVisitor(currentMember);
ResolveResult rr = r.ResolveInternal(ccsf.bestStatement.SwitchExpression, ExpressionContext.Default);
if (rr != null && rr.ResolvedType != null) {
return ProvideContextCompletion(editor, rr.ResolvedType, ' ');
}
}
}
}
return false;
}
private class CaseCompletionSwitchFinder : AbstractAstVisitor
{
Location caretLocation;
internal AST.SwitchStatement bestStatement;
public CaseCompletionSwitchFinder(int caretLine, int caretColumn)
{
caretLocation = new Location(caretColumn, caretLine);
}
public override object Visit(AST.SwitchStatement switchStatement, object data)
{
if (switchStatement.StartLocation < caretLocation && caretLocation < switchStatement.EndLocation) {
bestStatement = switchStatement;
}
return base.Visit(switchStatement, data);
}
}
#endregion
}
}

84
src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Parser;
@ -141,20 +142,14 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -141,20 +142,14 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
public ResolveResult Resolve(ExpressionResult expressionResult,
int caretLineNumber,
int caretColumn,
string fileName,
string fileContent)
public bool Initialize(string fileName, int caretLineNumber, int caretColumn)
{
string expression = GetFixedExpression(expressionResult);
this.caretLine = caretLineNumber;
this.caretColumn = caretColumn;
ParseInformation parseInfo = ParserService.GetParseInformation(fileName);
if (parseInfo == null) {
return null;
return false;
}
cu = parseInfo.MostRecentCompilationUnit;
@ -162,6 +157,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -162,6 +157,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
if (cu != null) {
callingClass = cu.GetInnermostClass(caretLine, caretColumn);
}
return true;
}
public ResolveResult Resolve(ExpressionResult expressionResult,
int caretLineNumber,
int caretColumn,
string fileName,
string fileContent)
{
string expression = GetFixedExpression(expressionResult);
if (!Initialize(fileName, caretLineNumber, caretColumn))
return null;
Expression expr = null;
if (language == SupportedLanguage.VBNet) {
@ -245,21 +253,49 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -245,21 +253,49 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
}
}
public INode ParseCurrentMember(string fileContent)
{
CompilationUnit cu = ParseCurrentMemberAsCompilationUnit(fileContent);
if (cu != null && cu.Children.Count > 0) {
TypeDeclaration td = cu.Children[0] as TypeDeclaration;
if (td != null && td.Children.Count > 0) {
return td.Children[0];
}
}
return null;
}
public CompilationUnit ParseCurrentMemberAsCompilationUnit(string fileContent)
{
System.IO.TextReader content = ExtractCurrentMethod(fileContent);
if (content != null) {
ICSharpCode.NRefactory.Parser.IParser p = ParserFactory.CreateParser(language, content);
p.Parse();
return p.CompilationUnit;
} else {
return null;
}
}
void RunLookupTableVisitor(string fileContent)
{
lookupTableVisitor = new LookupTableVisitor(languageProperties.NameComparer);
callingMember = GetCurrentMember();
if (callingMember != null) {
System.IO.TextReader content = ExtractMethod(fileContent, callingMember);
if (content != null) {
ICSharpCode.NRefactory.Parser.IParser p = ParserFactory.CreateParser(language, content);
p.Parse();
lookupTableVisitor.Visit(p.CompilationUnit, null);
CompilationUnit cu = ParseCurrentMemberAsCompilationUnit(fileContent);
if (cu != null) {
lookupTableVisitor.Visit(cu, null);
}
}
}
public void RunLookupTableVisitor(INode currentMemberNode)
{
lookupTableVisitor = new LookupTableVisitor(languageProperties.NameComparer);
currentMemberNode.AcceptVisitor(lookupTableVisitor, null);
}
string GetAttributeName(Expression expr)
{
if (expr is IdentifierExpression) {
@ -310,7 +346,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -310,7 +346,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
ResolveResult ResolveInternal(Expression expr, ExpressionContext context)
public ResolveResult ResolveInternal(Expression expr, ExpressionContext context)
{
TypeVisitor typeVisitor = new TypeVisitor(this);
IReturnType type;
@ -459,12 +495,22 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -459,12 +495,22 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return ResolveMethod(type, fieldReferenceExpression.FieldName);
}
public TextReader ExtractCurrentMethod(string fileContent)
{
if (callingMember == null)
callingMember = GetCurrentMember();
if (callingMember == null)
return null;
return ExtractMethod(fileContent, callingMember, language, caretLine);
}
/// <summary>
/// Creates a new class containing only the specified member.
/// This is useful because we only want to parse current method for local variables,
/// as all fields etc. are already prepared in the AST.
/// </summary>
System.IO.TextReader ExtractMethod(string fileContent, IMember member)
public static TextReader ExtractMethod(string fileContent, IMember member,
SupportedLanguage language, int caretLine)
{
// As the parse information is always some seconds old, the end line could be wrong
// if the user just inserted a line in the method.
@ -998,11 +1044,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -998,11 +1044,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
callingMember = GetCurrentMember();
if (callingMember != null) {
System.IO.TextReader content = ExtractMethod(fileContent, callingMember);
if (content != null) {
ICSharpCode.NRefactory.Parser.IParser p = ParserFactory.CreateParser(language, content);
p.Parse();
lookupTableVisitor.Visit(p.CompilationUnit, null);
CompilationUnit parsedCu = ParseCurrentMemberAsCompilationUnit(fileContent);
if (cu != null) {
lookupTableVisitor.Visit(parsedCu, null);
}
}

Loading…
Cancel
Save