Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
1d25a68c
V
vscode
项目概览
xxadev
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1d25a68c
编写于
1月 10, 2017
作者:
A
Alex Dima
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Introduce CharacterMapping that can transform char offsets to rendered view parts
上级
48c1c577
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
215 addition
and
201 deletion
+215
-201
src/vs/editor/browser/viewParts/lines/viewLine.ts
src/vs/editor/browser/viewParts/lines/viewLine.ts
+21
-33
src/vs/editor/common/core/arrays.ts
src/vs/editor/common/core/arrays.ts
+0
-43
src/vs/editor/common/core/lineParts.ts
src/vs/editor/common/core/lineParts.ts
+0
-5
src/vs/editor/common/core/viewLineToken.ts
src/vs/editor/common/core/viewLineToken.ts
+0
-10
src/vs/editor/common/viewLayout/viewLineParts.ts
src/vs/editor/common/viewLayout/viewLineParts.ts
+0
-50
src/vs/editor/common/viewLayout/viewLineRenderer.ts
src/vs/editor/common/viewLayout/viewLineRenderer.ts
+125
-19
src/vs/editor/test/common/viewLayout/viewLineParts.test.ts
src/vs/editor/test/common/viewLayout/viewLineParts.test.ts
+3
-2
src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts
...vs/editor/test/common/viewLayout/viewLineRenderer.test.ts
+66
-39
未找到文件。
src/vs/editor/browser/viewParts/lines/viewLine.ts
浏览文件 @
1d25a68c
...
...
@@ -7,15 +7,14 @@
import
*
as
browser
from
'
vs/base/browser/browser
'
;
import
{
FastDomNode
,
createFastDomNode
}
from
'
vs/base/browser/styleMutator
'
;
import
{
IConfigurationChangedEvent
}
from
'
vs/editor/common/editorCommon
'
;
import
{
createLineParts
,
getColumnOfLinePartOffset
}
from
'
vs/editor/common/viewLayout/viewLineParts
'
;
import
{
renderLine
,
RenderLineInput
,
RenderLineOutput
}
from
'
vs/editor/common/viewLayout/viewLineRenderer
'
;
import
{
createLineParts
}
from
'
vs/editor/common/viewLayout/viewLineParts
'
;
import
{
renderLine
,
RenderLineInput
,
RenderLineOutput
,
CharacterMapping
}
from
'
vs/editor/common/viewLayout/viewLineRenderer
'
;
import
{
ClassNames
}
from
'
vs/editor/browser/editorBrowser
'
;
import
{
IVisibleLineData
}
from
'
vs/editor/browser/view/viewLayer
'
;
import
{
RangeUtil
}
from
'
vs/editor/browser/viewParts/lines/rangeUtil
'
;
import
{
ViewContext
}
from
'
vs/editor/common/view/viewContext
'
;
import
{
HorizontalRange
}
from
'
vs/editor/common/view/renderingContext
'
;
import
{
InlineDecoration
}
from
'
vs/editor/common/viewModel/viewModel
'
;
import
{
LineParts
}
from
'
vs/editor/common/core/lineParts
'
;
export
class
ViewLine
implements
IVisibleLineData
{
...
...
@@ -175,8 +174,7 @@ class RenderedViewLine {
public
readonly
input
:
RenderLineInput
;
public
readonly
html
:
string
;
protected
readonly
_charOffsetInPart
:
number
[];
private
readonly
_lastRenderedPartIndex
:
number
;
protected
readonly
_characterMapping
:
CharacterMapping
;
private
readonly
_isWhitespaceOnly
:
boolean
;
private
_cachedWidth
:
number
;
...
...
@@ -189,8 +187,7 @@ class RenderedViewLine {
this
.
domNode
=
domNode
;
this
.
input
=
renderLineInput
;
this
.
html
=
renderLineOutput
.
output
;
this
.
_charOffsetInPart
=
renderLineOutput
.
charOffsetInPart
;
this
.
_lastRenderedPartIndex
=
renderLineOutput
.
lastRenderedPartIndex
;
this
.
_characterMapping
=
renderLineOutput
.
characterMapping
;
this
.
_isWhitespaceOnly
=
renderLineOutput
.
isWhitespaceOnly
;
this
.
_cachedWidth
=
-
1
;
...
...
@@ -291,18 +288,19 @@ class RenderedViewLine {
private
_actualReadPixelOffset
(
column
:
number
,
clientRectDeltaLeft
:
number
,
endNode
:
HTMLElement
):
number
{
if
(
this
.
_char
OffsetInPart
.
length
===
0
)
{
if
(
this
.
_char
acterMapping
.
length
===
0
)
{
// This line is empty
return
0
;
}
if
(
column
===
this
.
_char
OffsetInPart
.
length
&&
this
.
_isWhitespaceOnly
)
{
if
(
column
===
this
.
_char
acterMapping
.
length
&&
this
.
_isWhitespaceOnly
)
{
// This branch helps in the case of whitespace only lines which have a width set
return
this
.
getWidth
();
}
let
partIndex
=
findIndexInArrayWithMax
(
this
.
input
.
lineParts
,
column
-
1
,
this
.
_lastRenderedPartIndex
);
let
charOffsetInPart
=
this
.
_charOffsetInPart
[
column
-
1
];
let
partData
=
this
.
_characterMapping
.
charOffsetToPartData
(
column
-
1
);
let
partIndex
=
CharacterMapping
.
getPartIndex
(
partData
);
let
charOffsetInPart
=
CharacterMapping
.
getCharIndex
(
partData
);
let
r
=
RangeUtil
.
readHorizontalRanges
(
this
.
_getReadingTarget
(),
partIndex
,
charOffsetInPart
,
partIndex
,
charOffsetInPart
,
clientRectDeltaLeft
,
endNode
);
if
(
!
r
||
r
.
length
===
0
)
{
...
...
@@ -313,16 +311,19 @@ class RenderedViewLine {
private
_readRawVisibleRangesForRange
(
startColumn
:
number
,
endColumn
:
number
,
clientRectDeltaLeft
:
number
,
endNode
:
HTMLElement
):
HorizontalRange
[]
{
if
(
startColumn
===
1
&&
endColumn
===
this
.
_char
OffsetInPart
.
length
)
{
if
(
startColumn
===
1
&&
endColumn
===
this
.
_char
acterMapping
.
length
)
{
// This branch helps IE with bidi text & gives a performance boost to other browsers when reading visible ranges for an entire line
return
[
new
HorizontalRange
(
0
,
this
.
getWidth
())];
}
let
startPartIndex
=
findIndexInArrayWithMax
(
this
.
input
.
lineParts
,
startColumn
-
1
,
this
.
_lastRenderedPartIndex
);
let
startCharOffsetInPart
=
this
.
_charOffsetInPart
[
startColumn
-
1
];
let
endPartIndex
=
findIndexInArrayWithMax
(
this
.
input
.
lineParts
,
endColumn
-
1
,
this
.
_lastRenderedPartIndex
);
let
endCharOffsetInPart
=
this
.
_charOffsetInPart
[
endColumn
-
1
];
let
startPartData
=
this
.
_characterMapping
.
charOffsetToPartData
(
startColumn
-
1
);
let
startPartIndex
=
CharacterMapping
.
getPartIndex
(
startPartData
);
let
startCharOffsetInPart
=
CharacterMapping
.
getCharIndex
(
startPartData
);
let
endPartData
=
this
.
_characterMapping
.
charOffsetToPartData
(
endColumn
-
1
);
let
endPartIndex
=
CharacterMapping
.
getPartIndex
(
endPartData
);
let
endCharOffsetInPart
=
CharacterMapping
.
getCharIndex
(
endPartData
);
return
RangeUtil
.
readHorizontalRanges
(
this
.
_getReadingTarget
(),
startPartIndex
,
startCharOffsetInPart
,
endPartIndex
,
endCharOffsetInPart
,
clientRectDeltaLeft
,
endNode
);
}
...
...
@@ -338,17 +339,9 @@ class RenderedViewLine {
spanNode
=
<
HTMLElement
>
spanNode
.
previousSibling
;
spanIndex
++
;
}
let
lineParts
=
this
.
input
.
lineParts
.
parts
;
return
getColumnOfLinePartOffset
(
this
.
input
.
stopRenderingLineAfter
,
lineParts
,
this
.
input
.
lineParts
.
maxLineColumn
,
this
.
_charOffsetInPart
,
spanIndex
,
spanNodeTextContentLength
,
offset
);
let
charOffset
=
this
.
_characterMapping
.
partDataToCharOffset
(
spanIndex
,
spanNodeTextContentLength
,
offset
);
return
charOffset
+
1
;
}
}
...
...
@@ -356,7 +349,7 @@ class WebKitRenderedViewLine extends RenderedViewLine {
protected
_readVisibleRangesForRange
(
startColumn
:
number
,
endColumn
:
number
,
clientRectDeltaLeft
:
number
,
endNode
:
HTMLElement
):
HorizontalRange
[]
{
let
output
=
super
.
_readVisibleRangesForRange
(
startColumn
,
endColumn
,
clientRectDeltaLeft
,
endNode
);
if
(
!
output
||
output
.
length
===
0
||
startColumn
===
endColumn
||
(
startColumn
===
1
&&
endColumn
===
this
.
_char
OffsetInPart
.
length
))
{
if
(
!
output
||
output
.
length
===
0
||
startColumn
===
endColumn
||
(
startColumn
===
1
&&
endColumn
===
this
.
_char
acterMapping
.
length
))
{
return
output
;
}
...
...
@@ -383,11 +376,6 @@ class WebKitRenderedViewLine extends RenderedViewLine {
}
}
function
findIndexInArrayWithMax
(
lineParts
:
LineParts
,
desiredIndex
:
number
,
maxResult
:
number
):
number
{
let
r
=
lineParts
.
findIndexOfOffset
(
desiredIndex
);
return
r
<=
maxResult
?
r
:
maxResult
;
}
const
createRenderedLine
:
(
domNode
:
FastDomNode
,
renderLineInput
:
RenderLineInput
,
modelContainsRTL
:
boolean
,
renderLineOutput
:
RenderLineOutput
)
=>
RenderedViewLine
=
(
function
()
{
if
(
browser
.
isWebKit
)
{
return
createWebKitRenderedLine
;
...
...
src/vs/editor/common/core/arrays.ts
已删除
100644 → 0
浏览文件 @
48c1c577
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
export
namespace
Arrays
{
/**
* Given a sorted array of natural number segments, find the segment containing a natural number.
* For example, the segments [0, 5), [5, 9), [9, infinity) will be represented in the following manner:
* [{ startIndex: 0 }, { startIndex: 5 }, { startIndex: 9 }]
* Searching for 0, 1, 2, 3 or 4 will return 0.
* Searching for 5, 6, 7 or 8 will return 1.
* Searching for 9, 10, 11, ... will return 2.
* @param arr A sorted array representing natural number segments
* @param desiredIndex The search
* @return The index of the containing segment in the array.
*/
export
function
findIndexInSegmentsArray
(
arr
:
{
readonly
startIndex
:
number
;
}[],
desiredIndex
:
number
):
number
{
let
low
=
0
;
let
high
=
arr
.
length
-
1
;
if
(
high
<=
0
)
{
return
0
;
}
while
(
low
<
high
)
{
let
mid
=
low
+
Math
.
ceil
((
high
-
low
)
/
2
);
if
(
arr
[
mid
].
startIndex
>
desiredIndex
)
{
high
=
mid
-
1
;
}
else
{
low
=
mid
;
}
}
return
low
;
}
}
src/vs/editor/common/core/lineParts.ts
浏览文件 @
1d25a68c
...
...
@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
Arrays
}
from
'
vs/editor/common/core/arrays
'
;
import
{
ViewLineToken
}
from
'
vs/editor/common/core/viewLineToken
'
;
export
class
LineParts
{
...
...
@@ -24,8 +23,4 @@ export class LineParts {
&&
ViewLineToken
.
equalsArray
(
this
.
parts
,
other
.
parts
)
);
}
public
findIndexOfOffset
(
offset
:
number
):
number
{
return
Arrays
.
findIndexInSegmentsArray
(
this
.
parts
,
offset
);
}
}
src/vs/editor/common/core/viewLineToken.ts
浏览文件 @
1d25a68c
...
...
@@ -4,8 +4,6 @@
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
{
Arrays
}
from
'
vs/editor/common/core/arrays
'
;
/**
* A token on a line.
*/
...
...
@@ -27,10 +25,6 @@ export class ViewLineToken {
);
}
public
static
findIndexInSegmentsArray
(
arr
:
ViewLineToken
[],
desiredIndex
:
number
):
number
{
return
Arrays
.
findIndexInSegmentsArray
(
arr
,
desiredIndex
);
}
public
static
equalsArray
(
a
:
ViewLineToken
[],
b
:
ViewLineToken
[]):
boolean
{
let
aLen
=
a
.
length
;
let
bLen
=
b
.
length
;
...
...
@@ -78,8 +72,4 @@ export class ViewLineTokens {
&&
ViewLineToken
.
equalsArray
(
this
.
_lineTokens
,
other
.
_lineTokens
)
);
}
public
findIndexOfOffset
(
offset
:
number
):
number
{
return
ViewLineToken
.
findIndexInSegmentsArray
(
this
.
_lineTokens
,
offset
);
}
}
src/vs/editor/common/viewLayout/viewLineParts.ts
浏览文件 @
1d25a68c
...
...
@@ -38,56 +38,6 @@ export function createLineParts(lineNumber: number, minLineColumn: number, lineC
}
}
export
function
getColumnOfLinePartOffset
(
stopRenderingLineAfter
:
number
,
lineParts
:
ViewLineToken
[],
lineMaxColumn
:
number
,
charOffsetInPart
:
number
[],
partIndex
:
number
,
partLength
:
number
,
offset
:
number
):
number
{
if
(
partIndex
>=
lineParts
.
length
)
{
return
stopRenderingLineAfter
;
}
if
(
offset
===
0
)
{
return
lineParts
[
partIndex
].
startIndex
+
1
;
}
if
(
offset
===
partLength
)
{
return
(
partIndex
+
1
<
lineParts
.
length
?
lineParts
[
partIndex
+
1
].
startIndex
+
1
:
lineMaxColumn
);
}
let
originalMin
=
lineParts
[
partIndex
].
startIndex
;
let
originalMax
=
(
partIndex
+
1
<
lineParts
.
length
?
lineParts
[
partIndex
+
1
].
startIndex
:
lineMaxColumn
-
1
);
let
min
=
originalMin
;
let
max
=
originalMax
;
// invariant: offsetOf(min) <= offset <= offsetOf(max)
while
(
min
+
1
<
max
)
{
let
mid
=
((
min
+
max
)
>>>
1
);
let
midOffset
=
charOffsetInPart
[
mid
];
if
(
midOffset
===
offset
)
{
return
mid
+
1
;
}
else
if
(
midOffset
>
offset
)
{
max
=
mid
;
}
else
{
min
=
mid
;
}
}
if
(
min
===
max
)
{
return
min
+
1
;
}
let
minOffset
=
charOffsetInPart
[
min
];
let
maxOffset
=
(
max
<
originalMax
?
charOffsetInPart
[
max
]
:
partLength
);
let
distanceToMin
=
offset
-
minOffset
;
let
distanceToMax
=
maxOffset
-
offset
;
if
(
distanceToMin
<=
distanceToMax
)
{
return
min
+
1
;
}
else
{
return
max
+
1
;
}
}
function
trimEmptyTrailingPart
(
parts
:
ViewLineToken
[],
lineContent
:
string
):
ViewLineToken
[]
{
if
(
parts
.
length
<=
1
)
{
return
parts
;
...
...
src/vs/editor/common/viewLayout/viewLineRenderer.ts
浏览文件 @
1d25a68c
...
...
@@ -50,17 +50,126 @@ export class RenderLineInput {
}
}
export
const
enum
CharacterMappingConstants
{
PART_INDEX_MASK
=
0b11111111111111110000000000000000
,
CHAR_INDEX_MASK
=
0b00000000000000001111111111111111
,
CHAR_INDEX_OFFSET
=
0
,
PART_INDEX_OFFSET
=
16
}
/**
* Provides a both direction mapping between a line's character and its rendered position.
*/
export
class
CharacterMapping
{
public
static
getPartIndex
(
partData
:
number
):
number
{
return
(
partData
&
CharacterMappingConstants
.
PART_INDEX_MASK
)
>>>
CharacterMappingConstants
.
PART_INDEX_OFFSET
;
}
public
static
getCharIndex
(
partData
:
number
):
number
{
return
(
partData
&
CharacterMappingConstants
.
CHAR_INDEX_MASK
)
>>>
CharacterMappingConstants
.
CHAR_INDEX_OFFSET
;
}
private
readonly
_data
:
Uint32Array
;
public
readonly
length
:
number
;
constructor
(
length
:
number
)
{
this
.
length
=
length
;
this
.
_data
=
new
Uint32Array
(
this
.
length
);
}
public
setPartData
(
charOffset
:
number
,
partIndex
:
number
,
charIndex
:
number
):
void
{
let
partData
=
(
(
partIndex
<<
CharacterMappingConstants
.
PART_INDEX_OFFSET
)
|
(
charIndex
<<
CharacterMappingConstants
.
CHAR_INDEX_OFFSET
)
)
>>>
0
;
this
.
_data
[
charOffset
]
=
partData
;
}
public
charOffsetToPartData
(
charOffset
:
number
):
number
{
if
(
this
.
length
===
0
)
{
return
0
;
}
if
(
charOffset
<
0
)
{
return
this
.
_data
[
0
];
}
if
(
charOffset
>=
this
.
length
)
{
return
this
.
_data
[
this
.
length
-
1
];
}
return
this
.
_data
[
charOffset
];
}
public
partDataToCharOffset
(
partIndex
:
number
,
partLength
:
number
,
charIndex
:
number
):
number
{
if
(
this
.
length
===
0
)
{
return
0
;
}
let
searchEntry
=
(
(
partIndex
<<
CharacterMappingConstants
.
PART_INDEX_OFFSET
)
|
(
charIndex
<<
CharacterMappingConstants
.
CHAR_INDEX_OFFSET
)
)
>>>
0
;
let
min
=
0
;
let
max
=
this
.
length
-
1
;
while
(
min
+
1
<
max
)
{
let
mid
=
((
min
+
max
)
>>>
1
);
let
midEntry
=
this
.
_data
[
mid
];
if
(
midEntry
===
searchEntry
)
{
return
mid
;
}
else
if
(
midEntry
>
searchEntry
)
{
max
=
mid
;
}
else
{
min
=
mid
;
}
}
if
(
min
===
max
)
{
return
min
;
}
let
minEntry
=
this
.
_data
[
min
];
let
maxEntry
=
this
.
_data
[
max
];
if
(
minEntry
===
searchEntry
)
{
return
min
;
}
if
(
maxEntry
===
searchEntry
)
{
return
max
;
}
let
minPartIndex
=
CharacterMapping
.
getPartIndex
(
minEntry
);
let
minCharIndex
=
CharacterMapping
.
getCharIndex
(
minEntry
);
let
maxPartIndex
=
CharacterMapping
.
getPartIndex
(
maxEntry
);
let
maxCharIndex
:
number
;
if
(
minPartIndex
!==
maxPartIndex
)
{
// sitting between parts
maxCharIndex
=
partLength
;
}
else
{
maxCharIndex
=
CharacterMapping
.
getCharIndex
(
maxEntry
);
}
let
minEntryDistance
=
charIndex
-
minCharIndex
;
let
maxEntryDistance
=
maxCharIndex
-
charIndex
;
if
(
minEntryDistance
<=
maxEntryDistance
)
{
return
min
;
}
return
max
;
}
}
export
class
RenderLineOutput
{
_renderLineOutputBrand
:
void
;
readonly
charOffsetInPart
:
number
[];
readonly
lastRenderedPartIndex
:
number
;
readonly
characterMapping
:
CharacterMapping
;
readonly
output
:
string
;
readonly
isWhitespaceOnly
:
boolean
;
constructor
(
charOffsetInPart
:
number
[],
lastRenderedPartIndex
:
number
,
output
:
string
,
isWhitespaceOnly
:
boolean
)
{
this
.
charOffsetInPart
=
charOffsetInPart
;
this
.
lastRenderedPartIndex
=
lastRenderedPartIndex
;
constructor
(
characterMapping
:
CharacterMapping
,
output
:
string
,
isWhitespaceOnly
:
boolean
)
{
this
.
characterMapping
=
characterMapping
;
this
.
output
=
output
;
this
.
isWhitespaceOnly
=
isWhitespaceOnly
;
}
...
...
@@ -78,8 +187,7 @@ export function renderLine(input: RenderLineInput): RenderLineOutput {
if
(
lineTextLength
===
0
)
{
return
new
RenderLineOutput
(
[],
0
,
new
CharacterMapping
(
0
),
// This is basically for IE's hit test to work
'
<span><span> </span></span>
'
,
true
...
...
@@ -113,11 +221,12 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
let
charIndex
=
0
;
let
out
=
''
;
let
charOffsetInPartArr
:
number
[]
=
[];
let
charOffsetInPart
=
0
;
let
tabsCharDelta
=
0
;
let
isWhitespaceOnly
=
/^
\s
*$/
.
test
(
lineText
);
let
characterMapping
=
new
CharacterMapping
(
Math
.
min
(
lineTextLength
,
charBreakIndex
)
+
1
);
out
+=
'
<span>
'
;
for
(
let
partIndex
=
0
,
partIndexLen
=
actualLineParts
.
length
;
partIndex
<
partIndexLen
;
partIndex
++
)
{
let
part
=
actualLineParts
[
partIndex
];
...
...
@@ -136,7 +245,7 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
let
partContentCnt
=
0
;
let
partContent
=
''
;
for
(;
charIndex
<
toCharIndex
;
charIndex
++
)
{
char
OffsetInPartArr
[
charIndex
]
=
charOffsetInPart
;
char
acterMapping
.
setPartData
(
charIndex
,
partIndex
,
charOffsetInPart
)
;
let
charCode
=
lineText
.
charCodeAt
(
charIndex
);
if
(
charCode
===
CharCode
.
Tab
)
{
...
...
@@ -163,10 +272,9 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
if
(
charIndex
>=
charBreakIndex
)
{
out
+=
`<span class="
${
part
.
type
}
" style="width:
${(
spaceWidth
*
partContentCnt
)}
px">
${
partContent
}
…</span></span>`
;
char
OffsetInPartArr
[
charIndex
]
=
charOffsetInPart
;
char
acterMapping
.
setPartData
(
charIndex
,
partIndex
,
charOffsetInPart
)
;
return
new
RenderLineOutput
(
charOffsetInPartArr
,
partIndex
,
characterMapping
,
out
,
isWhitespaceOnly
);
...
...
@@ -177,7 +285,7 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
out
+=
`<span class="
${
part
.
type
}
">`
;
for
(;
charIndex
<
toCharIndex
;
charIndex
++
)
{
char
OffsetInPartArr
[
charIndex
]
=
charOffsetInPart
;
char
acterMapping
.
setPartData
(
charIndex
,
partIndex
,
charOffsetInPart
)
;
let
charCode
=
lineText
.
charCodeAt
(
charIndex
);
switch
(
charCode
)
{
...
...
@@ -233,10 +341,9 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
if
(
charIndex
>=
charBreakIndex
)
{
out
+=
'
…</span></span>
'
;
char
OffsetInPartArr
[
charIndex
]
=
charOffsetInPart
;
char
acterMapping
.
setPartData
(
charIndex
,
partIndex
,
charOffsetInPart
)
;
return
new
RenderLineOutput
(
charOffsetInPartArr
,
partIndex
,
characterMapping
,
out
,
isWhitespaceOnly
);
...
...
@@ -251,11 +358,10 @@ function renderLineActual(lineText: string, lineTextLength: number, tabSize: num
// When getting client rects for the last character, we will position the
// text range at the end of the span, insteaf of at the beginning of next span
char
OffsetInPartArr
.
push
(
charOffsetInPart
);
char
acterMapping
.
setPartData
(
lineTextLength
,
actualLineParts
.
length
-
1
,
charOffsetInPart
);
return
new
RenderLineOutput
(
charOffsetInPartArr
,
actualLineParts
.
length
-
1
,
characterMapping
,
out
,
isWhitespaceOnly
);
...
...
src/vs/editor/test/common/viewLayout/viewLineParts.test.ts
浏览文件 @
1d25a68c
...
...
@@ -5,7 +5,7 @@
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
{
DecorationSegment
,
LineDecorationsNormalizer
,
getColumnOfLinePartOffset
,
createLineParts
}
from
'
vs/editor/common/viewLayout/viewLineParts
'
;
import
{
DecorationSegment
,
LineDecorationsNormalizer
,
createLineParts
}
from
'
vs/editor/common/viewLayout/viewLineParts
'
;
import
{
Range
}
from
'
vs/editor/common/core/range
'
;
import
{
RenderLineInput
,
renderLine
}
from
'
vs/editor/common/viewLayout/viewLineRenderer
'
;
import
{
ViewLineToken
,
ViewLineTokens
}
from
'
vs/editor/common/core/viewLineToken
'
;
...
...
@@ -342,7 +342,8 @@ suite('Editor ViewLayout - ViewLineParts', () => {
let
renderLineOutput
=
renderLine
(
new
RenderLineInput
(
lineContent
,
tabSize
,
10
,
-
1
,
'
none
'
,
false
,
new
LineParts
(
parts
,
lineContent
.
length
+
1
)));
return
(
partIndex
:
number
,
partLength
:
number
,
offset
:
number
,
expected
:
number
)
=>
{
let
actual
=
getColumnOfLinePartOffset
(
-
1
,
parts
,
lineContent
.
length
+
1
,
renderLineOutput
.
charOffsetInPart
,
partIndex
,
partLength
,
offset
);
let
charOffset
=
renderLineOutput
.
characterMapping
.
partDataToCharOffset
(
partIndex
,
partLength
,
offset
);
let
actual
=
charOffset
+
1
;
assert
.
equal
(
actual
,
expected
,
'
getColumnOfLinePartOffset for
'
+
partIndex
+
'
@
'
+
offset
);
};
}
...
...
src/vs/editor/test/common/viewLayout/viewLineRenderer.test.ts
浏览文件 @
1d25a68c
...
...
@@ -5,7 +5,7 @@
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
{
renderLine
,
RenderLineInput
}
from
'
vs/editor/common/viewLayout/viewLineRenderer
'
;
import
{
renderLine
,
RenderLineInput
,
CharacterMapping
}
from
'
vs/editor/common/viewLayout/viewLineRenderer
'
;
import
{
ViewLineToken
}
from
'
vs/editor/common/core/viewLineToken
'
;
import
{
CharCode
}
from
'
vs/base/common/charCode
'
;
import
{
LineParts
}
from
'
vs/editor/common/core/lineParts
'
;
...
...
@@ -16,7 +16,7 @@ suite('viewLineRenderer.renderLine', () => {
return
new
ViewLineToken
(
startIndex
,
type
);
}
function
assertCharacterReplacement
(
lineContent
:
string
,
tabSize
:
number
,
expected
:
string
,
expectedCharOffsetInPart
:
number
[]):
void
{
function
assertCharacterReplacement
(
lineContent
:
string
,
tabSize
:
number
,
expected
:
string
,
expectedCharOffsetInPart
:
number
[]
[]
):
void
{
let
_actual
=
renderLine
(
new
RenderLineInput
(
lineContent
,
tabSize
,
...
...
@@ -28,37 +28,37 @@ suite('viewLineRenderer.renderLine', () => {
));
assert
.
equal
(
_actual
.
output
,
'
<span><span class="">
'
+
expected
+
'
</span></span>
'
);
assert
.
deepEqual
(
_actual
.
charOffsetInPart
,
expectedCharOffsetInPart
);
assert
CharacterMapping
(
_actual
.
characterMapping
,
expectedCharOffsetInPart
);
}
test
(
'
replaces spaces
'
,
()
=>
{
assertCharacterReplacement
(
'
'
,
4
,
'
'
,
[
0
,
1
]);
assertCharacterReplacement
(
'
'
,
4
,
'
'
,
[
0
,
1
,
2
]);
assertCharacterReplacement
(
'
a b
'
,
4
,
'
a b
'
,
[
0
,
1
,
2
,
3
,
4
]);
assertCharacterReplacement
(
'
'
,
4
,
'
'
,
[
[
0
,
1
]
]);
assertCharacterReplacement
(
'
'
,
4
,
'
'
,
[
[
0
,
1
,
2
]
]);
assertCharacterReplacement
(
'
a b
'
,
4
,
'
a b
'
,
[
[
0
,
1
,
2
,
3
,
4
]
]);
});
test
(
'
escapes HTML markup
'
,
()
=>
{
assertCharacterReplacement
(
'
a<b
'
,
4
,
'
a<b
'
,
[
0
,
1
,
2
,
3
]);
assertCharacterReplacement
(
'
a>b
'
,
4
,
'
a>b
'
,
[
0
,
1
,
2
,
3
]);
assertCharacterReplacement
(
'
a&b
'
,
4
,
'
a&b
'
,
[
0
,
1
,
2
,
3
]);
assertCharacterReplacement
(
'
a<b
'
,
4
,
'
a<b
'
,
[
[
0
,
1
,
2
,
3
]
]);
assertCharacterReplacement
(
'
a>b
'
,
4
,
'
a>b
'
,
[
[
0
,
1
,
2
,
3
]
]);
assertCharacterReplacement
(
'
a&b
'
,
4
,
'
a&b
'
,
[
[
0
,
1
,
2
,
3
]
]);
});
test
(
'
replaces some bad characters
'
,
()
=>
{
assertCharacterReplacement
(
'
a
\
0b
'
,
4
,
'
a�b
'
,
[
0
,
1
,
2
,
3
]);
assertCharacterReplacement
(
'
a
'
+
String
.
fromCharCode
(
CharCode
.
UTF8_BOM
)
+
'
b
'
,
4
,
'
a
\
ufffdb
'
,
[
0
,
1
,
2
,
3
]);
assertCharacterReplacement
(
'
a
\
u2028b
'
,
4
,
'
a
\
ufffdb
'
,
[
0
,
1
,
2
,
3
]);
assertCharacterReplacement
(
'
a
\r
b
'
,
4
,
'
a​b
'
,
[
0
,
1
,
2
,
3
]);
assertCharacterReplacement
(
'
a
\
0b
'
,
4
,
'
a�b
'
,
[
[
0
,
1
,
2
,
3
]
]);
assertCharacterReplacement
(
'
a
'
+
String
.
fromCharCode
(
CharCode
.
UTF8_BOM
)
+
'
b
'
,
4
,
'
a
\
ufffdb
'
,
[
[
0
,
1
,
2
,
3
]
]);
assertCharacterReplacement
(
'
a
\
u2028b
'
,
4
,
'
a
\
ufffdb
'
,
[
[
0
,
1
,
2
,
3
]
]);
assertCharacterReplacement
(
'
a
\r
b
'
,
4
,
'
a​b
'
,
[
[
0
,
1
,
2
,
3
]
]);
});
test
(
'
handles tabs
'
,
()
=>
{
assertCharacterReplacement
(
'
\t
'
,
4
,
'
'
,
[
0
,
4
]);
assertCharacterReplacement
(
'
x
\t
'
,
4
,
'
x
'
,
[
0
,
1
,
4
]);
assertCharacterReplacement
(
'
xx
\t
'
,
4
,
'
xx
'
,
[
0
,
1
,
2
,
4
]);
assertCharacterReplacement
(
'
xxx
\t
'
,
4
,
'
xxx
'
,
[
0
,
1
,
2
,
3
,
4
]);
assertCharacterReplacement
(
'
xxxx
\t
'
,
4
,
'
xxxx
'
,
[
0
,
1
,
2
,
3
,
4
,
8
]);
assertCharacterReplacement
(
'
\t
'
,
4
,
'
'
,
[
[
0
,
4
]
]);
assertCharacterReplacement
(
'
x
\t
'
,
4
,
'
x
'
,
[
[
0
,
1
,
4
]
]);
assertCharacterReplacement
(
'
xx
\t
'
,
4
,
'
xx
'
,
[
[
0
,
1
,
2
,
4
]
]);
assertCharacterReplacement
(
'
xxx
\t
'
,
4
,
'
xxx
'
,
[
[
0
,
1
,
2
,
3
,
4
]
]);
assertCharacterReplacement
(
'
xxxx
\t
'
,
4
,
'
xxxx
'
,
[
[
0
,
1
,
2
,
3
,
4
,
8
]
]);
});
function
assertParts
(
lineContent
:
string
,
tabSize
:
number
,
parts
:
ViewLineToken
[],
expected
:
string
,
expectedCharOffsetInPart
:
number
[]):
void
{
function
assertParts
(
lineContent
:
string
,
tabSize
:
number
,
parts
:
ViewLineToken
[],
expected
:
string
,
expectedCharOffsetInPart
:
number
[]
[]
):
void
{
let
_actual
=
renderLine
(
new
RenderLineInput
(
lineContent
,
tabSize
,
...
...
@@ -70,7 +70,7 @@ suite('viewLineRenderer.renderLine', () => {
));
assert
.
equal
(
_actual
.
output
,
'
<span>
'
+
expected
+
'
</span>
'
);
assert
.
deepEqual
(
_actual
.
charOffsetInPart
,
expectedCharOffsetInPart
);
assert
CharacterMapping
(
_actual
.
characterMapping
,
expectedCharOffsetInPart
);
}
test
(
'
empty line
'
,
()
=>
{
...
...
@@ -78,15 +78,15 @@ suite('viewLineRenderer.renderLine', () => {
});
test
(
'
uses part type
'
,
()
=>
{
assertParts
(
'
x
'
,
4
,
[
createPart
(
0
,
'
y
'
)],
'
<span class="y">x</span>
'
,
[
0
,
1
]);
assertParts
(
'
x
'
,
4
,
[
createPart
(
0
,
'
aAbBzZ0123456789-cC
'
)],
'
<span class="aAbBzZ0123456789-cC">x</span>
'
,
[
0
,
1
]);
assertParts
(
'
x
'
,
4
,
[
createPart
(
0
,
'
'
)],
'
<span class=" ">x</span>
'
,
[
0
,
1
]);
assertParts
(
'
x
'
,
4
,
[
createPart
(
0
,
'
y
'
)],
'
<span class="y">x</span>
'
,
[
[
0
,
1
]
]);
assertParts
(
'
x
'
,
4
,
[
createPart
(
0
,
'
aAbBzZ0123456789-cC
'
)],
'
<span class="aAbBzZ0123456789-cC">x</span>
'
,
[
[
0
,
1
]
]);
assertParts
(
'
x
'
,
4
,
[
createPart
(
0
,
'
'
)],
'
<span class=" ">x</span>
'
,
[
[
0
,
1
]
]);
});
test
(
'
two parts
'
,
()
=>
{
assertParts
(
'
xy
'
,
4
,
[
createPart
(
0
,
'
a
'
),
createPart
(
1
,
'
b
'
)],
'
<span class="a">x</span><span class="b">y</span>
'
,
[
0
,
0
,
1
]);
assertParts
(
'
xyz
'
,
4
,
[
createPart
(
0
,
'
a
'
),
createPart
(
1
,
'
b
'
)],
'
<span class="a">x</span><span class="b">yz</span>
'
,
[
0
,
0
,
1
,
2
]);
assertParts
(
'
xyz
'
,
4
,
[
createPart
(
0
,
'
a
'
),
createPart
(
2
,
'
b
'
)],
'
<span class="a">xy</span><span class="b">z</span>
'
,
[
0
,
1
,
0
,
1
]);
assertParts
(
'
xy
'
,
4
,
[
createPart
(
0
,
'
a
'
),
createPart
(
1
,
'
b
'
)],
'
<span class="a">x</span><span class="b">y</span>
'
,
[
[
0
],
[
0
,
1
]
]);
assertParts
(
'
xyz
'
,
4
,
[
createPart
(
0
,
'
a
'
),
createPart
(
1
,
'
b
'
)],
'
<span class="a">x</span><span class="b">yz</span>
'
,
[
[
0
],
[
0
,
1
,
2
]
]);
assertParts
(
'
xyz
'
,
4
,
[
createPart
(
0
,
'
a
'
),
createPart
(
2
,
'
b
'
)],
'
<span class="a">xy</span><span class="b">z</span>
'
,
[
[
0
,
1
],
[
0
,
1
]
]);
});
test
(
'
overflow
'
,
()
=>
{
...
...
@@ -126,13 +126,13 @@ suite('viewLineRenderer.renderLine', () => {
].
join
(
''
);
assert
.
equal
(
_actual
.
output
,
'
<span>
'
+
expectedOutput
+
'
</span>
'
);
assert
.
deepEqual
(
_actual
.
charOffsetInPart
,
[
0
,
0
,
0
,
0
,
0
,
1
assert
CharacterMapping
(
_actual
.
characterMapping
,
[
[
0
]
,
[
0
]
,
[
0
]
,
[
0
]
,
[
0
]
,
[
1
],
]);
});
...
...
@@ -180,7 +180,6 @@ suite('viewLineRenderer.renderLine', () => {
[
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
,
13
,
14
],
[
0
,
1
,
2
,
3
,
4
,
5
],
];
let
expectedOffsets
=
expectedOffsetsArr
.
reduce
((
prev
,
curr
)
=>
prev
.
concat
(
curr
),
[]);
let
_actual
=
renderLine
(
new
RenderLineInput
(
lineText
,
...
...
@@ -193,7 +192,7 @@ suite('viewLineRenderer.renderLine', () => {
));
assert
.
equal
(
_actual
.
output
,
'
<span>
'
+
expectedOutput
+
'
</span>
'
);
assert
.
deepEqual
(
_actual
.
charOffsetInPart
,
expectedOffsets
);
assert
CharacterMapping
(
_actual
.
characterMapping
,
expectedOffsetsArr
);
});
test
(
'
issue #2255: Weird line rendering part 1
'
,
()
=>
{
...
...
@@ -235,7 +234,6 @@ suite('viewLineRenderer.renderLine', () => {
[
0
],
// 1 char
[
0
,
1
]
// 2 chars
];
let
expectedOffsets
=
expectedOffsetsArr
.
reduce
((
prev
,
curr
)
=>
prev
.
concat
(
curr
),
[]);
let
_actual
=
renderLine
(
new
RenderLineInput
(
lineText
,
...
...
@@ -248,7 +246,7 @@ suite('viewLineRenderer.renderLine', () => {
));
assert
.
equal
(
_actual
.
output
,
'
<span>
'
+
expectedOutput
+
'
</span>
'
);
assert
.
deepEqual
(
_actual
.
charOffsetInPart
,
expectedOffsets
);
assert
CharacterMapping
(
_actual
.
characterMapping
,
expectedOffsetsArr
);
});
test
(
'
issue #2255: Weird line rendering part 2
'
,
()
=>
{
...
...
@@ -290,7 +288,6 @@ suite('viewLineRenderer.renderLine', () => {
[
0
],
// 1 char
[
0
,
1
]
// 2 chars
];
let
expectedOffsets
=
expectedOffsetsArr
.
reduce
((
prev
,
curr
)
=>
prev
.
concat
(
curr
),
[]);
let
_actual
=
renderLine
(
new
RenderLineInput
(
lineText
,
...
...
@@ -303,8 +300,38 @@ suite('viewLineRenderer.renderLine', () => {
));
assert
.
equal
(
_actual
.
output
,
'
<span>
'
+
expectedOutput
+
'
</span>
'
);
assert
.
deepEqual
(
_actual
.
charOffsetInPart
,
expectedOffsets
);
assert
CharacterMapping
(
_actual
.
characterMapping
,
expectedOffsetsArr
);
});
function
assertCharacterMapping
(
actual
:
CharacterMapping
,
expected
:
number
[][]):
void
{
let
charOffset
=
0
;
for
(
let
partIndex
=
0
;
partIndex
<
expected
.
length
;
partIndex
++
)
{
let
part
=
expected
[
partIndex
];
for
(
let
i
=
0
;
i
<
part
.
length
;
i
++
)
{
let
charIndex
=
part
[
i
];
let
_actualPartData
=
actual
.
charOffsetToPartData
(
charOffset
);
let
actualPartIndex
=
CharacterMapping
.
getPartIndex
(
_actualPartData
);
let
actualCharIndex
=
CharacterMapping
.
getCharIndex
(
_actualPartData
);
assert
.
deepEqual
(
{
partIndex
:
actualPartIndex
,
charIndex
:
actualCharIndex
},
{
partIndex
:
partIndex
,
charIndex
:
charIndex
},
`character mapping for offset
${
charOffset
}
`
);
let
actualOffset
=
actual
.
partDataToCharOffset
(
partIndex
,
part
[
part
.
length
-
1
]
+
1
,
charIndex
);
assert
.
equal
(
actualOffset
,
charOffset
,
`character mapping for part
${
partIndex
}
,
${
charIndex
}
`
);
charOffset
++
;
}
}
assert
.
equal
(
actual
.
length
,
charOffset
);
}
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录