1
1
import {
2
2
asyncSafety ,
3
3
type ActionDescriptor ,
4
+ type Modifier ,
4
5
type ScopeType ,
5
6
type SimpleScopeTypeType ,
6
7
} from "@cursorless/common" ;
@@ -11,9 +12,10 @@ import { endToEndTestSetup } from "../endToEndTestSetup";
11
12
12
13
const testData = generateTestData ( 100 ) ;
13
14
14
- const textBasedThresholdMs = 100 ;
15
- const parseTreeThresholdMs = 500 ;
16
- const surroundingPairThresholdMs = 500 ;
15
+ const smallThresholdMs = 100 ;
16
+ const largeThresholdMs = 500 ;
17
+
18
+ type ModifierType = "containing" | "previous" | "every" ;
17
19
18
20
suite ( "Performance" , async function ( ) {
19
21
endToEndTestSetup ( this ) ;
@@ -32,42 +34,56 @@ suite("Performance", async function () {
32
34
33
35
test (
34
36
"Remove token" ,
35
- asyncSafety ( ( ) => removeToken ( textBasedThresholdMs ) ) ,
37
+ asyncSafety ( ( ) => removeToken ( smallThresholdMs ) ) ,
36
38
) ;
37
39
38
- const fixtures : [ SimpleScopeTypeType | ScopeType , number ] [ ] = [
40
+ const fixtures : (
41
+ | [ SimpleScopeTypeType | ScopeType , number ]
42
+ | [ SimpleScopeTypeType | ScopeType , number , ModifierType ]
43
+ ) [ ] = [
39
44
// Text based
40
- [ "character" , textBasedThresholdMs ] ,
41
- [ "word" , textBasedThresholdMs ] ,
42
- [ "token" , textBasedThresholdMs ] ,
43
- [ "identifier" , textBasedThresholdMs ] ,
44
- [ "line" , textBasedThresholdMs ] ,
45
- [ "sentence" , textBasedThresholdMs ] ,
46
- [ "paragraph" , textBasedThresholdMs ] ,
47
- [ "document" , textBasedThresholdMs ] ,
48
- [ "nonWhitespaceSequence" , textBasedThresholdMs ] ,
49
- // Parse tree based
50
- [ "string" , parseTreeThresholdMs ] ,
51
- [ "map" , parseTreeThresholdMs ] ,
52
- [ "collectionKey" , parseTreeThresholdMs ] ,
53
- [ "value" , parseTreeThresholdMs ] ,
45
+ [ "character" , smallThresholdMs ] ,
46
+ [ "word" , smallThresholdMs ] ,
47
+ [ "token" , smallThresholdMs ] ,
48
+ [ "identifier" , smallThresholdMs ] ,
49
+ [ "line" , smallThresholdMs ] ,
50
+ [ "sentence" , smallThresholdMs ] ,
51
+ [ "paragraph" , smallThresholdMs ] ,
52
+ [ "document" , smallThresholdMs ] ,
53
+ [ "nonWhitespaceSequence" , smallThresholdMs ] ,
54
+ // Parse tree based, containing/every scope
55
+ [ "string" , smallThresholdMs ] ,
56
+ [ "map" , smallThresholdMs ] ,
57
+ [ "collectionKey" , smallThresholdMs ] ,
58
+ [ "value" , smallThresholdMs ] ,
59
+ [ "collectionKey" , smallThresholdMs , "every" ] ,
60
+ [ "value" , smallThresholdMs , "every" ] ,
61
+ // Parse tree based, relative scope
62
+ [ "collectionKey" , largeThresholdMs , "previous" ] ,
63
+ [ "value" , largeThresholdMs , "previous" ] ,
54
64
// Text based, but utilizes surrounding pair
55
- [ "boundedParagraph" , surroundingPairThresholdMs ] ,
56
- [ "boundedNonWhitespaceSequence" , surroundingPairThresholdMs ] ,
57
- [ "collectionItem" , surroundingPairThresholdMs ] ,
65
+ [ "boundedParagraph" , largeThresholdMs ] ,
66
+ [ "boundedNonWhitespaceSequence" , largeThresholdMs ] ,
67
+ [ "collectionItem" , largeThresholdMs ] ,
58
68
// Surrounding pair
59
- [ { type : "surroundingPair" , delimiter : "any" } , surroundingPairThresholdMs ] ,
69
+ [ { type : "surroundingPair" , delimiter : "any" } , largeThresholdMs ] ,
70
+ [ { type : "surroundingPair" , delimiter : "curlyBrackets" } , largeThresholdMs ] ,
71
+ [ { type : "surroundingPair" , delimiter : "any" } , largeThresholdMs , "every" ] ,
60
72
[
61
- { type : "surroundingPair" , delimiter : "curlyBrackets" } ,
62
- surroundingPairThresholdMs ,
73
+ { type : "surroundingPair" , delimiter : "any" } ,
74
+ largeThresholdMs ,
75
+ "previous" ,
63
76
] ,
64
77
] ;
65
78
66
- for ( const [ scope , threshold ] of fixtures ) {
67
- const [ scopeType , title ] = getScopeTypeAndTitle ( scope ) ;
79
+ for ( const [ scope , threshold , modifierType ] of fixtures ) {
80
+ const [ scopeType , scopeTitle ] = getScopeTypeAndTitle ( scope ) ;
81
+ const title = modifierType
82
+ ? `${ modifierType } ${ scopeTitle } `
83
+ : `${ scopeTitle } ` ;
68
84
test (
69
85
`Select ${ title } ` ,
70
- asyncSafety ( ( ) => selectScopeType ( scopeType , threshold ) ) ,
86
+ asyncSafety ( ( ) => selectScopeType ( scopeType , threshold , modifierType ) ) ,
71
87
) ;
72
88
}
73
89
} ) ;
@@ -82,16 +98,40 @@ async function removeToken(thresholdMs: number) {
82
98
} ) ;
83
99
}
84
100
85
- async function selectScopeType ( scopeType : ScopeType , thresholdMs : number ) {
101
+ async function selectScopeType (
102
+ scopeType : ScopeType ,
103
+ thresholdMs : number ,
104
+ modifierType ?: ModifierType ,
105
+ ) {
86
106
await testPerformance ( thresholdMs , {
87
107
name : "setSelection" ,
88
108
target : {
89
109
type : "primitive" ,
90
- modifiers : [ { type : "containingScope" , scopeType } ] ,
110
+ modifiers : [ getModifier ( scopeType , modifierType ) ] ,
91
111
} ,
92
112
} ) ;
93
113
}
94
114
115
+ function getModifier (
116
+ scopeType : ScopeType ,
117
+ modifierType : ModifierType = "containing" ,
118
+ ) : Modifier {
119
+ switch ( modifierType ) {
120
+ case "containing" :
121
+ return { type : "containingScope" , scopeType } ;
122
+ case "every" :
123
+ return { type : "everyScope" , scopeType } ;
124
+ case "previous" :
125
+ return {
126
+ type : "relativeScope" ,
127
+ direction : "backward" ,
128
+ offset : 1 ,
129
+ length : 1 ,
130
+ scopeType,
131
+ } ;
132
+ }
133
+ }
134
+
95
135
async function testPerformance ( thresholdMs : number , action : ActionDescriptor ) {
96
136
const editor = await openNewEditor ( testData , { languageId : "json" } ) ;
97
137
// This is the position of the last json key in the document
0 commit comments