Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
7618cf49
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,发现更多精彩内容 >>
未验证
提交
7618cf49
编写于
3月 09, 2018
作者:
P
Pine
提交者:
GitHub
3月 09, 2018
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #45437 from Microsoft/octref/pathCompletion
March path completion improvements
上级
a2a515e0
b49be24f
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
203 addition
and
102 deletion
+203
-102
extensions/html/server/src/modes/pathCompletion.ts
extensions/html/server/src/modes/pathCompletion.ts
+42
-27
extensions/html/server/src/test/pathCompletion/pathCompletion.test.ts
...tml/server/src/test/pathCompletion/pathCompletion.test.ts
+161
-75
未找到文件。
extensions/html/server/src/modes/pathCompletion.ts
浏览文件 @
7618cf49
...
...
@@ -22,15 +22,10 @@ export function getPathCompletionParticipant(
onHtmlAttributeValue
:
({
tag
,
attribute
,
value
,
range
})
=>
{
if
(
shouldDoPathCompletion
(
tag
,
attribute
,
value
))
{
let
workspaceRoot
;
if
(
startsWith
(
value
,
'
/
'
))
{
if
(
!
workspaceFolders
||
workspaceFolders
.
length
===
0
)
{
return
;
}
workspaceRoot
=
resolveWorkspaceRoot
(
document
,
workspaceFolders
);
if
(
!
workspaceFolders
||
workspaceFolders
.
length
===
0
)
{
return
;
}
const
workspaceRoot
=
resolveWorkspaceRoot
(
document
,
workspaceFolders
);
const
suggestions
=
providePathSuggestions
(
value
,
range
,
URI
.
parse
(
document
.
uri
).
fsPath
,
workspaceRoot
);
result
.
items
=
[...
suggestions
,
...
result
.
items
];
...
...
@@ -56,34 +51,49 @@ function shouldDoPathCompletion(tag: string, attr: string, value: string): boole
}
export
function
providePathSuggestions
(
value
:
string
,
range
:
Range
,
activeDocFsPath
:
string
,
root
?:
string
):
CompletionItem
[]
{
if
(
value
.
indexOf
(
'
/
'
)
===
-
1
)
{
return
[];
}
if
(
startsWith
(
value
,
'
/
'
)
&&
!
root
)
{
return
[];
}
let
replaceRange
:
Range
;
const
lastIndexOfSlash
=
value
.
lastIndexOf
(
'
/
'
);
const
valueBeforeLastSlash
=
value
.
slice
(
0
,
lastIndexOfSlash
+
1
);
const
valueAfterLastSlash
=
value
.
slice
(
lastIndexOfSlash
+
1
);
const
parentDir
=
startsWith
(
value
,
'
/
'
)
?
path
.
resolve
(
root
,
'
.
'
+
valueBeforeLastSlash
)
:
path
.
resolve
(
activeDocFsPath
,
'
..
'
,
valueBeforeLastSlash
);
if
(
!
fs
.
existsSync
(
parentDir
))
{
return
[];
if
(
lastIndexOfSlash
===
-
1
)
{
replaceRange
=
getFullReplaceRange
(
range
);
}
else
{
const
valueAfterLastSlash
=
value
.
slice
(
lastIndexOfSlash
+
1
);
replaceRange
=
getReplaceRange
(
range
,
valueAfterLastSlash
);
}
const
replaceRange
=
getReplaceRange
(
range
,
valueAfterLastSlash
);
let
parentDir
:
string
;
if
(
lastIndexOfSlash
===
-
1
)
{
parentDir
=
path
.
resolve
(
root
);
}
else
{
const
valueBeforeLastSlash
=
value
.
slice
(
0
,
lastIndexOfSlash
+
1
);
parentDir
=
startsWith
(
value
,
'
/
'
)
?
path
.
resolve
(
root
,
'
.
'
+
valueBeforeLastSlash
)
:
path
.
resolve
(
activeDocFsPath
,
'
..
'
,
valueBeforeLastSlash
);
}
try
{
return
fs
.
readdirSync
(
parentDir
).
map
(
f
=>
{
return
{
label
:
f
,
kind
:
isDir
(
path
.
resolve
(
parentDir
,
f
))
?
CompletionItemKind
.
Folder
:
CompletionItemKind
.
File
,
textEdit
:
TextEdit
.
replace
(
replaceRange
,
f
)
};
if
(
isDir
(
path
.
resolve
(
parentDir
,
f
)))
{
return
{
label
:
f
+
'
/
'
,
kind
:
CompletionItemKind
.
Folder
,
textEdit
:
TextEdit
.
replace
(
replaceRange
,
f
+
'
/
'
),
command
:
{
title
:
'
Suggest
'
,
command
:
'
editor.action.triggerSuggest
'
}
};
}
else
{
return
{
label
:
f
,
kind
:
CompletionItemKind
.
File
,
textEdit
:
TextEdit
.
replace
(
replaceRange
,
f
)
};
}
});
}
catch
(
e
)
{
return
[];
...
...
@@ -102,7 +112,12 @@ function resolveWorkspaceRoot(activeDoc: TextDocument, workspaceFolders: Propose
}
}
function
getReplaceRange
(
valueRange
:
Range
,
valueAfterLastSlash
:
string
):
Range
{
function
getFullReplaceRange
(
valueRange
:
Range
)
{
const
start
=
Position
.
create
(
valueRange
.
end
.
line
,
valueRange
.
start
.
character
+
1
);
const
end
=
Position
.
create
(
valueRange
.
end
.
line
,
valueRange
.
end
.
character
-
1
);
return
Range
.
create
(
start
,
end
);
}
function
getReplaceRange
(
valueRange
:
Range
,
valueAfterLastSlash
:
string
)
{
const
start
=
Position
.
create
(
valueRange
.
end
.
line
,
valueRange
.
end
.
character
-
1
-
valueAfterLastSlash
.
length
);
const
end
=
Position
.
create
(
valueRange
.
end
.
line
,
valueRange
.
end
.
character
-
1
);
return
Range
.
create
(
start
,
end
);
...
...
extensions/html/server/src/test/pathCompletion/pathCompletion.test.ts
浏览文件 @
7618cf49
...
...
@@ -7,78 +7,117 @@
import
*
as
assert
from
'
assert
'
;
import
*
as
path
from
'
path
'
;
import
{
providePathSuggestions
}
from
'
../../modes/pathCompletion
'
;
import
{
CompletionItemKind
,
Range
,
Position
}
from
'
vscode-languageserver-types
'
;
import
{
CompletionItemKind
,
Range
,
Position
,
CompletionItem
,
TextEdit
,
Command
}
from
'
vscode-languageserver-types
'
;
const
fixtureRoot
=
path
.
resolve
(
__dirname
,
'
../../../test/pathCompletionFixtures
'
);
suite
(
'
Path Completion - Relative Path
'
,
()
=>
{
const
mockRange
=
Range
.
create
(
Position
.
create
(
0
,
3
),
Position
.
create
(
0
,
5
));
function
toRange
(
line
:
number
,
startChar
:
number
,
endChar
:
number
)
{
return
Range
.
create
(
Position
.
create
(
line
,
startChar
),
Position
.
create
(
line
,
endChar
));
}
function
toTextEdit
(
line
:
number
,
startChar
:
number
,
endChar
:
number
,
newText
:
string
)
{
const
range
=
Range
.
create
(
Position
.
create
(
line
,
startChar
),
Position
.
create
(
line
,
endChar
));
return
TextEdit
.
replace
(
range
,
newText
);
}
interface
PathSuggestion
{
label
?:
string
;
kind
?:
CompletionItemKind
;
textEdit
?:
TextEdit
;
command
?:
Command
;
}
function
assertSuggestions
(
actual
:
CompletionItem
[],
expected
:
PathSuggestion
[])
{
assert
.
equal
(
actual
.
length
,
expected
.
length
,
`Suggestions have length
${
actual
.
length
}
but should have length
${
expected
.
length
}
`
);
for
(
let
i
=
0
;
i
<
expected
.
length
;
i
++
)
{
if
(
expected
[
i
].
label
)
{
assert
.
equal
(
actual
[
i
].
label
,
expected
[
i
].
label
,
`Suggestion
${
actual
[
i
].
label
}
should have label
${
expected
[
i
].
label
}
`
);
}
if
(
expected
[
i
].
kind
)
{
assert
.
equal
(
actual
[
i
].
kind
,
expected
[
i
].
kind
,
`Suggestion
${
actual
[
i
].
label
}
has type
${
CompletionItemKind
[
actual
[
i
].
kind
]}
but should have label
${
CompletionItemKind
[
expected
[
i
].
kind
]}
`
);
}
if
(
expected
[
i
].
textEdit
)
{
assert
.
equal
(
actual
[
i
].
textEdit
.
newText
,
expected
[
i
].
textEdit
.
newText
);
assert
.
deepEqual
(
actual
[
i
].
textEdit
.
range
,
expected
[
i
].
textEdit
.
range
);
}
if
(
expected
[
i
].
command
)
{
assert
.
equal
(
actual
[
i
].
command
.
title
,
expected
[
i
].
command
.
title
,
`Suggestion
${
actual
[
i
].
label
}
has command title
${
actual
[
i
].
command
.
title
}
but should have command title
${
expected
[
i
].
command
.
title
}
`
);
assert
.
equal
(
actual
[
i
].
command
.
command
,
expected
[
i
].
command
.
command
,
`Suggestion
${
actual
[
i
].
label
}
has command
${
actual
[
i
].
command
.
command
}
but should have command
${
expected
[
i
].
command
.
command
}
`
);
}
}
}
suite
(
'
Path Completion - Relative Path:
'
,
()
=>
{
const
mockRange
=
toRange
(
0
,
3
,
5
);
test
(
'
Current Folder
'
,
()
=>
{
const
value
=
'
./
'
;
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
index.html
'
);
const
suggestions
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath
);
assert
.
equal
(
suggestions
.
length
,
3
);
assert
.
equal
(
suggestions
[
0
].
label
,
'
about
'
);
assert
.
equal
(
suggestions
[
1
].
label
,
'
index.html
'
);
assert
.
equal
(
suggestions
[
2
].
label
,
'
src
'
);
assert
.
equal
(
suggestions
[
0
].
kind
,
CompletionItemKind
.
Folder
);
assert
.
equal
(
suggestions
[
1
].
kind
,
CompletionItemKind
.
File
);
assert
.
equal
(
suggestions
[
2
].
kind
,
CompletionItemKind
.
Folder
);
assertSuggestions
(
suggestions
,
[
{
label
:
'
about/
'
,
kind
:
CompletionItemKind
.
Folder
},
{
label
:
'
index.html
'
,
kind
:
CompletionItemKind
.
File
},
{
label
:
'
src/
'
,
kind
:
CompletionItemKind
.
Folder
}
]);
});
test
(
'
Parent Folder
'
,
()
=>
{
test
(
'
Parent Folder
:
'
,
()
=>
{
const
value
=
'
../
'
;
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
about/about.html
'
);
const
suggestions
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath
);
assert
.
equal
(
suggestions
.
length
,
3
);
assert
.
equal
(
suggestions
[
0
].
label
,
'
about
'
);
assert
.
equal
(
suggestions
[
1
].
label
,
'
index.html
'
);
assert
.
equal
(
suggestions
[
2
].
label
,
'
src
'
);
assert
.
equal
(
suggestions
[
0
].
kind
,
CompletionItemKind
.
Folder
);
assert
.
equal
(
suggestions
[
1
].
kind
,
CompletionItemKind
.
File
);
assert
.
equal
(
suggestions
[
2
].
kind
,
CompletionItemKind
.
Folder
);
assertSuggestions
(
suggestions
,
[
{
label
:
'
about/
'
,
kind
:
CompletionItemKind
.
Folder
},
{
label
:
'
index.html
'
,
kind
:
CompletionItemKind
.
File
},
{
label
:
'
src/
'
,
kind
:
CompletionItemKind
.
Folder
}
]);
});
test
(
'
Adjacent Folder
'
,
()
=>
{
test
(
'
Adjacent Folder
:
'
,
()
=>
{
const
value
=
'
../src/
'
;
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
about/about.html
'
);
const
suggestions
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath
);
assert
.
equal
(
suggestions
.
length
,
2
);
assert
.
equal
(
suggestions
[
0
].
label
,
'
feature.js
'
);
assert
.
equal
(
suggestions
[
1
].
label
,
'
test.js
'
);
assert
.
equal
(
suggestions
[
0
].
kind
,
CompletionItemKind
.
File
);
assert
.
equal
(
suggestions
[
1
].
kind
,
CompletionItemKind
.
File
);
assertSuggestions
(
suggestions
,
[
{
label
:
'
feature.js
'
,
kind
:
CompletionItemKind
.
File
},
{
label
:
'
test.js
'
,
kind
:
CompletionItemKind
.
File
}
]);
});
});
suite
(
'
Path Completion - Absolute Path
'
,
()
=>
{
const
mockRange
=
Range
.
create
(
Position
.
create
(
0
,
3
),
Position
.
create
(
0
,
5
)
);
suite
(
'
Path Completion - Absolute Path
:
'
,
()
=>
{
const
mockRange
=
toRange
(
0
,
3
,
5
);
test
(
'
Root
'
,
()
=>
{
const
value
=
'
/
'
;
const
activeFileFsPath1
=
path
.
resolve
(
fixtureRoot
,
'
index.html
'
);
const
activeFileFsPath2
=
path
.
resolve
(
fixtureRoot
,
'
about/index.html
'
);
const
suggestions1
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath1
,
fixtureRoot
);
const
suggestions2
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath2
,
fixtureRoot
);
const
suggestions1
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath1
,
fixtureRoot
);
const
suggestions2
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath2
,
fixtureRoot
);
const
verify
=
(
suggestions
)
=>
{
assert
.
equal
(
suggestions
[
0
].
label
,
'
about
'
);
assert
.
equal
(
suggestions
[
1
].
label
,
'
index.html
'
);
assert
.
equal
(
suggestions
[
2
].
label
,
'
src
'
);
assert
.
equal
(
suggestions
[
0
].
kind
,
CompletionItemKind
.
Folder
);
assert
.
equal
(
suggestions
[
1
].
kind
,
CompletionItemKind
.
File
);
assert
.
equal
(
suggestions
[
2
].
kind
,
CompletionItemKind
.
Folder
);
assertSuggestions
(
suggestions
,
[
{
label
:
'
about/
'
,
kind
:
CompletionItemKind
.
Folder
},
{
label
:
'
index.html
'
,
kind
:
CompletionItemKind
.
File
},
{
label
:
'
src/
'
,
kind
:
CompletionItemKind
.
Folder
}
]);
};
verify
(
suggestions1
);
...
...
@@ -90,62 +129,109 @@ suite('Path Completion - Absolute Path', () => {
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
about/about.html
'
);
const
suggestions
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath
,
fixtureRoot
);
assert
.
equal
(
suggestions
.
length
,
2
);
assert
.
equal
(
suggestions
[
0
].
label
,
'
feature.js
'
);
assert
.
equal
(
suggestions
[
1
].
label
,
'
test.js
'
);
assertSuggestions
(
suggestions
,
[
{
label
:
'
feature.js
'
,
kind
:
CompletionItemKind
.
File
},
{
label
:
'
test.js
'
,
kind
:
CompletionItemKind
.
File
}
]);
});
});
suite
(
'
Path Completion - Folder Commands:
'
,
()
=>
{
const
mockRange
=
toRange
(
0
,
3
,
5
);
test
(
'
Folder should have command `editor.action.triggerSuggest
'
,
()
=>
{
const
value
=
'
./
'
;
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
index.html
'
);
const
suggestions
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath
);
assert
.
equal
(
suggestions
[
0
].
kind
,
CompletionItemKind
.
File
);
assert
.
equal
(
suggestions
[
1
].
kind
,
CompletionItemKind
.
File
);
assertSuggestions
(
suggestions
,
[
{
label
:
'
about/
'
,
command
:
{
title
:
'
Suggest
'
,
command
:
'
editor.action.triggerSuggest
'
}
},
{
label
:
'
index.html
'
},
{
label
:
'
src/
'
,
command
:
{
title
:
'
Suggest
'
,
command
:
'
editor.action.triggerSuggest
'
}
},
]);
});
});
suite
(
'
Path Completion - Incomplete Path at End
'
,
()
=>
{
const
mockRange
=
Range
.
create
(
Position
.
create
(
0
,
3
),
Position
.
create
(
0
,
5
)
);
suite
(
'
Path Completion - Incomplete Path at End
:
'
,
()
=>
{
const
mockRange
=
toRange
(
0
,
3
,
5
);
test
(
'
Incomplete Path that starts with slash
'
,
()
=>
{
const
value
=
'
/src/f
'
;
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
about/about.html
'
);
const
suggestions
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath
,
fixtureRoot
);
assert
.
equal
(
suggestions
.
length
,
2
);
assert
.
equal
(
suggestions
[
0
].
label
,
'
feature.js
'
);
assert
.
equal
(
suggestions
[
1
].
label
,
'
test.js
'
);
assert
.
equal
(
suggestions
[
0
].
kind
,
CompletionItemKind
.
File
);
assert
.
equal
(
suggestions
[
1
].
kind
,
CompletionItemKind
.
File
);
});
assertSuggestions
(
suggestions
,
[
{
label
:
'
feature.js
'
,
kind
:
CompletionItemKind
.
File
},
{
label
:
'
test.js
'
,
kind
:
CompletionItemKind
.
File
}
]);
});
test
(
'
Incomplete Path that does not start with slash
'
,
()
=>
{
const
value
=
'
../src/f
'
;
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
about/about.html
'
);
const
suggestions
=
providePathSuggestions
(
value
,
mockRange
,
activeFileFsPath
,
fixtureRoot
);
assert
.
equal
(
suggestions
.
length
,
2
);
assert
.
equal
(
suggestions
[
0
].
label
,
'
feature.js
'
);
assert
.
equal
(
suggestions
[
1
].
label
,
'
test.js
'
);
assertSuggestions
(
suggestions
,
[
{
label
:
'
feature.js
'
,
kind
:
CompletionItemKind
.
File
},
{
label
:
'
test.js
'
,
kind
:
CompletionItemKind
.
File
}
]);
});
});
suite
(
'
Path Completion - No leading dot or slash:
'
,
()
=>
{
test
(
'
Top level completion
'
,
()
=>
{
const
value
=
'
s
'
;
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
index.html
'
);
const
range
=
toRange
(
0
,
3
,
5
);
const
suggestions
=
providePathSuggestions
(
value
,
range
,
activeFileFsPath
,
fixtureRoot
);
assertSuggestions
(
suggestions
,
[
{
label
:
'
about/
'
,
kind
:
CompletionItemKind
.
Folder
,
textEdit
:
toTextEdit
(
0
,
4
,
4
,
'
about/
'
)
},
{
label
:
'
index.html
'
,
kind
:
CompletionItemKind
.
File
,
textEdit
:
toTextEdit
(
0
,
4
,
4
,
'
index.html
'
)
},
{
label
:
'
src/
'
,
kind
:
CompletionItemKind
.
Folder
,
textEdit
:
toTextEdit
(
0
,
4
,
4
,
'
src/
'
)
}
]);
});
test
(
'
src/
'
,
()
=>
{
const
value
=
'
src/
'
;
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
index.html
'
);
const
range
=
toRange
(
0
,
3
,
8
);
const
suggestions
=
providePathSuggestions
(
value
,
range
,
activeFileFsPath
,
fixtureRoot
);
assert
.
equal
(
suggestions
[
0
].
kind
,
CompletionItemKind
.
File
);
assert
.
equal
(
suggestions
[
1
].
kind
,
CompletionItemKind
.
File
);
});
assertSuggestions
(
suggestions
,
[
{
label
:
'
feature.js
'
,
kind
:
CompletionItemKind
.
File
,
textEdit
:
toTextEdit
(
0
,
7
,
7
,
'
feature.js
'
)
},
{
label
:
'
test.js
'
,
kind
:
CompletionItemKind
.
File
,
textEdit
:
toTextEdit
(
0
,
7
,
7
,
'
test.js
'
)
}
]);
});
test
(
'
src/f
'
,
()
=>
{
const
value
=
'
src/f
'
;
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
index.html
'
);
const
range
=
toRange
(
0
,
3
,
9
);
const
suggestions
=
providePathSuggestions
(
value
,
range
,
activeFileFsPath
,
fixtureRoot
);
assertSuggestions
(
suggestions
,
[
{
label
:
'
feature.js
'
,
kind
:
CompletionItemKind
.
File
,
textEdit
:
toTextEdit
(
0
,
7
,
8
,
'
feature.js
'
)
},
{
label
:
'
test.js
'
,
kind
:
CompletionItemKind
.
File
,
textEdit
:
toTextEdit
(
0
,
7
,
8
,
'
test.js
'
)
}
]);
});
});
suite
(
'
Path Completion - TextEdit
'
,
()
=>
{
suite
(
'
Path Completion - TextEdit:
'
,
()
=>
{
test
(
'
TextEdit has correct replace text and range
'
,
()
=>
{
const
value
=
'
./
'
;
const
activeFileFsPath
=
path
.
resolve
(
fixtureRoot
,
'
index.html
'
);
const
range
=
Range
.
create
(
Position
.
create
(
0
,
3
),
Position
.
create
(
0
,
5
));
const
suggestions
=
providePathSuggestions
(
value
,
range
,
activeFileFsPath
);
assert
.
equal
(
suggestions
[
0
].
textEdit
.
newText
,
'
about
'
);
assert
.
equal
(
suggestions
[
1
].
textEdit
.
newText
,
'
index.html
'
);
assert
.
equal
(
suggestions
[
2
].
textEdit
.
newText
,
'
src
'
);
assert
.
equal
(
suggestions
[
0
].
textEdit
.
range
.
start
.
character
,
4
);
assert
.
equal
(
suggestions
[
1
].
textEdit
.
range
.
start
.
character
,
4
);
assert
.
equal
(
suggestions
[
2
].
textEdit
.
range
.
start
.
character
,
4
);
assert
.
equal
(
suggestions
[
0
].
textEdit
.
range
.
end
.
character
,
4
);
assert
.
equal
(
suggestions
[
1
].
textEdit
.
range
.
end
.
character
,
4
);
assert
.
equal
(
suggestions
[
2
].
textEdit
.
range
.
end
.
character
,
4
);
const
range
=
toRange
(
0
,
3
,
5
);
const
expectedReplaceRange
=
toRange
(
0
,
4
,
4
);
const
suggestions
=
providePathSuggestions
(
value
,
range
,
activeFileFsPath
);
assertSuggestions
(
suggestions
,
[
{
textEdit
:
TextEdit
.
replace
(
expectedReplaceRange
,
'
about/
'
)
},
{
textEdit
:
TextEdit
.
replace
(
expectedReplaceRange
,
'
index.html
'
)
},
{
textEdit
:
TextEdit
.
replace
(
expectedReplaceRange
,
'
src/
'
)
},
]);
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录