1
+ import { uuid } from '@opensumi/ide-core-common' ;
1
2
import { IRange } from '@opensumi/monaco-editor-core' ;
2
3
import { LineRange as MonacoLineRange } from '@opensumi/monaco-editor-core/esm/vs/editor/common/diff/linesDiffComputer' ;
3
4
4
- import { EditorViewType , IRangeContrast , LineRangeType } from '../types' ;
5
+ import { ETurnDirection , IRangeContrast , LineRangeType } from '../types' ;
5
6
6
7
import { InnerRange } from './inner-range' ;
7
8
9
+ /**
10
+ * 如果 lineRange 是通过 merge 合并生成的
11
+ * 则跟 merge 相关的数据状态都在该 model 来处理
12
+ */
13
+ export class MergeStateModel {
14
+ /**
15
+ * 存储合并前的所有 lineRange 元数据
16
+ */
17
+ private metaRanges : LineRange [ ] = [ ] ;
18
+
19
+ public get isMerge ( ) : boolean {
20
+ return this . metaRanges . length > 0 ;
21
+ }
22
+
23
+ /**
24
+ * 只有当 metaRanges 里的 range 彼此都只是表面接触时才允许 combination 操作
25
+ * (能被 accept combination 意味着这块 diff 区域,左右两边的代码合并后不会出现被覆盖的情况)
26
+ * 例如
27
+ * 左边 中间 右边
28
+ * ``` ``` ```
29
+ * 1. const a = 1 const a = 2 const a = 1
30
+ * 2. const b = 1 const b = 1 const b = 2
31
+ * 3. const c = 1 const c = 2 const c = 1
32
+ * ``` ``` ```
33
+ *
34
+ * 其中第一行中间与两边都有 diff,但不管是接受左边的还是右边的,最终对结果的影响不变(接受左右两边都一样)
35
+ * 如果这三行都是这样的情况,则被允许 combination
36
+ */
37
+ public get isAllowCombination ( ) : boolean {
38
+ const length = this . metaRanges . length ;
39
+ if ( length <= 1 ) {
40
+ return false ;
41
+ }
42
+
43
+ let slow = 0 ;
44
+ for ( let fast = 0 ; fast < length ; fast ++ ) {
45
+ const slowRange = this . metaRanges [ slow ] ;
46
+ const fastRange = this . metaRanges [ fast ] ;
47
+
48
+ if ( slowRange . id === fastRange . id ) {
49
+ continue ;
50
+ }
51
+
52
+ if ( ! fastRange . isContact ( slowRange ) ) {
53
+ return false ;
54
+ }
55
+
56
+ slow += 1 ;
57
+ }
58
+
59
+ return true ;
60
+ }
61
+
62
+ public add ( range : LineRange ) : this {
63
+ this . metaRanges . push ( range ) ;
64
+ return this ;
65
+ }
66
+
67
+ public reset ( ) : this {
68
+ this . metaRanges = [ ] ;
69
+ return this ;
70
+ }
71
+
72
+ public has ( metaRange : LineRange ) : boolean {
73
+ return this . metaRanges . some ( ( m ) => m . id === metaRange . id ) ;
74
+ }
75
+
76
+ public getMetaRanges ( ) : LineRange [ ] {
77
+ return this . metaRanges ;
78
+ }
79
+ }
80
+
8
81
export class LineRange extends MonacoLineRange implements IRangeContrast {
9
82
static fromPositions ( startLineNumber : number , endLineNumber : number = startLineNumber ) : LineRange {
10
83
return new LineRange ( startLineNumber , endLineNumber ) ;
@@ -25,24 +98,35 @@ export class LineRange extends MonacoLineRange implements IRangeContrast {
25
98
return this . _isComplete ;
26
99
}
27
100
28
- private _turnDirection : EditorViewType . CURRENT | EditorViewType . INCOMING ;
29
- public get turnDirection ( ) : EditorViewType . CURRENT | EditorViewType . INCOMING {
101
+ private _turnDirection : ETurnDirection ;
102
+ public get turnDirection ( ) : ETurnDirection {
30
103
return this . _turnDirection ;
31
104
}
32
105
106
+ public get isMerge ( ) : boolean {
107
+ return this . mergeStateModel . isMerge ;
108
+ }
109
+
110
+ public get isAllowCombination ( ) : boolean {
111
+ return this . mergeStateModel . isAllowCombination ;
112
+ }
113
+
114
+ private mergeStateModel : MergeStateModel ;
115
+
33
116
constructor ( startLineNumber : number , endLineNumberExclusive : number ) {
34
117
super ( startLineNumber , endLineNumberExclusive ) ;
35
118
this . _type = 'insert' ;
36
119
this . _isComplete = false ;
37
- this . _id = `${ this . startLineNumber } _${ this . endLineNumberExclusive } _${ this . length } ` ;
120
+ this . _id = uuid ( 6 ) ;
121
+ this . mergeStateModel = new MergeStateModel ( ) ;
38
122
}
39
123
40
124
private setId ( id : string ) : this {
41
125
this . _id = id ;
42
126
return this ;
43
127
}
44
128
45
- public setTurnDirection ( t : EditorViewType . CURRENT | EditorViewType . INCOMING ) {
129
+ public setTurnDirection ( t : ETurnDirection ) {
46
130
this . _turnDirection = t ;
47
131
return this ;
48
132
}
@@ -52,13 +136,14 @@ export class LineRange extends MonacoLineRange implements IRangeContrast {
52
136
return this ;
53
137
}
54
138
55
- public setType ( v : LineRangeType ) : this {
56
- this . _type = v ;
139
+ private setMergeStateModel ( state : MergeStateModel ) : this {
140
+ this . mergeStateModel = state ;
57
141
return this ;
58
142
}
59
143
60
- public calcMargin ( range : LineRange ) : number {
61
- return this . length - range . length ;
144
+ public setType ( v : LineRangeType ) : this {
145
+ this . _type = v ;
146
+ return this ;
62
147
}
63
148
64
149
public isTendencyRight ( refer : LineRange ) : boolean {
@@ -81,6 +166,15 @@ export class LineRange extends MonacoLineRange implements IRangeContrast {
81
166
return this . endLineNumberExclusive >= range . startLineNumber && range . endLineNumberExclusive >= this . startLineNumber ;
82
167
}
83
168
169
+ /**
170
+ * 是否仅仅只是表面接触
171
+ */
172
+ public isContact ( range : LineRange ) : boolean {
173
+ return (
174
+ this . startLineNumber === range . endLineNumberExclusive || this . endLineNumberExclusive === range . startLineNumber
175
+ ) ;
176
+ }
177
+
84
178
public isInclude ( range : LineRange | InnerRange ) : boolean {
85
179
if ( range instanceof LineRange ) {
86
180
return (
@@ -99,13 +193,33 @@ export class LineRange extends MonacoLineRange implements IRangeContrast {
99
193
return this . startLineNumber === range . startLineNumber && this . length === range . length ;
100
194
}
101
195
102
- public merge ( other : LineRange ) : LineRange {
196
+ public get metaMergeRanges ( ) : LineRange [ ] {
197
+ return this . mergeStateModel . getMetaRanges ( ) ;
198
+ }
199
+
200
+ public recordMergeRange ( range : LineRange ) : this {
201
+ this . mergeStateModel . add ( range ) ;
202
+ return this ;
203
+ }
204
+
205
+ /**
206
+ * 与 other range 合并成一个 range
207
+ * @param isKeep: 是否记录被合并的 range
208
+ */
209
+ public merge ( other : LineRange , isKeep = true ) : LineRange {
210
+ if ( isKeep ) {
211
+ if ( ! this . mergeStateModel . has ( this ) ) {
212
+ this . recordMergeRange ( this ) ;
213
+ }
214
+ this . recordMergeRange ( other ) ;
215
+ }
216
+
103
217
return this . retainState (
104
218
new LineRange (
105
219
Math . min ( this . startLineNumber , other . startLineNumber ) ,
106
220
Math . max ( this . endLineNumberExclusive , other . endLineNumberExclusive ) ,
107
221
) ,
108
- ) ;
222
+ ) . setTurnDirection ( ETurnDirection . BOTH ) ;
109
223
}
110
224
111
225
// 生一个除 id 以外,state 状态都相同的 lineRange
@@ -131,7 +245,8 @@ export class LineRange extends MonacoLineRange implements IRangeContrast {
131
245
. setId ( this . _id )
132
246
. setType ( this . _type )
133
247
. setTurnDirection ( this . _turnDirection )
134
- . setComplete ( this . _isComplete ) ;
248
+ . setComplete ( this . _isComplete )
249
+ . setMergeStateModel ( this . mergeStateModel ) ;
135
250
}
136
251
137
252
public override delta ( offset : number ) : LineRange {
0 commit comments