10 changed files with 336 additions and 11 deletions
@ -0,0 +1,77 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using ICSharpCode.SharpDevelop.Editor; |
||||||
|
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; |
||||||
|
|
||||||
|
namespace ICSharpCode.PythonBinding |
||||||
|
{ |
||||||
|
public class PythonInsightWindowHandler : IInsightWindowHandler |
||||||
|
{ |
||||||
|
ITextEditor editor; |
||||||
|
IInsightWindow insightWindow; |
||||||
|
|
||||||
|
public void InitializeOpenedInsightWindow(ITextEditor editor, IInsightWindow insightWindow) |
||||||
|
{ |
||||||
|
this.editor = editor; |
||||||
|
this.insightWindow = insightWindow; |
||||||
|
int offset = insightWindow.StartOffset; |
||||||
|
insightWindow.DocumentChanged += DocumentChanged; |
||||||
|
} |
||||||
|
|
||||||
|
void DocumentChanged(object sender, TextChangeEventArgs e) |
||||||
|
{ |
||||||
|
if (IsOutsideMethodCall()) { |
||||||
|
insightWindow.Close(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool IsOutsideMethodCall() |
||||||
|
{ |
||||||
|
string text = GetTextInsideMethodCallUpToCursor(); |
||||||
|
return TextContainsClosingBracketForMethod(text); |
||||||
|
} |
||||||
|
|
||||||
|
string GetTextInsideMethodCallUpToCursor() |
||||||
|
{ |
||||||
|
int insightStartOffset = insightWindow.StartOffset; |
||||||
|
int currentOffset = editor.Caret.Offset; |
||||||
|
int length = currentOffset - insightStartOffset; |
||||||
|
if (length < 0) { |
||||||
|
// Force completion window to close by returning the close bracket.
|
||||||
|
return ")"; |
||||||
|
} |
||||||
|
return editor.Document.GetText(insightStartOffset, length); |
||||||
|
} |
||||||
|
|
||||||
|
bool TextContainsClosingBracketForMethod(string text) |
||||||
|
{ |
||||||
|
int bracketCount = 1; |
||||||
|
foreach (char ch in text) { |
||||||
|
switch (ch) { |
||||||
|
case '(': |
||||||
|
bracketCount++; |
||||||
|
break; |
||||||
|
case ')': |
||||||
|
bracketCount--; |
||||||
|
if (bracketCount == 0) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public bool InsightRefreshOnComma(ITextEditor editor, char ch, out IInsightWindow insightWindow) |
||||||
|
{ |
||||||
|
insightWindow = null; |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
public void HighlightParameter(IInsightWindow window, int index) |
||||||
|
{ |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using NUnit.Framework; |
||||||
|
using PythonBinding.Tests.Utils; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Completion |
||||||
|
{ |
||||||
|
[TestFixture] |
||||||
|
public class PythonCodeCompletionBindingTests |
||||||
|
{ |
||||||
|
TestablePythonCodeCompletionBinding completionBinding; |
||||||
|
|
||||||
|
void CreatePythonCodeCompletionBinding() |
||||||
|
{ |
||||||
|
completionBinding = new TestablePythonCodeCompletionBinding(); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void InsightHandler_CreateNewCodecompletionBindingInstance_IsSetToPythonInsightWindowHandlerInstance() |
||||||
|
{ |
||||||
|
CreatePythonCodeCompletionBinding(); |
||||||
|
PythonInsightWindowHandler handler = completionBinding.PythonInsightWindowHandler; |
||||||
|
Assert.IsNotNull(handler); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,126 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using ICSharpCode.PythonBinding; |
||||||
|
using ICSharpCode.Scripting.Tests.Utils; |
||||||
|
using ICSharpCode.SharpDevelop.Editor; |
||||||
|
using NUnit.Framework; |
||||||
|
using PythonBinding.Tests.Utils; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Completion |
||||||
|
{ |
||||||
|
[TestFixture] |
||||||
|
public class PythonInsightWindowHandlerTests |
||||||
|
{ |
||||||
|
PythonInsightWindowHandler handler; |
||||||
|
MockTextEditor fakeTextEditor; |
||||||
|
FakeInsightWindow fakeInsightWindow; |
||||||
|
|
||||||
|
void CreatePythonInsightWindowHandler() |
||||||
|
{ |
||||||
|
fakeTextEditor = new MockTextEditor(); |
||||||
|
fakeInsightWindow = new FakeInsightWindow(); |
||||||
|
handler = new PythonInsightWindowHandler(); |
||||||
|
} |
||||||
|
|
||||||
|
void InitializePythonInsightWindowHandler() |
||||||
|
{ |
||||||
|
handler.InitializeOpenedInsightWindow(fakeTextEditor, fakeInsightWindow); |
||||||
|
} |
||||||
|
|
||||||
|
TextChangeEventArgs CreateInsertedTextChangeEventArgs(int offset, string insertedText) |
||||||
|
{ |
||||||
|
return new TextChangeEventArgs(offset, String.Empty, insertedText); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void InitializeOpenedInsightWindow_CloseParenthesisCharacterAddedToDocument_InsightWindowClosed() |
||||||
|
{ |
||||||
|
CreatePythonInsightWindowHandler(); |
||||||
|
fakeTextEditor.FakeDocument.Text = "method("; |
||||||
|
fakeTextEditor.FakeCaret.Offset = 7; |
||||||
|
fakeInsightWindow.StartOffset = 7; |
||||||
|
InitializePythonInsightWindowHandler(); |
||||||
|
|
||||||
|
int newCaretOffset = 8; |
||||||
|
fakeTextEditor.FakeCaret.Offset = newCaretOffset; |
||||||
|
fakeTextEditor.FakeDocument.Text = "method()"; |
||||||
|
TextChangeEventArgs e = CreateInsertedTextChangeEventArgs(newCaretOffset, ")"); |
||||||
|
fakeInsightWindow.FireDocumentChangedEvent(e); |
||||||
|
|
||||||
|
bool closed = fakeInsightWindow.IsClosed; |
||||||
|
Assert.IsTrue(closed); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void InitializeOpenedInsightWindow_MethodCallWithCursorAtOpenBracket_InsightWindowIsClosedBeforeDocumentIsChanged() |
||||||
|
{ |
||||||
|
CreatePythonInsightWindowHandler(); |
||||||
|
fakeTextEditor.FakeDocument.Text = "method("; |
||||||
|
fakeTextEditor.FakeCaret.Offset = 7; |
||||||
|
fakeInsightWindow.StartOffset = 7; |
||||||
|
InitializePythonInsightWindowHandler(); |
||||||
|
|
||||||
|
bool closed = fakeInsightWindow.IsClosed; |
||||||
|
Assert.IsFalse(closed); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void InitializeOpenedInsightWindow_SingleCharacterAddedToDocumentAfterOpenParenthesis_InsightWindowIsNotClosed() |
||||||
|
{ |
||||||
|
CreatePythonInsightWindowHandler(); |
||||||
|
fakeTextEditor.FakeDocument.Text = "method("; |
||||||
|
fakeTextEditor.FakeCaret.Offset = 7; |
||||||
|
fakeInsightWindow.StartOffset = 7; |
||||||
|
InitializePythonInsightWindowHandler(); |
||||||
|
|
||||||
|
int newCaretOffset = 8; |
||||||
|
fakeTextEditor.FakeCaret.Offset = newCaretOffset; |
||||||
|
fakeTextEditor.FakeDocument.Text = "method(a"; |
||||||
|
TextChangeEventArgs e = CreateInsertedTextChangeEventArgs(newCaretOffset, "a"); |
||||||
|
fakeInsightWindow.FireDocumentChangedEvent(e); |
||||||
|
|
||||||
|
bool closed = fakeInsightWindow.IsClosed; |
||||||
|
Assert.IsFalse(closed); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void InitializeOpenedInsightWindow_MethodCallInsideMethodCallAndCloseParenthesisCharacterAddedToDocument_InsightWindowIsNotClosed() |
||||||
|
{ |
||||||
|
CreatePythonInsightWindowHandler(); |
||||||
|
fakeTextEditor.FakeDocument.Text = "method(a("; |
||||||
|
fakeTextEditor.FakeCaret.Offset = 9; |
||||||
|
fakeInsightWindow.StartOffset = 7; |
||||||
|
InitializePythonInsightWindowHandler(); |
||||||
|
|
||||||
|
int newCaretOffset = 10; |
||||||
|
fakeTextEditor.FakeCaret.Offset = newCaretOffset; |
||||||
|
fakeTextEditor.FakeDocument.Text = "method(a()"; |
||||||
|
TextChangeEventArgs e = CreateInsertedTextChangeEventArgs(newCaretOffset, ")"); |
||||||
|
fakeInsightWindow.FireDocumentChangedEvent(e); |
||||||
|
|
||||||
|
bool closed = fakeInsightWindow.IsClosed; |
||||||
|
Assert.IsFalse(closed); |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void InitializeOpenedInsightWindow_CharacterAddedToDocumentBeforeStartOfInsightWindow_InsightWindowClosed() |
||||||
|
{ |
||||||
|
CreatePythonInsightWindowHandler(); |
||||||
|
fakeTextEditor.FakeDocument.Text = "method("; |
||||||
|
fakeTextEditor.FakeCaret.Offset = 7; |
||||||
|
fakeInsightWindow.StartOffset = 7; |
||||||
|
InitializePythonInsightWindowHandler(); |
||||||
|
|
||||||
|
int newCaretOffset = 1; |
||||||
|
fakeTextEditor.FakeCaret.Offset = newCaretOffset; |
||||||
|
fakeTextEditor.FakeDocument.Text = "aethod("; |
||||||
|
TextChangeEventArgs e = CreateInsertedTextChangeEventArgs(newCaretOffset, "a"); |
||||||
|
fakeInsightWindow.FireDocumentChangedEvent(e); |
||||||
|
|
||||||
|
bool closed = fakeInsightWindow.IsClosed; |
||||||
|
Assert.IsTrue(closed); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||||
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using ICSharpCode.SharpDevelop.Editor; |
||||||
|
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; |
||||||
|
|
||||||
|
namespace PythonBinding.Tests.Utils |
||||||
|
{ |
||||||
|
public class FakeInsightWindow : IInsightWindow |
||||||
|
{ |
||||||
|
#pragma warning disable 67
|
||||||
|
public event EventHandler<TextChangeEventArgs> DocumentChanged; |
||||||
|
public event EventHandler SelectedItemChanged; |
||||||
|
public event EventHandler CaretPositionChanged; |
||||||
|
public event EventHandler Closed; |
||||||
|
#pragma warning restore 67
|
||||||
|
|
||||||
|
public bool IsClosed; |
||||||
|
|
||||||
|
public IList<IInsightItem> Items { |
||||||
|
get { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public IInsightItem SelectedItem { |
||||||
|
get { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
set { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public double Width { |
||||||
|
get { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
set { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public double Height { |
||||||
|
get { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
set { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public bool CloseAutomatically { |
||||||
|
get { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
set { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int StartOffset { get; set; } |
||||||
|
|
||||||
|
public int EndOffset { |
||||||
|
get { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
set { |
||||||
|
throw new NotImplementedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void Close() |
||||||
|
{ |
||||||
|
IsClosed = true; |
||||||
|
} |
||||||
|
|
||||||
|
public void FireDocumentChangedEvent(TextChangeEventArgs e) |
||||||
|
{ |
||||||
|
if (DocumentChanged != null) { |
||||||
|
DocumentChanged(this, e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue