Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
6d788bff
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,发现更多精彩内容 >>
提交
6d788bff
编写于
9月 14, 2016
作者:
M
Martin Aeschlimann
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[html] bring back provider configuration settings
上级
cf1596c6
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
61 addition
and
130 deletion
+61
-130
extensions/html/server/src/htmlServerMain.ts
extensions/html/server/src/htmlServerMain.ts
+8
-54
extensions/html/server/src/service/htmlLanguageService.ts
extensions/html/server/src/service/htmlLanguageService.ts
+3
-8
extensions/html/server/src/service/parser/htmlTags.ts
extensions/html/server/src/service/parser/htmlTags.ts
+8
-0
extensions/html/server/src/service/services/htmlCompletion.ts
...nsions/html/server/src/service/services/htmlCompletion.ts
+11
-10
extensions/html/server/src/service/services/htmlHighlighting.ts
...ions/html/server/src/service/services/htmlHighlighting.ts
+0
-1
extensions/html/server/src/service/test/completion.test.ts
extensions/html/server/src/service/test/completion.test.ts
+31
-57
未找到文件。
extensions/html/server/src/htmlServerMain.ts
浏览文件 @
6d788bff
...
...
@@ -9,7 +9,7 @@ import {
TextDocuments
,
TextDocument
,
InitializeParams
,
InitializeResult
}
from
'
vscode-languageserver
'
;
import
{
HTMLDocument
,
LanguageSettings
,
getLanguageService
}
from
'
./service/htmlLanguageService
'
;
import
{
HTMLDocument
,
getLanguageService
,
CompletionConfiguration
,
HTMLFormatConfiguration
}
from
'
./service/htmlLanguageService
'
;
import
*
as
nls
from
'
vscode-nls
'
;
nls
.
config
(
process
.
env
[
'
VSCODE_NLS_CONFIG
'
]);
...
...
@@ -51,66 +51,19 @@ interface Settings {
html
:
LanguageSettings
;
}
interface
LanguageSettings
{
suggest
:
CompletionConfiguration
;
format
:
HTMLFormatConfiguration
;
}
let
languageSettings
:
LanguageSettings
;
// The settings have changed. Is send on server activation as well.
connection
.
onDidChangeConfiguration
((
change
)
=>
{
var
settings
=
<
Settings
>
change
.
settings
;
languageSettings
=
settings
.
html
;
updateConfiguration
();
});
function
updateConfiguration
()
{
languageService
.
configure
(
languageSettings
);
// Revalidate any open text documents
documents
.
all
().
forEach
(
triggerValidation
);
}
// The content of a text document has changed. This event is emitted
// when the text document first opened or when its content has changed.
documents
.
onDidChangeContent
((
change
)
=>
{
triggerValidation
(
change
.
document
);
});
// a document has closed: clear all diagnostics
documents
.
onDidClose
(
event
=>
{
cleanPendingValidation
(
event
.
document
);
connection
.
sendDiagnostics
({
uri
:
event
.
document
.
uri
,
diagnostics
:
[]
});
});
let
pendingValidationRequests
:
{[
uri
:
string
]:
NodeJS
.
Timer
}
=
{};
const
validationDelayMs
=
200
;
function
cleanPendingValidation
(
textDocument
:
TextDocument
):
void
{
let
request
=
pendingValidationRequests
[
textDocument
.
uri
];
if
(
request
)
{
clearTimeout
(
request
);
delete
pendingValidationRequests
[
textDocument
.
uri
];
}
}
function
triggerValidation
(
textDocument
:
TextDocument
):
void
{
cleanPendingValidation
(
textDocument
);
pendingValidationRequests
[
textDocument
.
uri
]
=
setTimeout
(()
=>
{
delete
pendingValidationRequests
[
textDocument
.
uri
];
validateTextDocument
(
textDocument
);
},
validationDelayMs
);
}
function
validateTextDocument
(
textDocument
:
TextDocument
):
void
{
if
(
textDocument
.
getText
().
length
===
0
)
{
// ignore empty documents
connection
.
sendDiagnostics
({
uri
:
textDocument
.
uri
,
diagnostics
:
[]
});
return
;
}
let
htmlDocument
=
getHTMLDocument
(
textDocument
);
let
diagnostics
=
languageService
.
doValidation
(
textDocument
,
htmlDocument
);
// Send the computed diagnostics to VSCode.
connection
.
sendDiagnostics
({
uri
:
textDocument
.
uri
,
diagnostics
});
}
function
getHTMLDocument
(
document
:
TextDocument
):
HTMLDocument
{
return
languageService
.
parseHTMLDocument
(
document
);
}
...
...
@@ -118,7 +71,8 @@ function getHTMLDocument(document: TextDocument): HTMLDocument {
connection
.
onCompletion
(
textDocumentPosition
=>
{
let
document
=
documents
.
get
(
textDocumentPosition
.
textDocument
.
uri
);
let
htmlDocument
=
getHTMLDocument
(
document
);
return
languageService
.
doComplete
(
document
,
textDocumentPosition
.
position
,
htmlDocument
);
let
options
=
languageSettings
&&
languageSettings
.
suggest
;
return
languageService
.
doComplete
(
document
,
textDocumentPosition
.
position
,
htmlDocument
,
options
);
});
connection
.
onDocumentHighlight
(
documentHighlightParams
=>
{
...
...
extensions/html/server/src/service/htmlLanguageService.ts
浏览文件 @
6d788bff
...
...
@@ -41,27 +41,22 @@ export interface HTMLFormatConfiguration {
extraLiners
:
string
;
}
export
interface
LanguageSettings
{
validate
:
boolean
;
format
:
HTMLFormatConfiguration
;
export
interface
CompletionConfiguration
{
[
provider
:
string
]:
boolean
;
}
export
declare
type
HTMLDocument
=
{};
export
interface
LanguageService
{
configure
(
settings
:
LanguageSettings
):
void
;
parseHTMLDocument
(
document
:
TextDocument
):
HTMLDocument
;
doValidation
(
document
:
TextDocument
,
htmlDocument
:
HTMLDocument
):
Diagnostic
[];
findDocumentHighlights
(
document
:
TextDocument
,
position
:
Position
,
htmlDocument
:
HTMLDocument
):
DocumentHighlight
[];
doComplete
(
document
:
TextDocument
,
position
:
Position
,
htmlDocument
:
HTMLDocument
):
CompletionList
;
doComplete
(
document
:
TextDocument
,
position
:
Position
,
htmlDocument
:
HTMLDocument
,
options
?:
CompletionConfiguration
):
CompletionList
;
format
(
document
:
TextDocument
,
range
:
Range
,
options
:
HTMLFormatConfiguration
):
TextEdit
[];
provideLinks
(
document
:
TextDocument
,
workspacePath
:
string
):
DocumentLink
[];
}
export
function
getLanguageService
()
:
LanguageService
{
return
{
doValidation
:
(
document
,
htmlDocument
)
=>
{
return
[];
},
configure
:
(
settings
)
=>
{},
parseHTMLDocument
:
(
document
)
=>
parse
(
document
.
getText
()),
doComplete
,
format
,
...
...
extensions/html/server/src/service/parser/htmlTags.ts
浏览文件 @
6d788bff
...
...
@@ -50,6 +50,8 @@ export function isSameTag(t1: string, t2: string) : boolean {
}
export
interface
IHTMLTagProvider
{
getId
():
string
;
isApplicable
(
languageId
:
string
);
collectTags
(
collector
:
(
tag
:
string
,
label
:
string
)
=>
void
):
void
;
collectAttributes
(
tag
:
string
,
collector
:
(
attribute
:
string
,
type
:
string
)
=>
void
):
void
;
collectValues
(
tag
:
string
,
attribute
:
string
,
collector
:
(
value
:
string
)
=>
void
):
void
;
...
...
@@ -481,6 +483,8 @@ export function getHTML5TagProvider(): IHTMLTagProvider {
};
return
{
getId
:
()
=>
'
html5
'
,
isApplicable
:
()
=>
true
,
collectTags
:
(
collector
:
(
tag
:
string
,
label
:
string
)
=>
void
)
=>
collectTagsDefault
(
collector
,
HTML_TAGS
),
collectAttributes
:
(
tag
:
string
,
collector
:
(
attribute
:
string
,
type
:
string
)
=>
void
)
=>
{
collectAttributesDefault
(
tag
,
collector
,
HTML_TAGS
,
globalAttributes
);
...
...
@@ -508,6 +512,8 @@ export function getAngularTagProvider(): IHTMLTagProvider {
];
return
{
getId
:
()
=>
'
angular1
'
,
isApplicable
:
(
languageId
)
=>
languageId
===
'
html
'
,
collectTags
:
(
collector
:
(
tag
:
string
)
=>
void
)
=>
{
// no extra tags
},
...
...
@@ -555,6 +561,8 @@ export function getIonicTagProvider(): IHTMLTagProvider {
};
return
{
getId
:
()
=>
'
ionic
'
,
isApplicable
:
(
languageId
)
=>
languageId
===
'
html
'
,
collectTags
:
(
collector
:
(
tag
:
string
,
label
:
string
)
=>
void
)
=>
collectTagsDefault
(
collector
,
IONIC_TAGS
),
collectAttributes
:
(
tag
:
string
,
collector
:
(
attribute
:
string
,
type
:
string
)
=>
void
)
=>
{
collectAttributesDefault
(
tag
,
collector
,
IONIC_TAGS
,
globalAttributes
);
...
...
extensions/html/server/src/service/services/htmlCompletion.ts
浏览文件 @
6d788bff
...
...
@@ -7,21 +7,22 @@
import
{
TextDocument
,
Position
,
CompletionList
,
CompletionItemKind
,
Range
}
from
'
vscode-languageserver-types
'
;
import
{
HTMLDocument
}
from
'
../parser/htmlParser
'
;
import
{
TokenType
,
createScanner
,
ScannerState
}
from
'
../parser/htmlScanner
'
;
import
{
IHTMLTagProvider
,
getHTML5TagProvider
,
getAngularTagProvider
,
getIonicTagProvider
}
from
'
../parser/htmlTags
'
;
import
{
startsWith
}
from
'
../utils/strings
'
;
import
{
getHTML5TagProvider
,
getAngularTagProvider
,
getIonicTagProvider
}
from
'
../parser/htmlTags
'
;
import
{
CompletionConfiguration
}
from
'
../htmlLanguageService
'
;
let
tagProviders
:
IHTMLTagProvider
[]
=
[];
tagProviders
.
push
(
getHTML5TagProvider
());
tagProviders
.
push
(
getAngularTagProvider
());
tagProviders
.
push
(
getIonicTagProvider
());
let
allTagProviders
=
[
getHTML5TagProvider
(),
getAngularTagProvider
(),
getIonicTagProvider
()
];
export
function
doComplete
(
document
:
TextDocument
,
position
:
Position
,
doc
:
HTMLDocument
):
CompletionList
{
export
function
doComplete
(
document
:
TextDocument
,
position
:
Position
,
doc
:
HTMLDocument
,
settings
?:
CompletionConfiguration
):
CompletionList
{
let
result
:
CompletionList
=
{
isIncomplete
:
false
,
items
:
[]
};
let
tagProviders
=
allTagProviders
.
filter
(
p
=>
p
.
isApplicable
(
document
.
languageId
)
&&
(
!
settings
||
!!
settings
[
p
.
getId
()]));
let
offset
=
document
.
offsetAt
(
position
);
let
node
=
doc
.
findNodeBefore
(
offset
);
...
...
@@ -56,8 +57,8 @@ export function doComplete(document: TextDocument, position: Position, doc: HTML
function
collectCloseTagSuggestions
(
afterOpenBracket
:
number
,
matchingOnly
:
boolean
)
:
CompletionList
{
let
range
=
getReplaceRange
(
afterOpenBracket
);
let
contentAfter
=
document
.
getText
().
substr
(
offset
,
1
);
let
closeTag
=
isWhiteSpace
(
contentAfter
)
||
startsWith
(
contentAfter
,
'
<
'
)
?
'
>
'
:
'
'
;
let
contentAfter
=
document
.
getText
().
substr
(
offset
);
let
closeTag
=
contentAfter
.
match
(
/^
\s
*>/
)
?
''
:
'
>
'
;
let
curr
=
node
;
while
(
curr
)
{
let
tag
=
curr
.
tag
;
...
...
extensions/html/server/src/service/services/htmlHighlighting.ts
浏览文件 @
6d788bff
...
...
@@ -25,7 +25,6 @@ export function findDocumentHighlights(document: TextDocument, position: Positio
result
.
push
({
kind
:
DocumentHighlightKind
.
Read
,
range
:
endTagRange
});
}
}
console
.
log
(
'
foo
'
+
result
.
length
);
return
result
;
}
...
...
extensions/html/server/src/service/test/completion.test.ts
浏览文件 @
6d788bff
...
...
@@ -17,6 +17,7 @@ export interface ItemDescription {
insertText
?:
string
;
overwriteBefore
?:
number
;
resultText
?:
string
;
notAvailable
?:
boolean
;
}
function
asPromise
<
T
>
(
result
:
T
):
Promise
<
T
>
{
...
...
@@ -27,6 +28,11 @@ export let assertCompletion = function (completions: CompletionList, expected: I
let
matches
=
completions
.
items
.
filter
(
completion
=>
{
return
completion
.
label
===
expected
.
label
;
});
if
(
expected
.
notAvailable
)
{
assert
.
equal
(
matches
.
length
,
0
,
expected
.
label
+
"
should not existing is results
"
);
return
;
}
assert
.
equal
(
matches
.
length
,
1
,
expected
.
label
+
"
should only existing once: Actual:
"
+
completions
.
items
.
map
(
c
=>
c
.
label
).
join
(
'
,
'
));
if
(
expected
.
documentation
)
{
assert
.
equal
(
matches
[
0
].
documentation
,
expected
.
documentation
);
...
...
@@ -52,7 +58,7 @@ export let assertCompletion = function (completions: CompletionList, expected: I
}
};
let
testCompletionFor
=
function
(
value
:
string
,
expected
:
{
count
?:
number
,
items
?:
ItemDescription
[]
}):
Thenable
<
void
>
{
let
testCompletionFor
=
function
(
value
:
string
,
expected
:
{
count
?:
number
,
items
?:
ItemDescription
[]
}
,
settings
?
:
htmlLanguageService
.
CompletionConfiguration
):
Thenable
<
void
>
{
let
offset
=
value
.
indexOf
(
'
|
'
);
value
=
value
.
substr
(
0
,
offset
)
+
value
.
substr
(
offset
+
1
);
...
...
@@ -61,7 +67,7 @@ let testCompletionFor = function (value: string, expected: { count?: number, ite
let
document
=
TextDocument
.
create
(
'
test://test/test.html
'
,
'
html
'
,
0
,
value
);
let
position
=
document
.
positionAt
(
offset
);
let
htmlDoc
=
ls
.
parseHTMLDocument
(
document
);
return
asPromise
(
ls
.
doComplete
(
document
,
position
,
htmlDoc
)).
then
(
list
=>
{
return
asPromise
(
ls
.
doComplete
(
document
,
position
,
htmlDoc
,
settings
)).
then
(
list
=>
{
try
{
if
(
expected
.
count
)
{
assert
.
equal
(
list
.
items
,
expected
.
count
);
...
...
@@ -87,7 +93,7 @@ function run(tests: Thenable<void>[], testDone) {
suite
(
'
HTML Completion
'
,
()
=>
{
test
(
'
Intellisens
e
'
,
function
(
testDone
):
any
{
test
(
'
Complet
e
'
,
function
(
testDone
):
any
{
run
([
testCompletionFor
(
'
<|
'
,
{
items
:
[
...
...
@@ -271,7 +277,7 @@ suite('HTML Completion', () => {
suite
(
'
Handlevar Completion
'
,
(
testDone
)
=>
{
run
([
testCompletionFor
(
'
<script id="entry-template" type="text/x-handlebars-template"> | </script>
'
,
{
items
:
[
{
label
:
'
div
'
,
resultText
:
'
<script id="entry-template" type="text/x-handlebars-template"> <div></div> </script>
'
},
...
...
@@ -280,7 +286,7 @@ suite('HTML Completion', () => {
],
testDone
);
});
test
(
'
Intellisens
e aria
'
,
function
(
testDone
):
any
{
test
(
'
Complet
e aria
'
,
function
(
testDone
):
any
{
let
expectedAriaAttributes
=
[
{
label
:
'
aria-activedescendant
'
},
{
label
:
'
aria-atomic
'
},
...
...
@@ -338,7 +344,7 @@ suite('HTML Completion', () => {
],
testDone
);
});
test
(
'
Intellisens
e Angular
'
,
function
(
testDone
):
any
{
test
(
'
Complet
e Angular
'
,
function
(
testDone
):
any
{
run
([
testCompletionFor
(
'
<body |> </body >
'
,
{
items
:
[
...
...
@@ -361,70 +367,38 @@ suite('HTML Completion', () => {
],
testDone
);
});
test
(
'
Intellisens
e Ionic
'
,
function
(
testDone
):
any
{
test
(
'
Complet
e Ionic
'
,
function
(
testDone
):
any
{
run
([
// Try some Ionic tags
testCompletionFor
(
'
<|
'
,
{
items
:
[
{
label
:
'
ion-checkbox
'
,
resultText
:
'
<ion-checkbox
'
},
{
label
:
'
ion-content
'
,
resultText
:
'
<ion-content
'
},
{
label
:
'
ion-nav-title
'
,
resultText
:
'
<ion-nav-title
'
},
]
}),
testCompletionFor
(
'
<ion-re|
'
,
{
items
:
[
{
label
:
'
ion-refresher
'
,
resultText
:
'
<ion-refresher
'
},
{
label
:
'
ion-reorder-button
'
,
resultText
:
'
<ion-reorder-button
'
},
]
}),
// Try some global attributes (1 with value suggestions, 1 without value suggestions, 1 void)
testCompletionFor
(
'
<ion-checkbox |
'
,
{
items
:
[
{
label
:
'
force-refresh-images
'
,
resultText
:
'
<ion-checkbox force-refresh-images="{{}}"
'
},
{
label
:
'
collection-repeat
'
,
resultText
:
'
<ion-checkbox collection-repeat="{{}}"
'
},
{
label
:
'
menu-close
'
,
resultText
:
'
<ion-checkbox menu-close
'
},
]
}),
// Try some tag-specific attributes (1 with value suggestions, 1 void)
testCompletionFor
(
'
<ion-footer-bar |
'
,
{
items
:
[
{
label
:
'
align-title
'
,
resultText
:
'
<ion-footer-bar align-title="{{}}"
'
},
{
label
:
'
keyboard-attach
'
,
resultText
:
'
<ion-footer-bar keyboard-attach
'
},
]
}),
// Try the extended attributes of an existing HTML 5 tag
testCompletionFor
(
'
<a |
'
,
{
items
:
[
{
label
:
'
nav-direction
'
,
resultText
:
'
<a nav-direction="{{}}"
'
},
{
label
:
'
nav-transition
'
,
resultText
:
'
<a nav-transition="{{}}"
'
},
{
label
:
'
href
'
,
resultText
:
'
<a href="{{}}"
'
},
{
label
:
'
hreflang
'
,
resultText
:
'
<a hreflang="{{}}"
'
},
]
}),
// Try value suggestion for a tag-specific attribute
testCompletionFor
(
'
<ion-side-menu side="|
'
,
{
})
],
testDone
);
});
test
(
'
Settings
'
,
function
(
testDone
):
any
{
run
([
testCompletionFor
(
'
<|
'
,
{
items
:
[
{
label
:
'
left
'
,
resultText
:
'
<ion-side-menu side="left"
'
},
{
label
:
'
primary
'
,
resultText
:
'
<ion-side-menu side="primary"
'
},
{
label
:
'
right
'
,
resultText
:
'
<ion-side-menu side="right"
'
},
{
label
:
'
secondary
'
,
resultText
:
'
<ion-side-menu side="secondary"
'
},
{
label
:
'
ion-checkbox
'
},
{
label
:
'
div
'
,
notAvailable
:
true
},
]
}),
// Try a value suggestion for a global attribute
testCompletionFor
(
'
<img force-refresh-images="|
'
,
{
},
{
html5
:
false
,
ionic
:
true
,
angular1
:
false
}),
testCompletionFor
(
'
<|
'
,
{
items
:
[
{
label
:
'
false
'
,
resultText
:
'
<img force-refresh-images="false"
'
},
{
label
:
'
true
'
,
resultText
:
'
<img force-refresh-images="true"
'
},
{
label
:
'
ion-checkbox
'
,
notAvailable
:
true
},
{
label
:
'
div
'
},
]
}),
// Try a value suggestion for an extended attribute of an existing HTML 5 tag
testCompletionFor
(
'
<a nav-transition="|
'
,
{
},
{
html5
:
true
,
ionic
:
false
,
angular1
:
false
}),
testCompletionFor
(
'
<input |> </input >
'
,
{
items
:
[
{
label
:
'
android
'
,
resultText
:
'
<a nav-transition="android"
'
},
{
label
:
'
ios
'
,
resultText
:
'
<a nav-transition="ios"
'
},
{
label
:
'
none
'
,
resultText
:
'
<a nav-transition="none"
'
},
{
label
:
'
ng-model
'
,
notAvailable
:
true
},
{
label
:
'
type
'
},
]
}
)
}
,
{
html5
:
true
,
ionic
:
false
,
angular1
:
false
}),
],
testDone
);
});
})
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录