Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
0671cb3e
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
0671cb3e
编写于
9月 21, 2021
作者:
H
Henning Dieterichs
提交者:
GitHub
9月 21, 2021
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #131789 from microsoft/hediet/bracket-pair-colorizer-improvements
bracket pair colorizer improvements
上级
20048d6d
e8807a25
变更
7
展开全部
隐藏空白更改
内联
并排
Showing
7 changed file
with
667 addition
and
347 deletion
+667
-347
src/vs/editor/common/model/bracketPairColorizer/ast.ts
src/vs/editor/common/model/bracketPairColorizer/ast.ts
+427
-259
src/vs/editor/common/model/bracketPairColorizer/bracketPairColorizer.ts
...common/model/bracketPairColorizer/bracketPairColorizer.ts
+41
-15
src/vs/editor/common/model/bracketPairColorizer/concat23Trees.ts
...editor/common/model/bracketPairColorizer/concat23Trees.ts
+145
-43
src/vs/editor/common/model/bracketPairColorizer/length.ts
src/vs/editor/common/model/bracketPairColorizer/length.ts
+1
-1
src/vs/editor/common/model/bracketPairColorizer/nodeReader.ts
...vs/editor/common/model/bracketPairColorizer/nodeReader.ts
+24
-12
src/vs/editor/common/model/bracketPairColorizer/parser.ts
src/vs/editor/common/model/bracketPairColorizer/parser.ts
+18
-6
src/vs/editor/test/common/model/bracketPairColorizer/concat23Trees.test.ts
...t/common/model/bracketPairColorizer/concat23Trees.test.ts
+11
-11
未找到文件。
src/vs/editor/common/model/bracketPairColorizer/ast.ts
浏览文件 @
0671cb3e
此差异已折叠。
点击以展开。
src/vs/editor/common/model/bracketPairColorizer/bracketPairColorizer.ts
浏览文件 @
0671cb3e
...
...
@@ -149,7 +149,7 @@ class BracketPairColorizerImpl extends Disposable implements DecorationProvider
toLength
(
r
.
toLineNumber
-
r
.
fromLineNumber
+
1
,
0
)
)
);
this
.
astWithTokens
=
this
.
parseDocumentFromTextBuffer
(
edits
,
this
.
astWithTokens
);
this
.
astWithTokens
=
this
.
parseDocumentFromTextBuffer
(
edits
,
this
.
astWithTokens
,
false
);
if
(
!
this
.
initialAstWithoutTokens
)
{
this
.
didChangeDecorationsEmitter
.
fire
();
}
...
...
@@ -159,16 +159,16 @@ class BracketPairColorizerImpl extends Disposable implements DecorationProvider
// There are no token information yet
const
brackets
=
this
.
brackets
.
getSingleLanguageBracketTokens
(
this
.
textModel
.
getLanguageIdentifier
().
id
);
const
tokenizer
=
new
FastTokenizer
(
this
.
textModel
.
getValue
(),
brackets
);
this
.
initialAstWithoutTokens
=
parseDocument
(
tokenizer
,
[],
undefined
);
this
.
astWithTokens
=
this
.
initialAstWithoutTokens
.
clone
()
;
this
.
initialAstWithoutTokens
=
parseDocument
(
tokenizer
,
[],
undefined
,
true
);
this
.
astWithTokens
=
this
.
initialAstWithoutTokens
;
}
else
if
(
textModel
.
backgroundTokenizationState
===
BackgroundTokenizationState
.
Completed
)
{
// Skip the initial ast, as there is no flickering.
// Directly create the tree with token information.
this
.
initialAstWithoutTokens
=
undefined
;
this
.
astWithTokens
=
this
.
parseDocumentFromTextBuffer
([],
undefined
);
this
.
astWithTokens
=
this
.
parseDocumentFromTextBuffer
([],
undefined
,
false
);
}
else
if
(
textModel
.
backgroundTokenizationState
===
BackgroundTokenizationState
.
InProgress
)
{
this
.
initialAstWithoutTokens
=
this
.
parseDocumentFromTextBuffer
([],
undefined
);
this
.
astWithTokens
=
this
.
initialAstWithoutTokens
.
clone
()
;
this
.
initialAstWithoutTokens
=
this
.
parseDocumentFromTextBuffer
([],
undefined
,
true
);
this
.
astWithTokens
=
this
.
initialAstWithoutTokens
;
}
}
...
...
@@ -182,21 +182,21 @@ class BracketPairColorizerImpl extends Disposable implements DecorationProvider
);
}).
reverse
();
this
.
astWithTokens
=
this
.
parseDocumentFromTextBuffer
(
edits
,
this
.
astWithTokens
);
this
.
astWithTokens
=
this
.
parseDocumentFromTextBuffer
(
edits
,
this
.
astWithTokens
,
false
);
if
(
this
.
initialAstWithoutTokens
)
{
this
.
initialAstWithoutTokens
=
this
.
parseDocumentFromTextBuffer
(
edits
,
this
.
initialAstWithoutTokens
);
this
.
initialAstWithoutTokens
=
this
.
parseDocumentFromTextBuffer
(
edits
,
this
.
initialAstWithoutTokens
,
false
);
}
}
/**
* @pure (only if isPure = true)
*/
private
parseDocumentFromTextBuffer
(
edits
:
TextEditInfo
[],
previousAst
:
AstNode
|
undefined
):
AstNode
{
private
parseDocumentFromTextBuffer
(
edits
:
TextEditInfo
[],
previousAst
:
AstNode
|
undefined
,
immutable
:
boolean
):
AstNode
{
// Is much faster if `isPure = false`.
const
isPure
=
false
;
const
previousAstClone
=
isPure
?
previousAst
?.
c
lone
()
:
previousAst
;
const
previousAstClone
=
isPure
?
previousAst
?.
deepC
lone
()
:
previousAst
;
const
tokenizer
=
new
TextBufferTokenizer
(
this
.
textModel
,
this
.
brackets
);
const
result
=
parseDocument
(
tokenizer
,
edits
,
previousAstClone
);
const
result
=
parseDocument
(
tokenizer
,
edits
,
previousAstClone
,
immutable
);
return
result
;
}
...
...
@@ -236,10 +236,7 @@ function collectBrackets(node: AstNode, nodeOffsetStart: Length, nodeOffsetEnd:
}
else
if
(
node
.
kind
===
AstNodeKind
.
UnexpectedClosingBracket
)
{
const
range
=
lengthsToRange
(
nodeOffsetStart
,
nodeOffsetEnd
);
result
.
push
(
new
BracketInfo
(
range
,
level
-
1
,
true
));
}
else
{
if
(
node
.
kind
===
AstNodeKind
.
Pair
)
{
level
++
;
}
}
else
if
(
node
.
kind
===
AstNodeKind
.
List
)
{
for
(
const
child
of
node
.
children
)
{
nodeOffsetEnd
=
lengthAdd
(
nodeOffsetStart
,
child
.
length
);
if
(
lengthLessThanEqual
(
nodeOffsetStart
,
endOffset
)
&&
lengthGreaterThanEqual
(
nodeOffsetEnd
,
startOffset
))
{
...
...
@@ -247,6 +244,35 @@ function collectBrackets(node: AstNode, nodeOffsetStart: Length, nodeOffsetEnd:
}
nodeOffsetStart
=
nodeOffsetEnd
;
}
}
else
if
(
node
.
kind
===
AstNodeKind
.
Pair
)
{
// Don't use node.children here to improve performance
level
++
;
{
const
child
=
node
.
openingBracket
;
nodeOffsetEnd
=
lengthAdd
(
nodeOffsetStart
,
child
.
length
);
if
(
lengthLessThanEqual
(
nodeOffsetStart
,
endOffset
)
&&
lengthGreaterThanEqual
(
nodeOffsetEnd
,
startOffset
))
{
collectBrackets
(
child
,
nodeOffsetStart
,
nodeOffsetEnd
,
startOffset
,
endOffset
,
result
,
level
);
}
nodeOffsetStart
=
nodeOffsetEnd
;
}
if
(
node
.
child
)
{
const
child
=
node
.
child
;
nodeOffsetEnd
=
lengthAdd
(
nodeOffsetStart
,
child
.
length
);
if
(
lengthLessThanEqual
(
nodeOffsetStart
,
endOffset
)
&&
lengthGreaterThanEqual
(
nodeOffsetEnd
,
startOffset
))
{
collectBrackets
(
child
,
nodeOffsetStart
,
nodeOffsetEnd
,
startOffset
,
endOffset
,
result
,
level
);
}
nodeOffsetStart
=
nodeOffsetEnd
;
}
if
(
node
.
closingBracket
)
{
const
child
=
node
.
closingBracket
;
nodeOffsetEnd
=
lengthAdd
(
nodeOffsetStart
,
child
.
length
);
if
(
lengthLessThanEqual
(
nodeOffsetStart
,
endOffset
)
&&
lengthGreaterThanEqual
(
nodeOffsetEnd
,
startOffset
))
{
collectBrackets
(
child
,
nodeOffsetStart
,
nodeOffsetEnd
,
startOffset
,
endOffset
,
result
,
level
);
}
nodeOffsetStart
=
nodeOffsetEnd
;
}
}
}
...
...
src/vs/editor/common/model/bracketPairColorizer/concat23Trees.ts
浏览文件 @
0671cb3e
...
...
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import
{
AstNode
,
ListAstNode
}
from
'
./ast
'
;
import
{
AstNode
,
AstNodeKind
,
ListAstNode
}
from
'
./ast
'
;
/**
* Concatenates a list of (2,3) AstNode's into a single (2,3) AstNode.
...
...
@@ -19,76 +19,178 @@ export function concat23Trees(items: AstNode[]): AstNode | null {
return
items
[
0
];
}
if
(
allItemsHaveSameHeight
(
items
))
{
return
concatFast
(
items
);
let
i
=
0
;
/**
* Reads nodes of same height and concatenates them to a single node.
*/
function
readNode
():
AstNode
|
null
{
if
(
i
>=
items
.
length
)
{
return
null
;
}
const
start
=
i
;
const
height
=
items
[
start
].
listHeight
;
i
++
;
while
(
i
<
items
.
length
&&
items
[
i
].
listHeight
===
height
)
{
i
++
;
}
if
(
i
-
start
>=
2
)
{
return
concat23TreesOfSameHeight
(
start
===
0
&&
i
===
items
.
length
?
items
:
items
.
slice
(
start
,
i
),
false
);
}
else
{
return
items
[
start
];
}
}
return
concatSlow
(
items
);
}
/**
* @param items must be non empty.
*/
function
allItemsHaveSameHeight
(
items
:
AstNode
[]):
boolean
{
const
firstHeight
=
items
[
0
].
listHeight
;
// The items might not have the same height.
// We merge all items by using a binary concat operator.
let
first
=
readNode
()
!
;
// There must be a first item
let
second
=
readNode
();
if
(
!
second
)
{
return
first
;
}
for
(
const
item
of
items
)
{
if
(
item
.
listHeight
!==
firstHeight
)
{
return
false
;
for
(
let
item
=
readNode
();
item
;
item
=
readNode
())
{
// Prefer concatenating smaller trees, as the runtime of concat depends on the tree height.
if
(
heightDiff
(
first
,
second
)
<=
heightDiff
(
second
,
item
))
{
first
=
concat
(
first
,
second
);
second
=
item
;
}
else
{
second
=
concat
(
second
,
item
);
}
}
return
true
;
const
result
=
concat
(
first
,
second
);
return
result
;
}
function
concatFast
(
items
:
AstNode
[]):
AstNode
|
null
{
export
function
concat23TreesOfSameHeight
(
items
:
AstNode
[],
createImmutableLists
:
boolean
=
false
):
AstNode
|
null
{
if
(
items
.
length
===
0
)
{
return
null
;
}
if
(
items
.
length
===
1
)
{
return
items
[
0
];
}
let
length
=
items
.
length
;
// All trees have same height, just create parent nodes.
while
(
length
>
1
)
{
while
(
length
>
3
)
{
const
newLength
=
length
>>
1
;
// Ideally, due to the slice, not a lot of memory is wasted.
const
newItems
=
new
Array
<
AstNode
>
(
newLength
);
for
(
let
i
=
0
;
i
<
newLength
;
i
++
)
{
const
j
=
i
<<
1
;
newItems
[
i
]
=
ListAstNode
.
create
(
items
.
slice
(
j
,
(
j
+
3
===
length
)
?
length
:
j
+
2
)
);
items
[
i
]
=
ListAstNode
.
create23
(
items
[
j
],
items
[
j
+
1
],
j
+
3
===
length
?
items
[
j
+
2
]
:
null
,
createImmutableLists
);
}
length
=
newLength
;
items
=
newItems
;
}
return
items
[
0
]
;
return
ListAstNode
.
create23
(
items
[
0
],
items
[
1
],
length
>=
3
?
items
[
2
]
:
null
,
createImmutableLists
)
;
}
function
heightDiff
(
node1
:
AstNode
,
node2
:
AstNode
):
number
{
return
Math
.
abs
(
node1
.
listHeight
-
node2
.
listHeight
);
}
function
concatSlow
(
items
:
AstNode
[]):
AstNode
|
null
{
// The items might not have the same height.
// We merge all items by using a binary concat operator.
let
first
=
items
[
0
];
let
second
=
items
[
1
];
function
concat
(
node1
:
AstNode
,
node2
:
AstNode
):
AstNode
{
if
(
node1
.
listHeight
===
node2
.
listHeight
)
{
return
ListAstNode
.
create23
(
node1
,
node2
,
null
,
false
);
}
else
if
(
node1
.
listHeight
>
node2
.
listHeight
)
{
// node1 is the tree we want to insert into
return
append
(
node1
as
ListAstNode
,
node2
);
}
else
{
return
prepend
(
node2
as
ListAstNode
,
node1
);
}
}
for
(
let
i
=
2
;
i
<
items
.
length
;
i
++
)
{
const
item
=
items
[
i
];
// Prefer concatenating smaller trees, as the runtime of concat depends on the tree height.
if
(
heightDiff
(
first
,
second
)
<=
heightDiff
(
second
,
item
))
{
first
=
concat
(
first
,
second
);
second
=
item
;
}
else
{
second
=
concat
(
second
,
item
);
/**
* Appends the given node to the end of this (2,3) tree.
* Returns the new root.
*/
function
append
(
list
:
ListAstNode
,
nodeToAppend
:
AstNode
):
AstNode
{
list
=
list
.
toMutable
()
as
ListAstNode
;
let
curNode
:
AstNode
=
list
;
const
parents
=
new
Array
<
ListAstNode
>
();
let
nodeToAppendOfCorrectHeight
:
AstNode
|
undefined
;
while
(
true
)
{
// assert nodeToInsert.listHeight <= curNode.listHeight
if
(
nodeToAppend
.
listHeight
===
curNode
.
listHeight
)
{
nodeToAppendOfCorrectHeight
=
nodeToAppend
;
break
;
}
// assert 0 <= nodeToInsert.listHeight < curNode.listHeight
if
(
curNode
.
kind
!==
AstNodeKind
.
List
)
{
throw
new
Error
(
'
unexpected
'
);
}
parents
.
push
(
curNode
);
// assert 2 <= curNode.childrenLength <= 3
curNode
=
curNode
.
makeLastElementMutable
()
!
;
}
// assert nodeToAppendOfCorrectHeight!.listHeight === curNode.listHeight
for
(
let
i
=
parents
.
length
-
1
;
i
>=
0
;
i
--
)
{
const
parent
=
parents
[
i
];
if
(
nodeToAppendOfCorrectHeight
)
{
// Can we take the element?
if
(
parent
.
childrenLength
>=
3
)
{
// assert parent.childrenLength === 3 && parent.listHeight === nodeToAppendOfCorrectHeight.listHeight + 1
const
result
=
concat
(
first
,
second
);
return
result
;
// we need to split to maintain (2,3)-tree property.
// Send the third element + the new element to the parent.
nodeToAppendOfCorrectHeight
=
ListAstNode
.
create23
(
parent
.
unappendChild
()
!
,
nodeToAppendOfCorrectHeight
,
null
,
false
);
}
else
{
parent
.
appendChildOfSameHeight
(
nodeToAppendOfCorrectHeight
);
nodeToAppendOfCorrectHeight
=
undefined
;
}
}
else
{
parent
.
handleChildrenChanged
();
}
}
if
(
nodeToAppendOfCorrectHeight
)
{
return
ListAstNode
.
create23
(
list
,
nodeToAppendOfCorrectHeight
,
null
,
false
);
}
else
{
return
list
;
}
}
function
concat
(
node1
:
AstNode
,
node2
:
AstNode
):
AstNode
{
if
(
node1
.
listHeight
===
node2
.
listHeight
)
{
return
ListAstNode
.
create
([
node1
,
node2
]);
/**
* Prepends the given node to the end of this (2,3) tree.
* Returns the new root.
*/
function
prepend
(
list
:
ListAstNode
,
nodeToAppend
:
AstNode
):
AstNode
{
list
=
list
.
toMutable
()
as
ListAstNode
;
let
curNode
:
AstNode
=
list
;
const
parents
=
new
Array
<
ListAstNode
>
();
// assert nodeToInsert.listHeight <= curNode.listHeight
while
(
nodeToAppend
.
listHeight
!==
curNode
.
listHeight
)
{
// assert 0 <= nodeToInsert.listHeight < curNode.listHeight
if
(
curNode
.
kind
!==
AstNodeKind
.
List
)
{
throw
new
Error
(
'
unexpected
'
);
}
parents
.
push
(
curNode
);
// assert 2 <= curNode.childrenFast.length <= 3
curNode
=
curNode
.
makeFirstElementMutable
()
!
;
}
else
if
(
node1
.
listHeight
>
node2
.
listHeight
)
{
// node1 is the tree we want to insert into
return
(
node1
as
ListAstNode
).
append
(
node2
);
let
nodeToPrependOfCorrectHeight
:
AstNode
|
undefined
=
nodeToAppend
;
// assert nodeToAppendOfCorrectHeight!.listHeight === curNode.listHeight
for
(
let
i
=
parents
.
length
-
1
;
i
>=
0
;
i
--
)
{
const
parent
=
parents
[
i
];
if
(
nodeToPrependOfCorrectHeight
)
{
// Can we take the element?
if
(
parent
.
childrenLength
>=
3
)
{
// assert parent.childrenLength === 3 && parent.listHeight === nodeToAppendOfCorrectHeight.listHeight + 1
// we need to split to maintain (2,3)-tree property.
// Send the third element + the new element to the parent.
nodeToPrependOfCorrectHeight
=
ListAstNode
.
create23
(
nodeToPrependOfCorrectHeight
,
parent
.
unprependChild
()
!
,
null
,
false
);
}
else
{
parent
.
prependChildOfSameHeight
(
nodeToPrependOfCorrectHeight
);
nodeToPrependOfCorrectHeight
=
undefined
;
}
}
else
{
parent
.
handleChildrenChanged
();
}
}
if
(
nodeToPrependOfCorrectHeight
)
{
return
ListAstNode
.
create23
(
nodeToPrependOfCorrectHeight
,
list
,
null
,
false
);
}
else
{
return
(
node2
as
ListAstNode
).
prepend
(
node1
)
;
return
list
;
}
}
src/vs/editor/common/model/bracketPairColorizer/length.ts
浏览文件 @
0671cb3e
...
...
@@ -9,7 +9,7 @@ import { Range } from 'vs/editor/common/core/range';
/**
* Represents a non-negative length in terms of line and column count.
* Prefer using {@link Length}.
* Prefer using {@link Length}
for performance reasons
.
*/
export
class
LengthObj
{
public
static
zero
=
new
LengthObj
(
0
,
0
);
...
...
src/vs/editor/common/model/bracketPairColorizer/nodeReader.ts
浏览文件 @
0671cb3e
...
...
@@ -24,7 +24,6 @@ export class NodeReader {
/**
* Returns the longest node at `offset` that satisfies the predicate.
* Has runtime O(log n) where n is the number of nodes in the tree.
* @param offset must be greater than or equal to the last offset this method has been called with!
*/
readLongestNodeAt
(
offset
:
Length
,
predicate
:
(
node
:
AstNode
)
=>
boolean
):
AstNode
|
undefined
{
...
...
@@ -55,11 +54,12 @@ export class NodeReader {
this
.
nextNodeAfterCurrent
();
}
else
{
// The reader is somewhere in the current node.
if
(
curNode
.
children
.
length
>
0
)
{
const
nextChildIdx
=
getNextChildIdx
(
curNode
);
if
(
nextChildIdx
!==
-
1
)
{
// Go to the first child and repeat.
this
.
nextNodes
.
push
(
curNode
.
children
[
0
]
);
this
.
nextNodes
.
push
(
curNode
.
getChild
(
nextChildIdx
)
!
);
this
.
offsets
.
push
(
curNodeOffset
);
this
.
idxs
.
push
(
0
);
this
.
idxs
.
push
(
nextChildIdx
);
}
else
{
// We don't have children
this
.
nextNodeAfterCurrent
();
...
...
@@ -71,16 +71,17 @@ export class NodeReader {
this
.
nextNodeAfterCurrent
();
return
curNode
;
}
else
{
const
nextChildIdx
=
getNextChildIdx
(
curNode
);
// look for shorter node
if
(
curNode
.
children
.
length
===
0
)
{
if
(
nextChildIdx
===
-
1
)
{
// There is no shorter node.
this
.
nextNodeAfterCurrent
();
return
undefined
;
}
else
{
// Descend into first child & repeat.
this
.
nextNodes
.
push
(
curNode
.
children
[
0
]
);
this
.
nextNodes
.
push
(
curNode
.
getChild
(
nextChildIdx
)
!
);
this
.
offsets
.
push
(
curNodeOffset
);
this
.
idxs
.
push
(
0
);
this
.
idxs
.
push
(
nextChildIdx
);
}
}
}
...
...
@@ -102,13 +103,12 @@ export class NodeReader {
// Parent is not undefined, because idxs is not empty
const
parent
=
lastOrUndefined
(
this
.
nextNodes
)
!
;
const
nextChildIdx
=
getNextChildIdx
(
parent
,
this
.
idxs
[
this
.
idxs
.
length
-
1
]);
this
.
idxs
[
this
.
idxs
.
length
-
1
]
++
;
const
parentIdx
=
this
.
idxs
[
this
.
idxs
.
length
-
1
];
if
(
parentIdx
<
parent
.
children
.
length
)
{
this
.
nextNodes
.
push
(
parent
.
children
[
parentIdx
]);
if
(
nextChildIdx
!==
-
1
)
{
this
.
nextNodes
.
push
(
parent
.
getChild
(
nextChildIdx
)
!
);
this
.
offsets
.
push
(
lengthAdd
(
currentOffset
!
,
currentNode
!
.
length
));
this
.
idxs
[
this
.
idxs
.
length
-
1
]
=
nextChildIdx
;
break
;
}
else
{
this
.
idxs
.
pop
();
...
...
@@ -119,6 +119,18 @@ export class NodeReader {
}
}
function
getNextChildIdx
(
node
:
AstNode
,
curIdx
:
number
=
-
1
):
number
|
-
1
{
while
(
true
)
{
curIdx
++
;
if
(
curIdx
>=
node
.
childrenLength
)
{
return
-
1
;
}
if
(
node
.
getChild
(
curIdx
))
{
return
curIdx
;
}
}
}
function
lastOrUndefined
<
T
>
(
arr
:
readonly
T
[]):
T
|
undefined
{
return
arr
.
length
>
0
?
arr
[
arr
.
length
-
1
]
:
undefined
;
}
src/vs/editor/common/model/bracketPairColorizer/parser.ts
浏览文件 @
0671cb3e
...
...
@@ -7,15 +7,21 @@ import { AstNode, AstNodeKind, BracketAstNode, InvalidBracketAstNode, ListAstNod
import
{
BeforeEditPositionMapper
,
TextEditInfo
}
from
'
./beforeEditPositionMapper
'
;
import
{
SmallImmutableSet
}
from
'
./smallImmutableSet
'
;
import
{
lengthGetLineCount
,
lengthIsZero
,
lengthLessThanEqual
}
from
'
./length
'
;
import
{
concat23Trees
}
from
'
./concat23Trees
'
;
import
{
concat23Trees
,
concat23TreesOfSameHeight
}
from
'
./concat23Trees
'
;
import
{
NodeReader
}
from
'
./nodeReader
'
;
import
{
OpeningBracketId
,
Tokenizer
,
TokenKind
}
from
'
./tokenizer
'
;
export
function
parseDocument
(
tokenizer
:
Tokenizer
,
edits
:
TextEditInfo
[],
oldNode
:
AstNode
|
undefined
):
AstNode
{
const
parser
=
new
Parser
(
tokenizer
,
edits
,
oldNode
);
/**
* Non incrementally built ASTs are immutable.
*/
export
function
parseDocument
(
tokenizer
:
Tokenizer
,
edits
:
TextEditInfo
[],
oldNode
:
AstNode
|
undefined
,
createImmutableLists
:
boolean
):
AstNode
{
const
parser
=
new
Parser
(
tokenizer
,
edits
,
oldNode
,
createImmutableLists
);
return
parser
.
parseDocument
();
}
/**
* Non incrementally built ASTs are immutable.
*/
class
Parser
{
private
readonly
oldNodeReader
?:
NodeReader
;
private
readonly
positionMapper
:
BeforeEditPositionMapper
;
...
...
@@ -40,7 +46,12 @@ class Parser {
private
readonly
tokenizer
:
Tokenizer
,
edits
:
TextEditInfo
[],
oldNode
:
AstNode
|
undefined
,
private
readonly
createImmutableLists
:
boolean
,
)
{
if
(
oldNode
&&
createImmutableLists
)
{
throw
new
Error
(
'
Not supported
'
);
}
this
.
oldNodeReader
=
oldNode
?
new
NodeReader
(
oldNode
)
:
undefined
;
this
.
positionMapper
=
new
BeforeEditPositionMapper
(
edits
,
tokenizer
.
length
);
}
...
...
@@ -51,7 +62,7 @@ class Parser {
let
result
=
this
.
parseList
(
SmallImmutableSet
.
getEmpty
());
if
(
!
result
)
{
result
=
ListAstNode
.
create
([]
);
result
=
ListAstNode
.
getEmpty
(
);
}
return
result
;
...
...
@@ -73,14 +84,15 @@ class Parser {
}
const
child
=
this
.
parseChild
(
openedBracketIds
);
if
(
child
.
kind
===
AstNodeKind
.
List
&&
child
.
children
.
l
ength
===
0
)
{
if
(
child
.
kind
===
AstNodeKind
.
List
&&
child
.
children
L
ength
===
0
)
{
continue
;
}
items
.
push
(
child
);
}
const
result
=
concat23Trees
(
items
);
// When there is no oldNodeReader, all items are created from scratch and must have the same height.
const
result
=
this
.
oldNodeReader
?
concat23Trees
(
items
)
:
concat23TreesOfSameHeight
(
items
,
this
.
createImmutableLists
);
return
result
;
}
...
...
src/vs/editor/test/common/model/bracketPairColorizer/concat23Trees.test.ts
浏览文件 @
0671cb3e
...
...
@@ -15,7 +15,7 @@ suite('Bracket Pair Colorizer - mergeItems', () => {
new
TextAstNode
(
toLength
(
1
,
1
)),
]);
assert
.
ok
(
equals
(
tree
,
tree
.
c
lone
()));
assert
.
ok
(
equals
(
tree
,
tree
.
deepC
lone
()));
});
function
equals
(
node1
:
AstNode
,
node2
:
AstNode
):
boolean
{
...
...
@@ -33,7 +33,7 @@ suite('Bracket Pair Colorizer - mergeItems', () => {
}
}
if
(
!
node1
.
missing
BracketIds
.
equals
(
node2
.
miss
ingBracketIds
))
{
if
(
!
node1
.
missing
OpeningBracketIds
.
equals
(
node2
.
missingOpen
ingBracketIds
))
{
return
false
;
}
...
...
@@ -47,7 +47,7 @@ suite('Bracket Pair Colorizer - mergeItems', () => {
}
function
testMerge
(
lists
:
AstNode
[])
{
const
node
=
(
concat23Trees
(
lists
.
map
(
l
=>
l
.
c
lone
()))
||
ListAstNode
.
create
([])).
flattenLists
();
const
node
=
(
concat23Trees
(
lists
.
map
(
l
=>
l
.
deepC
lone
()))
||
ListAstNode
.
create
([])).
flattenLists
();
// This trivial merge does not maintain the (2,3) tree invariant.
const
referenceNode
=
ListAstNode
.
create
(
lists
).
flattenLists
();
...
...
@@ -60,30 +60,30 @@ suite('Bracket Pair Colorizer - mergeItems', () => {
test
(
'
Same Height Lists
'
,
()
=>
{
const
textNode
=
new
TextAstNode
(
toLength
(
1
,
1
));
const
tree
=
ListAstNode
.
create
([
textNode
.
clone
(),
textNode
.
c
lone
()]);
testMerge
([
tree
.
clone
(),
tree
.
clone
(),
tree
.
clone
(),
tree
.
clone
(),
tree
.
c
lone
()]);
const
tree
=
ListAstNode
.
create
([
textNode
.
deepClone
(),
textNode
.
deepC
lone
()]);
testMerge
([
tree
.
deepClone
(),
tree
.
deepClone
(),
tree
.
deepClone
(),
tree
.
deepClone
(),
tree
.
deepC
lone
()]);
});
test
(
'
Different Height Lists 1
'
,
()
=>
{
const
textNode
=
new
TextAstNode
(
toLength
(
1
,
1
));
const
tree1
=
ListAstNode
.
create
([
textNode
.
clone
(),
textNode
.
c
lone
()]);
const
tree2
=
ListAstNode
.
create
([
tree1
.
clone
(),
tree1
.
c
lone
()]);
const
tree1
=
ListAstNode
.
create
([
textNode
.
deepClone
(),
textNode
.
deepC
lone
()]);
const
tree2
=
ListAstNode
.
create
([
tree1
.
deepClone
(),
tree1
.
deepC
lone
()]);
testMerge
([
tree1
,
tree2
]);
});
test
(
'
Different Height Lists 2
'
,
()
=>
{
const
textNode
=
new
TextAstNode
(
toLength
(
1
,
1
));
const
tree1
=
ListAstNode
.
create
([
textNode
.
clone
(),
textNode
.
c
lone
()]);
const
tree2
=
ListAstNode
.
create
([
tree1
.
clone
(),
tree1
.
c
lone
()]);
const
tree1
=
ListAstNode
.
create
([
textNode
.
deepClone
(),
textNode
.
deepC
lone
()]);
const
tree2
=
ListAstNode
.
create
([
tree1
.
deepClone
(),
tree1
.
deepC
lone
()]);
testMerge
([
tree2
,
tree1
]);
});
test
(
'
Different Height Lists 3
'
,
()
=>
{
const
textNode
=
new
TextAstNode
(
toLength
(
1
,
1
));
const
tree1
=
ListAstNode
.
create
([
textNode
.
clone
(),
textNode
.
c
lone
()]);
const
tree2
=
ListAstNode
.
create
([
tree1
.
clone
(),
tree1
.
c
lone
()]);
const
tree1
=
ListAstNode
.
create
([
textNode
.
deepClone
(),
textNode
.
deepC
lone
()]);
const
tree2
=
ListAstNode
.
create
([
tree1
.
deepClone
(),
tree1
.
deepC
lone
()]);
testMerge
([
tree2
,
tree1
,
tree1
,
tree2
,
tree2
]);
});
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录