Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
vscode
提交
f5763050
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,发现更多精彩内容 >>
提交
f5763050
编写于
1月 26, 2018
作者:
J
Johannes Rieken
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
implement different memory strategies, #41060
上级
a3ed7752
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
285 addition
and
119 deletion
+285
-119
src/vs/editor/contrib/suggest/suggestController.ts
src/vs/editor/contrib/suggest/suggestController.ts
+4
-16
src/vs/editor/contrib/suggest/suggestMemory.ts
src/vs/editor/contrib/suggest/suggestMemory.ts
+171
-79
src/vs/editor/contrib/suggest/test/completionModel.test.ts
src/vs/editor/contrib/suggest/test/completionModel.test.ts
+24
-24
src/vs/editor/contrib/suggest/test/suggestMemory.test.ts
src/vs/editor/contrib/suggest/test/suggestMemory.test.ts
+86
-0
未找到文件。
src/vs/editor/contrib/suggest/suggestController.ts
浏览文件 @
f5763050
...
...
@@ -95,7 +95,7 @@ export class SuggestController implements IEditorContribution {
@
IInstantiationService
private
_instantiationService
:
IInstantiationService
,
)
{
this
.
_model
=
new
SuggestModel
(
this
.
_editor
);
this
.
_memory
=
_instantiationService
.
createInstance
(
SuggestMemories
);
this
.
_memory
=
_instantiationService
.
createInstance
(
SuggestMemories
,
'
shy
'
);
this
.
_toDispose
.
push
(
this
.
_model
.
onDidTrigger
(
e
=>
{
if
(
!
this
.
_widget
)
{
...
...
@@ -103,21 +103,13 @@ export class SuggestController implements IEditorContribution {
}
this
.
_widget
.
showTriggered
(
e
.
auto
);
}));
let
lastSelectedItem
:
ICompletionItem
;
this
.
_toDispose
.
push
(
this
.
_model
.
onDidSuggest
(
e
=>
{
let
index
=
this
.
_memory
.
select
(
this
.
_editor
.
getModel
().
getLanguageIdentifier
(),
e
.
completionModel
.
items
,
lastSelectedItem
);
if
(
index
>=
0
)
{
lastSelectedItem
=
e
.
completionModel
.
items
[
index
];
}
else
{
index
=
0
;
lastSelectedItem
=
undefined
;
}
let
index
=
this
.
_memory
.
select
(
this
.
_editor
.
getModel
(),
this
.
_editor
.
getPosition
(),
e
.
completionModel
.
items
);
this
.
_widget
.
showSuggestions
(
e
.
completionModel
,
index
,
e
.
isFrozen
,
e
.
auto
);
}));
this
.
_toDispose
.
push
(
this
.
_model
.
onDidCancel
(
e
=>
{
if
(
this
.
_widget
&&
!
e
.
retrigger
)
{
this
.
_widget
.
hideWidget
();
lastSelectedItem
=
undefined
;
}
}));
...
...
@@ -209,12 +201,8 @@ export class SuggestController implements IEditorContribution {
this
.
_editor
.
pushUndoStop
();
}
// remember this suggestion for future invocations
// when it wasn't the first suggestion but from the group
// of top suggestions (cons -> const, console, constructor)
if
(
event
.
model
.
items
[
0
].
score
===
event
.
item
.
score
)
{
this
.
_memory
.
remember
(
this
.
_editor
.
getModel
().
getLanguageIdentifier
(),
event
.
item
);
}
// keep item in memory
this
.
_memory
.
memorize
(
this
.
_editor
.
getModel
(),
this
.
_editor
.
getPosition
(),
event
.
item
);
let
{
insertText
}
=
suggestion
;
if
(
suggestion
.
snippetType
!==
'
textmate
'
)
{
...
...
src/vs/editor/contrib/suggest/suggestMemory.ts
浏览文件 @
f5763050
...
...
@@ -5,119 +5,211 @@
'
use strict
'
;
import
{
ICompletionItem
}
from
'
vs/editor/contrib/suggest/completionModel
'
;
import
{
LRUCache
}
from
'
vs/base/common/map
'
;
import
{
LanguageIdentifier
}
from
'
vs/editor/common/modes
'
;
import
{
LRUCache
,
TernarySearchTree
}
from
'
vs/base/common/map
'
;
import
{
IStorageService
,
StorageScope
}
from
'
vs/platform/storage/common/storage
'
;
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
IPosition
}
from
'
vs/editor/common/core/position
'
;
import
{
RunOnceScheduler
}
from
'
vs/base/common/async
'
;
export
class
SuggestMemories
{
export
abstract
class
Memory
{
private
readonly
_storagePrefix
=
'
suggest/memories
'
;
private
readonly
_data
=
new
Map
<
string
,
SuggestMemory
>
();
abstract
memorize
(
model
:
ITextModel
,
pos
:
IPosition
,
item
:
ICompletionItem
):
void
;
constructor
(
@
IStorageService
private
_storageService
:
IStorageService
)
{
abstract
select
(
model
:
ITextModel
,
pos
:
IPosition
,
items
:
ICompletionItem
[]):
number
;
abstract
toJSON
():
object
;
abstract
fromJSON
(
data
:
object
):
void
;
}
export
class
NoMemory
extends
Memory
{
memorize
(
model
:
ITextModel
,
pos
:
IPosition
,
item
:
ICompletionItem
):
void
{
// no-op
}
select
(
model
:
ITextModel
,
pos
:
IPosition
,
items
:
ICompletionItem
[]):
number
{
return
0
;
}
toJSON
()
{
return
undefined
;
}
fromJSON
()
{
//
}
}
remember
({
language
}:
LanguageIdentifier
,
item
:
ICompletionItem
):
void
{
let
memory
=
this
.
_data
.
get
(
language
);
if
(
!
memory
)
{
memory
=
new
SuggestMemory
();
this
.
_data
.
set
(
language
,
memory
);
}
memory
.
remember
(
item
);
this
.
_storageService
.
store
(
`
${
this
.
_storagePrefix
}
/
${
language
}
`
,
JSON
.
stringify
(
memory
),
StorageScope
.
WORKSPACE
);
}
select
({
language
}:
LanguageIdentifier
,
items
:
ICompletionItem
[],
last
:
ICompletionItem
):
number
{
let
memory
=
this
.
_data
.
get
(
language
);
if
(
!
memory
)
{
const
key
:
string
=
`
${
this
.
_storagePrefix
}
/
${
language
}
`
;
const
raw
=
this
.
_storageService
.
get
(
key
,
StorageScope
.
WORKSPACE
);
if
(
raw
)
{
try
{
const
tuples
=
<
[
string
,
MemoryItem
][]
>
JSON
.
parse
(
raw
);
memory
=
new
SuggestMemory
(
tuples
);
last
=
undefined
;
this
.
_data
.
set
(
language
,
memory
);
}
catch
(
e
)
{
this
.
_storageService
.
remove
(
key
,
StorageScope
.
WORKSPACE
);
export
interface
MemItem
{
type
:
string
;
insertText
:
string
;
touch
:
number
;
}
export
class
ShyMemory
extends
Memory
{
private
_cache
=
new
LRUCache
<
string
,
MemItem
>
(
300
,
.
66
);
private
_seq
=
0
;
memorize
(
model
:
ITextModel
,
pos
:
IPosition
,
item
:
ICompletionItem
):
void
{
const
{
label
}
=
item
.
suggestion
;
const
key
=
`
${
model
.
getLanguageIdentifier
().
id
}
/
${
label
}
`
;
this
.
_cache
.
set
(
key
,
{
touch
:
this
.
_seq
++
,
type
:
item
.
suggestion
.
type
,
insertText
:
undefined
});
}
select
(
model
:
ITextModel
,
pos
:
IPosition
,
items
:
ICompletionItem
[]):
number
{
// in order of completions, select the first
// that has been used in the past
let
{
word
}
=
model
.
getWordUntilPosition
(
pos
);
let
res
=
0
;
let
seq
=
-
1
;
if
(
word
.
length
===
0
)
{
for
(
let
i
=
0
;
i
<
items
.
length
;
i
++
)
{
const
{
suggestion
}
=
items
[
i
];
const
key
=
`
${
model
.
getLanguageIdentifier
().
id
}
/
${
suggestion
.
label
}
`
;
const
item
=
this
.
_cache
.
get
(
key
);
if
(
item
&&
item
.
touch
>
seq
&&
item
.
type
===
suggestion
.
type
)
{
seq
=
item
.
touch
;
res
=
i
;
}
}
}
if
(
memory
)
{
return
memory
.
select
(
items
,
last
);
}
else
{
return
-
1
;
return
res
;
}
toJSON
():
object
{
let
data
:
[
string
,
MemItem
][]
=
[];
this
.
_cache
.
forEach
((
value
,
key
)
=>
{
data
.
push
([
key
,
value
]);
});
return
data
;
}
fromJSON
(
data
:
[
string
,
MemItem
][]):
void
{
this
.
_cache
.
clear
();
let
seq
=
0
;
for
(
const
[
key
,
value
]
of
data
)
{
value
.
touch
=
seq
;
this
.
_cache
.
set
(
key
,
value
);
}
this
.
_seq
=
this
.
_cache
.
size
;
}
}
export
interface
MemoryItem
{
type
:
string
;
insertText
:
string
;
}
export
class
PrefixMemory
extends
Memory
{
export
class
SuggestMemory
{
private
_trie
=
TernarySearchTree
.
forStrings
<
MemItem
>
();
private
_seq
=
0
;
private
readonly
_memory
=
new
LRUCache
<
string
,
MemoryItem
>
(
400
,
0.75
);
memorize
(
model
:
ITextModel
,
pos
:
IPosition
,
item
:
ICompletionItem
):
void
{
const
{
word
}
=
model
.
getWordUntilPosition
(
pos
);
const
key
=
`
${
model
.
getLanguageIdentifier
().
id
}
/
${
word
}
`
;
this
.
_trie
.
set
(
key
,
{
type
:
item
.
suggestion
.
type
,
insertText
:
item
.
suggestion
.
insertText
,
touch
:
this
.
_seq
++
});
}
constructor
(
tuples
?:
[
string
,
MemoryItem
][])
{
if
(
tuples
)
{
for
(
const
[
word
,
item
]
of
tuples
)
{
this
.
_memory
.
set
(
word
,
item
);
select
(
model
:
ITextModel
,
pos
:
IPosition
,
items
:
ICompletionItem
[]):
number
{
let
{
word
}
=
model
.
getWordUntilPosition
(
pos
);
if
(
!
word
)
{
return
0
;
}
let
key
=
`
${
model
.
getLanguageIdentifier
().
id
}
/
${
word
}
`
;
let
item
=
this
.
_trie
.
get
(
key
);
if
(
!
item
)
{
item
=
this
.
_trie
.
findSubstr
(
key
);
}
if
(
item
)
{
for
(
let
i
=
0
;
i
<
items
.
length
;
i
++
)
{
let
{
type
,
insertText
}
=
items
[
i
].
suggestion
;
if
(
type
===
item
.
type
&&
insertText
===
item
.
insertText
)
{
return
i
;
}
}
}
return
0
;
}
remember
(
item
:
ICompletionItem
):
void
{
if
(
item
.
word
)
{
this
.
_memory
.
set
(
item
.
word
,
{
insertText
:
item
.
suggestion
.
insertText
,
type
:
item
.
suggestion
.
type
});
toJSON
():
object
{
let
entries
:
[
string
,
MemItem
][]
=
[];
this
.
_trie
.
forEach
((
value
,
key
)
=>
entries
.
push
([
key
,
value
]));
// sort by last recently used (touch), then
// take the top 200 item and normalize their
// touch
entries
.
sort
((
a
,
b
)
=>
-
(
a
[
1
].
touch
-
b
[
1
].
touch
))
.
slice
(
0
,
200
)
.
forEach
((
value
,
i
)
=>
value
[
1
].
touch
=
i
);
return
entries
;
}
fromJSON
(
data
:
[
string
,
MemItem
][]):
void
{
this
.
_trie
.
clear
();
if
(
data
.
length
>
0
)
{
this
.
_seq
=
data
[
0
][
1
].
touch
+
1
;
for
(
const
[
key
,
value
]
of
data
)
{
this
.
_trie
.
set
(
key
,
value
);
}
}
}
}
select
(
items
:
ICompletionItem
[],
last
:
ICompletionItem
):
number
{
export
type
MemMode
=
'
off
'
|
'
shy
'
|
'
always
'
;
if
(
items
.
length
===
0
)
{
return
-
1
;
}
export
class
SuggestMemories
{
const
topScore
=
items
[
0
].
score
;
private
readonly
_storagePrefix
=
'
suggest/memories
'
;
for
(
let
i
=
0
;
i
<
items
.
length
;
i
++
)
{
private
_mode
:
MemMode
;
private
_strategy
:
Memory
;
private
_persistSoon
:
RunOnceScheduler
;
if
(
topScore
!==
items
[
i
].
score
)
{
// we only take a look at the bucket
// of top matches, hence we return
// as soon as we see an item that
// hasn't the top score anymore
return
-
1
;
}
constructor
(
mode
:
MemMode
,
@
IStorageService
private
_storageService
:
IStorageService
)
{
this
.
_persistSoon
=
new
RunOnceScheduler
(()
=>
this
.
_flush
(),
3000
);
this
.
setMode
(
mode
)
;
}
if
(
items
[
i
]
===
last
)
{
// prefer the last selected item when
// there is one
return
i
;
}
if
(
items
[
i
].
word
)
{
const
item
=
this
.
_memory
.
get
(
items
[
i
].
word
);
if
(
this
.
_matches
(
item
,
items
[
i
]))
{
return
i
;
}
}
setMode
(
mode
:
MemMode
):
void
{
if
(
this
.
_mode
===
mode
)
{
return
;
}
return
-
1
;
this
.
_mode
=
mode
;
this
.
_strategy
=
mode
===
'
always
'
?
new
PrefixMemory
()
:
mode
===
'
shy
'
?
new
ShyMemory
()
:
new
NoMemory
();
try
{
const
raw
=
this
.
_storageService
.
get
(
`
${
this
.
_storagePrefix
}
/
${
this
.
_mode
}
`
,
StorageScope
.
WORKSPACE
);
this
.
_strategy
.
fromJSON
(
JSON
.
parse
(
raw
));
}
catch
(
e
)
{
// things can go wrong with JSON...
}
}
memorize
(
model
:
ITextModel
,
pos
:
IPosition
,
item
:
ICompletionItem
):
void
{
this
.
_strategy
.
memorize
(
model
,
pos
,
item
);
this
.
_persistSoon
.
schedule
();
}
private
_matches
(
item
:
MemoryItem
,
candidate
:
ICompletionItem
):
boolean
{
return
item
&&
item
.
insertText
===
candidate
.
suggestion
.
insertText
&&
item
.
type
===
candidate
.
suggestion
.
type
;
select
(
model
:
ITextModel
,
pos
:
IPosition
,
items
:
ICompletionItem
[]):
number
{
return
this
.
_strategy
.
select
(
model
,
pos
,
items
)
;
}
toJSON
():
[
string
,
MemoryItem
][]
{
const
tuples
:
[
string
,
MemoryItem
][]
=
[];
this
.
_memory
.
forEach
((
value
,
key
)
=>
tuples
.
push
([
key
,
value
]));
return
tuples
;
private
_flush
()
{
const
raw
=
JSON
.
stringify
(
this
.
_strategy
);
this
.
_storageService
.
store
(
`
${
this
.
_storagePrefix
}
/
${
this
.
_mode
}
`
,
raw
,
StorageScope
.
WORKSPACE
);
}
}
src/vs/editor/contrib/suggest/test/completionModel.test.ts
浏览文件 @
f5763050
...
...
@@ -11,37 +11,37 @@ import { CompletionModel } from 'vs/editor/contrib/suggest/completionModel';
import
{
IPosition
}
from
'
vs/editor/common/core/position
'
;
import
{
TPromise
}
from
'
vs/base/common/winjs.base
'
;
suite
(
'
CompletionModel
'
,
function
()
{
function
createSuggestItem
(
label
:
string
,
overwriteBefore
:
number
,
type
:
SuggestionType
=
'
property
'
,
incomplete
:
boolean
=
false
,
position
:
IPosition
=
{
lineNumber
:
1
,
column
:
1
}):
ISuggestionItem
{
export
function
createSuggestItem
(
label
:
string
,
overwriteBefore
:
number
,
type
:
SuggestionType
=
'
property
'
,
incomplete
:
boolean
=
false
,
position
:
IPosition
=
{
lineNumber
:
1
,
column
:
1
}):
ISuggestionItem
{
return
new
class
implements
ISuggestionItem
{
return
new
class
implements
ISuggestionItem
{
position
=
position
;
position
=
position
;
suggestion
:
ISuggestion
=
{
label
,
overwriteBefore
,
insertText
:
label
,
type
};
container
:
ISuggestResult
=
{
incomplete
,
suggestions
:
[
this
.
suggestion
]
};
suggestion
:
ISuggestion
=
{
label
,
overwriteBefore
,
insertText
:
label
,
type
};
support
:
ISuggestSupport
=
{
provideCompletionItems
():
any
{
return
;
}
};
container
:
ISuggestResult
=
{
incomplete
,
suggestions
:
[
this
.
suggestion
]
};
resolve
():
TPromise
<
void
>
{
return
null
;
support
:
ISuggestSupport
=
{
provideCompletionItems
():
any
{
return
;
}
};
}
resolve
():
TPromise
<
void
>
{
return
null
;
}
};
}
suite
(
'
CompletionModel
'
,
function
()
{
let
model
:
CompletionModel
;
...
...
src/vs/editor/contrib/suggest/test/suggestMemory.test.ts
0 → 100644
浏览文件 @
f5763050
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
{
ShyMemory
,
NoMemory
,
PrefixMemory
}
from
'
vs/editor/contrib/suggest/suggestMemory
'
;
import
{
ITextModel
}
from
'
vs/editor/common/model
'
;
import
{
TextModel
}
from
'
vs/editor/common/model/textModel
'
;
import
{
ICompletionItem
}
from
'
vs/editor/contrib/suggest/completionModel
'
;
import
{
createSuggestItem
}
from
'
vs/editor/contrib/suggest/test/completionModel.test
'
;
import
{
IPosition
}
from
'
vs/editor/common/core/position
'
;
suite
(
'
SuggestMemories
'
,
function
()
{
let
pos
:
IPosition
;
let
buffer
:
ITextModel
;
let
items
:
ICompletionItem
[];
setup
(
function
()
{
pos
=
{
lineNumber
:
1
,
column
:
1
};
buffer
=
TextModel
.
createFromString
(
'
This is some text
'
);
items
=
[
createSuggestItem
(
'
foo
'
,
0
),
createSuggestItem
(
'
bar
'
,
0
)
];
});
test
(
'
NoMemory
'
,
function
()
{
const
mem
=
new
NoMemory
();
assert
.
equal
(
mem
.
select
(
buffer
,
pos
,
items
),
0
);
assert
.
equal
(
mem
.
select
(
buffer
,
pos
,
[]),
0
);
mem
.
memorize
(
buffer
,
pos
,
items
[
0
]);
mem
.
memorize
(
buffer
,
pos
,
null
);
});
test
(
'
ShyMemories
'
,
function
()
{
const
mem
=
new
ShyMemory
();
mem
.
memorize
(
buffer
,
pos
,
items
[
1
]);
assert
.
equal
(
mem
.
select
(
buffer
,
pos
,
items
),
1
);
assert
.
equal
(
mem
.
select
(
buffer
,
{
lineNumber
:
1
,
column
:
3
},
items
),
0
);
mem
.
memorize
(
buffer
,
pos
,
items
[
0
]);
assert
.
equal
(
mem
.
select
(
buffer
,
pos
,
items
),
0
);
assert
.
equal
(
mem
.
select
(
buffer
,
pos
,
[
createSuggestItem
(
'
new
'
,
0
),
createSuggestItem
(
'
bar
'
,
0
)
]),
1
);
assert
.
equal
(
mem
.
select
(
buffer
,
pos
,
[
createSuggestItem
(
'
new1
'
,
0
),
createSuggestItem
(
'
new2
'
,
0
)
]),
0
);
});
test
(
'
PrefixMemory
'
,
function
()
{
const
mem
=
new
PrefixMemory
();
buffer
.
setValue
(
'
constructor
'
);
const
item0
=
createSuggestItem
(
'
console
'
,
0
);
const
item1
=
createSuggestItem
(
'
const
'
,
0
);
const
item2
=
createSuggestItem
(
'
constructor
'
,
0
);
const
item3
=
createSuggestItem
(
'
constant
'
,
0
);
const
items
=
[
item0
,
item1
,
item2
,
item3
];
mem
.
memorize
(
buffer
,
{
lineNumber
:
1
,
column
:
2
},
item1
);
// c -> const
mem
.
memorize
(
buffer
,
{
lineNumber
:
1
,
column
:
3
},
item0
);
// co -> console
mem
.
memorize
(
buffer
,
{
lineNumber
:
1
,
column
:
4
},
item2
);
// con -> constructor
assert
.
equal
(
mem
.
select
(
buffer
,
{
lineNumber
:
1
,
column
:
1
},
items
),
0
);
assert
.
equal
(
mem
.
select
(
buffer
,
{
lineNumber
:
1
,
column
:
2
},
items
),
1
);
assert
.
equal
(
mem
.
select
(
buffer
,
{
lineNumber
:
1
,
column
:
3
},
items
),
0
);
assert
.
equal
(
mem
.
select
(
buffer
,
{
lineNumber
:
1
,
column
:
4
},
items
),
2
);
assert
.
equal
(
mem
.
select
(
buffer
,
{
lineNumber
:
1
,
column
:
7
},
items
),
2
);
// find substr
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录