1
1
using System . Collections . Generic ;
2
- using System . Diagnostics ;
3
- using System . Windows . Forms ;
2
+ using System . Linq ;
4
3
using Rubberduck . Settings ;
5
4
using Rubberduck . VBEditor ;
6
5
using Rubberduck . VBEditor . Events ;
@@ -10,86 +9,92 @@ namespace Rubberduck.AutoComplete.Service
10
9
{
11
10
public class SelfClosingPairHandler : AutoCompleteHandlerBase
12
11
{
13
- private static readonly IEnumerable < SelfClosingPair > SelfClosingPairs = new List < SelfClosingPair >
14
- {
15
- new SelfClosingPair ( '(' , ')' ) ,
16
- new SelfClosingPair ( '"' , '"' ) ,
17
- new SelfClosingPair ( '[' , ']' ) ,
18
- new SelfClosingPair ( '{' , '}' ) ,
19
- } ;
20
-
12
+ private readonly IDictionary < char , SelfClosingPair > _selfClosingPairs ;
21
13
private readonly SelfClosingPairCompletionService _scpService ;
22
14
23
15
public SelfClosingPairHandler ( ICodePaneHandler pane , SelfClosingPairCompletionService scpService )
24
16
: base ( pane )
25
17
{
18
+ var pairs = new [ ]
19
+ {
20
+ new SelfClosingPair ( '(' , ')' ) ,
21
+ new SelfClosingPair ( '"' , '"' ) ,
22
+ new SelfClosingPair ( '[' , ']' ) ,
23
+ new SelfClosingPair ( '{' , '}' ) ,
24
+ } ;
25
+ _selfClosingPairs = pairs
26
+ . Select ( p => new { Key = p . OpeningChar , Pair = p } )
27
+ . Union ( pairs . Where ( p => ! p . IsSymetric ) . Select ( p => new { Key = p . ClosingChar , Pair = p } ) )
28
+ . ToDictionary ( p => p . Key , p => p . Pair ) ;
29
+
26
30
_scpService = scpService ;
27
31
}
28
32
29
33
public override CodeString Handle ( AutoCompleteEventArgs e , AutoCompleteSettings settings )
30
34
{
35
+ if ( ! _selfClosingPairs . TryGetValue ( e . Character , out var pair ) && e . Character != '\b ' )
36
+ {
37
+ return null ;
38
+ }
39
+
31
40
var original = CodePaneHandler . GetCurrentLogicalLine ( e . Module ) ;
32
- foreach ( var pair in SelfClosingPairs )
41
+ if ( ! HandleInternal ( e , original , pair , out var result ) )
33
42
{
34
- var isPresent = original . CaretLine . EndsWith ( $ "{ pair . OpeningChar } { pair . ClosingChar } ") ;
35
-
36
- var result = ExecuteSelfClosingPair ( e , original , pair ) ;
37
- if ( result == null )
38
- {
39
- continue ;
40
- }
41
-
42
- var prettified = CodePaneHandler . Prettify ( e . Module , original ) ;
43
- if ( ! isPresent && original . CaretLine . Length + 2 == prettified . CaretLine . Length &&
44
- prettified . CaretLine . EndsWith ( $ "{ pair . OpeningChar } { pair . ClosingChar } ") )
45
- {
46
- // prettifier just added the pair for us; likely a Sub or Function statement.
47
- prettified = original ; // pretend this didn't happen. note: probably breaks if original has extra whitespace.
48
- }
49
-
50
- result = ExecuteSelfClosingPair ( e , prettified , pair ) ;
51
- if ( result == null )
52
- {
53
- continue ;
54
- }
55
-
56
- result = CodePaneHandler . Prettify ( e . Module , result ) ;
57
-
58
- var currentLine = result . Lines [ result . CaretPosition . StartLine ] ;
59
- if ( ! string . IsNullOrWhiteSpace ( currentLine ) &&
60
- currentLine . EndsWith ( " " ) &&
61
- result . CaretPosition . StartColumn == currentLine . Length )
62
- {
63
- result = result . ReplaceLine ( result . CaretPosition . StartLine , currentLine . TrimEnd ( ) ) ;
64
- }
65
-
66
- if ( pair . OpeningChar == '(' && e . Character != '\b ' && ! result . CaretLine . EndsWith ( $ "{ pair . OpeningChar } { pair . ClosingChar } ") )
67
- {
68
- // VBE eats it. just bail out.
69
- return null ;
70
- }
71
-
72
- e . Handled = true ;
73
- result = new CodeString ( result . Code , result . CaretPosition , new Selection ( result . SnippetPosition . StartLine , 1 , result . SnippetPosition . EndLine , 1 ) ) ;
74
- return result ;
43
+ return null ;
75
44
}
76
45
77
- return null ;
46
+ var snippetPosition = new Selection ( result . SnippetPosition . StartLine , 1 , result . SnippetPosition . EndLine , 1 ) ;
47
+ result = new CodeString ( result . Code , result . CaretPosition , snippetPosition ) ;
48
+
49
+ e . Handled = true ;
50
+ return result ;
78
51
}
79
52
80
- private CodeString ExecuteSelfClosingPair ( AutoCompleteEventArgs e , CodeString original , SelfClosingPair pair )
53
+ private bool HandleInternal ( AutoCompleteEventArgs e , CodeString original , SelfClosingPair pair , out CodeString result )
81
54
{
82
- CodeString result ;
83
- if ( e . Character == '\b ' && original . CaretPosition . StartColumn > 1 )
55
+ var isPresent = original . CaretLine . EndsWith ( $ "{ pair . OpeningChar } { pair . ClosingChar } ") ;
56
+
57
+ if ( ! ExecuteSelfClosingPair ( e , original , pair , out result ) )
84
58
{
85
- result = _scpService . Execute ( pair , original , Keys . Back ) ;
59
+ return false ;
86
60
}
87
- else
61
+
62
+ var prettified = CodePaneHandler . Prettify ( e . Module , original ) ;
63
+ if ( ! isPresent && original . CaretLine . Length + 2 == prettified . CaretLine . Length &&
64
+ prettified . CaretLine . EndsWith ( $ "{ pair . OpeningChar } { pair . ClosingChar } ") )
88
65
{
89
- result = _scpService . Execute ( pair , original , e . Character ) ;
66
+ // prettifier just added the pair for us; likely a Sub or Function statement.
67
+ prettified = original ; // pretend this didn't happen. note: probably breaks if original has extra whitespace.
90
68
}
91
69
92
- return result ;
70
+ if ( ! ExecuteSelfClosingPair ( e , prettified , pair , out result ) )
71
+ {
72
+ return false ;
73
+ }
74
+
75
+ result = CodePaneHandler . Prettify ( e . Module , result ) ;
76
+
77
+ var currentLine = result . Lines [ result . CaretPosition . StartLine ] ;
78
+ if ( ! string . IsNullOrWhiteSpace ( currentLine ) &&
79
+ currentLine . EndsWith ( " " ) &&
80
+ result . CaretPosition . StartColumn == currentLine . Length )
81
+ {
82
+ result = result . ReplaceLine ( result . CaretPosition . StartLine , currentLine . TrimEnd ( ) ) ;
83
+ }
84
+
85
+ if ( pair . OpeningChar == '(' && e . Character != '\b ' &&
86
+ ! result . CaretLine . EndsWith ( $ "{ pair . OpeningChar } { pair . ClosingChar } ") )
87
+ {
88
+ // VBE eats it. just bail out.
89
+ return true ;
90
+ }
91
+
92
+ return true ;
93
+ }
94
+
95
+ private bool ExecuteSelfClosingPair ( AutoCompleteEventArgs e , CodeString original , SelfClosingPair pair , out CodeString result )
96
+ {
97
+ return _scpService . Execute ( pair , original , e . Character , out result ) ;
93
98
}
94
99
}
95
100
}
0 commit comments