1+ import { FormattingOptions , TextEdit , TextDocument } from 'vscode' ;
2+ import { Position , Range } from 'vscode' ;
3+ import { CodeBlockFormatProvider , BlockRegEx } from './contracts' ;
4+ import { IF_REGEX , ELIF_REGEX , ELSE_REGEX , FOR_IN_REGEX , ASYNC_FOR_IN_REGEX , WHILE_REGEX } from './contracts' ;
5+ import { DEF_REGEX , ASYNC_DEF_REGEX , CLASS_REGEX } from './contracts' ;
6+
7+ export class ElseFormatProvider implements CodeBlockFormatProvider {
8+ private regExps : BlockRegEx [ ] ;
9+ private boundaryRegExps : BlockRegEx [ ] ;
10+ constructor ( ) {
11+ this . regExps = [
12+ IF_REGEX ,
13+ ELIF_REGEX ,
14+ FOR_IN_REGEX ,
15+ ASYNC_FOR_IN_REGEX ,
16+ WHILE_REGEX
17+ ] ;
18+ this . boundaryRegExps = [
19+ DEF_REGEX ,
20+ ASYNC_DEF_REGEX ,
21+ CLASS_REGEX
22+ ] ;
23+ }
24+ canProvideEdits ( line : string ) : boolean {
25+ return ELSE_REGEX . test ( line ) ;
26+ }
27+
28+ provideEdits ( document : TextDocument , position : Position , ch : string , options : FormattingOptions , line : string ) : TextEdit [ ] {
29+ // We can have else for the following blocks:
30+ // if:
31+ // elif x:
32+ // for x in y:
33+ // while x:
34+
35+ const indexOfElse = line . indexOf ( ELSE_REGEX . startWord ) ;
36+
37+ // We need to find a block statement that is less than or equal to this statement block (but not greater)
38+ for ( let lineNumber = position . line - 1 ; lineNumber > 0 ; lineNumber -- ) {
39+ const line = document . lineAt ( lineNumber ) . text ;
40+
41+ // Oops, we've reached a boundary (like the function or class definition)
42+ // Get out of here
43+ if ( this . boundaryRegExps . some ( value => value . test ( line ) ) ) {
44+ return [ ] ;
45+ }
46+
47+ const blockRegEx = this . regExps . find ( value => value . test ( line ) ) ;
48+ if ( ! blockRegEx ) {
49+ continue ;
50+ }
51+
52+ const startOfBlockInLine = line . indexOf ( blockRegEx . startWord ) ;
53+ if ( startOfBlockInLine > indexOfElse ) {
54+ continue ;
55+ }
56+
57+ const startPosition = new Position ( position . line , 0 ) ;
58+ const endPosition = new Position ( position . line , indexOfElse - startOfBlockInLine ) ;
59+ return [
60+ TextEdit . delete ( new Range ( startPosition , endPosition ) )
61+ ] ;
62+ }
63+
64+ return [ ] ;
65+ }
66+ }
0 commit comments