Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
97f93d29
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,发现更多精彩内容 >>
提交
97f93d29
编写于
4月 05, 2019
作者:
R
Rachel Macfarlane
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Process explorer refactoring
上级
591842cc
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
170 addition
and
85 deletion
+170
-85
src/vs/code/electron-browser/processExplorer/media/collapsed.svg
...code/electron-browser/processExplorer/media/collapsed.svg
+1
-0
src/vs/code/electron-browser/processExplorer/media/expanded.svg
.../code/electron-browser/processExplorer/media/expanded.svg
+1
-0
src/vs/code/electron-browser/processExplorer/media/processExplorer.css
...lectron-browser/processExplorer/media/processExplorer.css
+9
-0
src/vs/code/electron-browser/processExplorer/processExplorerMain.ts
...e/electron-browser/processExplorer/processExplorerMain.ts
+143
-81
src/vs/platform/diagnostics/electron-main/diagnosticsService.ts
.../platform/diagnostics/electron-main/diagnosticsService.ts
+4
-4
src/vs/platform/issue/electron-main/issueService.ts
src/vs/platform/issue/electron-main/issueService.ts
+12
-0
未找到文件。
src/vs/code/electron-browser/processExplorer/media/collapsed.svg
0 → 100755
浏览文件 @
97f93d29
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 16 16"
><path
fill=
"#646465"
d=
"M6 4v8l4-4-4-4zm1 2.414L8.586 8 7 9.586V6.414z"
/></svg>
\ No newline at end of file
src/vs/code/electron-browser/processExplorer/media/expanded.svg
0 → 100755
浏览文件 @
97f93d29
<svg
xmlns=
"http://www.w3.org/2000/svg"
viewBox=
"0 0 16 16"
><path
fill=
"#646465"
d=
"M11 10H5.344L11 4.414V10z"
/></svg>
\ No newline at end of file
src/vs/code/electron-browser/processExplorer/media/processExplorer.css
浏览文件 @
97f93d29
...
...
@@ -88,3 +88,12 @@ td {
tbody
>
tr
:hover
{
background-color
:
#2A2D2E
;
}
.hidden
{
display
:
none
;
}
img
{
width
:
16px
;
margin-right
:
4px
;
}
\ No newline at end of file
src/vs/code/electron-browser/processExplorer/processExplorerMain.ts
浏览文件 @
97f93d29
...
...
@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
import
'
vs/css!./media/processExplorer
'
;
import
{
listProcesses
}
from
'
vs/base/node/ps
'
;
import
{
webFrame
,
ipcRenderer
,
clipboard
}
from
'
electron
'
;
import
{
repeat
}
from
'
vs/base/common/strings
'
;
import
{
totalmem
}
from
'
os
'
;
...
...
@@ -16,31 +15,45 @@ import * as platform from 'vs/base/common/platform';
import
{
IContextMenuItem
}
from
'
vs/base/parts/contextmenu/common/contextmenu
'
;
import
{
popup
}
from
'
vs/base/parts/contextmenu/electron-browser/contextmenu
'
;
import
{
ProcessItem
}
from
'
vs/base/common/processes
'
;
import
{
addDisposableListener
}
from
'
vs/base/browser/dom
'
;
import
{
IDisposable
}
from
'
vs/base/common/lifecycle
'
;
let
processList
:
any
[];
let
mapPidToWindowTitle
=
new
Map
<
number
,
string
>
();
const
DEBUG_FLAGS_PATTERN
=
/
\s
--
(
inspect|debug
)(
-brk|port
)?
=
(\d
+
)?
/
;
const
DEBUG_PORT_PATTERN
=
/
\s
--
(
inspect|debug
)
-port=
(\d
+
)
/
;
const
listeners
:
IDisposable
[]
=
[];
const
collapsedStateCache
:
Map
<
string
,
boolean
>
=
new
Map
<
string
,
boolean
>
();
let
lastRequestTime
:
number
;
interface
FormattedProcessItem
{
cpu
:
string
;
memory
:
string
;
pid
:
string
;
name
:
string
;
formattedName
:
string
;
cmd
:
string
;
}
function
getProcessList
(
rootProcess
:
ProcessItem
)
{
const
processes
:
any
[]
=
[];
function
getProcessList
(
rootProcess
:
ProcessItem
,
isLocal
:
boolean
):
FormattedProcessItem
[]
{
const
processes
:
FormattedProcessItem
[]
=
[];
if
(
rootProcess
)
{
getProcessItem
(
processes
,
rootProcess
,
0
);
getProcessItem
(
processes
,
rootProcess
,
0
,
isLocal
);
}
return
processes
;
}
function
getProcessItem
(
processes
:
any
[],
item
:
ProcessItem
,
indent
:
number
):
void
{
function
getProcessItem
(
processes
:
FormattedProcessItem
[],
item
:
ProcessItem
,
indent
:
number
,
isLocal
:
boolean
):
void
{
const
isRoot
=
(
indent
===
0
);
const
MB
=
1024
*
1024
;
let
name
=
item
.
name
;
if
(
isRoot
)
{
name
=
`
${
product
.
applicationName
}
main`
;
name
=
isLocal
?
`
${
product
.
applicationName
}
main`
:
'
remote agent
'
;
}
if
(
name
===
'
window
'
)
{
...
...
@@ -52,9 +65,9 @@ function getProcessItem(processes: any[], item: ProcessItem, indent: number): vo
const
formattedName
=
isRoot
?
name
:
`
${
repeat
(
'
'
,
indent
)}
${
name
}
`
;
const
memory
=
process
.
platform
===
'
win32
'
?
item
.
mem
:
(
totalmem
()
*
(
item
.
mem
/
100
));
processes
.
push
({
cpu
:
Number
(
item
.
load
.
toFixed
(
0
)
),
memory
:
Number
((
memory
/
MB
).
toFixed
(
0
)
),
pid
:
Number
((
item
.
pid
).
toFixed
(
0
)
),
cpu
:
item
.
load
.
toFixed
(
0
),
memory
:
(
memory
/
MB
).
toFixed
(
0
),
pid
:
item
.
pid
.
toFixed
(
0
),
name
,
formattedName
,
cmd
:
item
.
cmd
...
...
@@ -62,7 +75,7 @@ function getProcessItem(processes: any[], item: ProcessItem, indent: number): vo
// Recurse into children if any
if
(
Array
.
isArray
(
item
.
children
))
{
item
.
children
.
forEach
(
child
=>
getProcessItem
(
processes
,
child
,
indent
+
1
));
item
.
children
.
forEach
(
child
=>
getProcessItem
(
processes
,
child
,
indent
+
1
,
isLocal
));
}
}
...
...
@@ -71,7 +84,7 @@ function isDebuggable(cmd: string): boolean {
return
(
matches
&&
matches
.
length
>=
2
)
||
cmd
.
indexOf
(
'
node
'
)
>=
0
||
cmd
.
indexOf
(
'
node.exe
'
)
>=
0
;
}
function
attachTo
(
item
:
ProcessItem
)
{
function
attachTo
(
item
:
Formatted
ProcessItem
)
{
const
config
:
any
=
{
type
:
'
node
'
,
request
:
'
attach
'
,
...
...
@@ -113,35 +126,57 @@ function getProcessIdWithHighestProperty(processList: any[], propertyName: strin
return
maxProcessId
;
}
function
updateProcessInfo
(
processList
:
any
[]):
void
{
function
updateSectionCollapsedState
(
shouldExpand
:
boolean
,
body
:
HTMLElement
,
twistie
:
HTMLImageElement
,
sectionName
:
string
)
{
if
(
shouldExpand
)
{
body
.
classList
.
remove
(
'
hidden
'
);
collapsedStateCache
.
set
(
sectionName
,
false
);
twistie
.
src
=
'
./media/expanded.svg
'
;
}
else
{
body
.
classList
.
add
(
'
hidden
'
);
collapsedStateCache
.
set
(
sectionName
,
true
);
twistie
.
src
=
'
./media/collapsed.svg
'
;
}
}
function
renderTableSection
(
sectionName
:
string
,
processList
:
FormattedProcessItem
[],
renderManySections
:
boolean
,
sectionIsLocal
:
boolean
):
void
{
const
container
=
document
.
getElementById
(
'
process-list
'
);
if
(
!
container
)
{
return
;
}
container
.
innerHTML
=
''
;
const
highestCPUProcess
=
getProcessIdWithHighestProperty
(
processList
,
'
cpu
'
);
const
highestMemoryProcess
=
getProcessIdWithHighestProperty
(
processList
,
'
memory
'
);
const
tableHead
=
document
.
createElement
(
'
thead
'
);
tableHead
.
innerHTML
=
`<tr>
<th scope="col" class="cpu">
${
localize
(
'
cpu
'
,
"
CPU %
"
)}
</th>
<th scope="col" class="memory">
${
localize
(
'
memory
'
,
"
Memory (MB)
"
)}
</th>
<th scope="col" class="pid">
${
localize
(
'
pid
'
,
"
pid
"
)}
</th>
<th scope="col" class="nameLabel">
${
localize
(
'
name
'
,
"
Name
"
)}
</th>
</tr>`
;
const
body
=
document
.
createElement
(
'
tbody
'
);
if
(
renderManySections
)
{
const
headerRow
=
document
.
createElement
(
'
tr
'
);
const
data
=
document
.
createElement
(
'
td
'
);
data
.
textContent
=
sectionName
;
data
.
colSpan
=
4
;
headerRow
.
appendChild
(
data
);
const
twistie
=
document
.
createElement
(
'
img
'
);
updateSectionCollapsedState
(
!
collapsedStateCache
.
get
(
sectionName
),
body
,
twistie
,
sectionName
);
data
.
prepend
(
twistie
);
const
tableBody
=
document
.
createElement
(
'
tbody
'
);
listeners
.
push
(
addDisposableListener
(
data
,
'
click
'
,
(
e
)
=>
{
const
isHidden
=
body
.
classList
.
contains
(
'
hidden
'
);
updateSectionCollapsedState
(
isHidden
,
body
,
twistie
,
sectionName
);
}));
container
.
appendChild
(
headerRow
);
}
processList
.
forEach
(
p
=>
{
const
row
=
document
.
createElement
(
'
tr
'
);
row
.
id
=
p
.
pid
;
row
.
id
=
p
.
pid
.
toString
()
;
const
cpu
=
document
.
createElement
(
'
td
'
);
p
.
pid
===
highestCPUProcess
?
cpu
.
classList
.
add
(
'
centered
'
,
'
highest
'
)
:
cpu
.
classList
.
add
(
'
centered
'
);
cpu
.
textContent
=
p
.
cpu
;
cpu
.
textContent
=
p
.
cpu
.
toString
()
;
const
memory
=
document
.
createElement
(
'
td
'
);
p
.
pid
===
highestMemoryProcess
...
...
@@ -160,10 +195,41 @@ function updateProcessInfo(processList: any[]): void {
name
.
textContent
=
p
.
formattedName
;
row
.
append
(
cpu
,
memory
,
pid
,
name
);
tableBody
.
appendChild
(
row
);
listeners
.
push
(
addDisposableListener
(
row
,
'
contextmenu
'
,
(
e
)
=>
{
showContextMenu
(
e
,
p
,
sectionIsLocal
);
}));
body
.
appendChild
(
row
);
});
container
.
append
(
tableHead
,
tableBody
);
container
.
appendChild
(
body
);
}
function
updateProcessInfo
(
processLists
:
{
[
key
:
string
]:
ProcessItem
}):
void
{
const
container
=
document
.
getElementById
(
'
process-list
'
);
if
(
!
container
)
{
return
;
}
container
.
innerHTML
=
''
;
listeners
.
forEach
(
l
=>
l
.
dispose
());
const
tableHead
=
document
.
createElement
(
'
thead
'
);
tableHead
.
innerHTML
=
`<tr>
<th scope="col" class="cpu">
${
localize
(
'
cpu
'
,
"
CPU %
"
)}
</th>
<th scope="col" class="memory">
${
localize
(
'
memory
'
,
"
Memory (MB)
"
)}
</th>
<th scope="col" class="pid">
${
localize
(
'
pid
'
,
"
pid
"
)}
</th>
<th scope="col" class="nameLabel">
${
localize
(
'
name
'
,
"
Name
"
)}
</th>
</tr>`
;
container
.
append
(
tableHead
);
const
hasMultipleMachines
=
Object
.
keys
(
processLists
).
length
>
1
;
Object
.
keys
(
processLists
).
forEach
((
key
,
i
)
=>
{
const
isLocal
=
i
===
0
;
renderTableSection
(
key
,
getProcessList
(
processLists
[
key
],
isLocal
),
hasMultipleMachines
,
isLocal
);
});
}
function
applyStyles
(
styles
:
ProcessExplorerStyles
):
void
{
...
...
@@ -171,11 +237,11 @@ function applyStyles(styles: ProcessExplorerStyles): void {
const
content
:
string
[]
=
[];
if
(
styles
.
hoverBackground
)
{
content
.
push
(
`tbody > tr:hover { background-color:
${
styles
.
hoverBackground
}
; }`
);
content
.
push
(
`tbody > tr:hover
, table > tr:hover
{ background-color:
${
styles
.
hoverBackground
}
; }`
);
}
if
(
styles
.
hoverForeground
)
{
content
.
push
(
`tbody > tr:hover{ color:
${
styles
.
hoverForeground
}
; }`
);
content
.
push
(
`tbody > tr:hover
, table > tr:hover
{ color:
${
styles
.
hoverForeground
}
; }`
);
}
if
(
styles
.
highlightForeground
)
{
...
...
@@ -200,13 +266,13 @@ function applyZoom(zoomLevel: number): void {
browser
.
setZoomLevel
(
webFrame
.
getZoomLevel
(),
/*isTrusted*/
false
);
}
function
showContextMenu
(
e
:
MouseEvent
)
{
function
showContextMenu
(
e
:
MouseEvent
,
item
:
FormattedProcessItem
,
isLocal
:
boolean
)
{
e
.
preventDefault
();
const
items
:
IContextMenuItem
[]
=
[];
const
pid
=
Number
(
item
.
pid
);
const
pid
=
parseInt
((
e
.
currentTarget
as
HTMLElement
).
id
);
if
(
pid
&&
typeof
pid
===
'
number
'
)
{
if
(
isLocal
)
{
items
.
push
({
label
:
localize
(
'
killProcess
'
,
"
Kill Process
"
),
click
()
{
...
...
@@ -224,48 +290,37 @@ function showContextMenu(e: MouseEvent) {
items
.
push
({
type
:
'
separator
'
});
}
items
.
push
({
label
:
localize
(
'
copy
'
,
"
Copy
"
),
click
()
{
const
row
=
document
.
getElementById
(
pid
.
toString
());
if
(
row
)
{
clipboard
.
writeText
(
row
.
innerText
);
}
items
.
push
({
label
:
localize
(
'
copy
'
,
"
Copy
"
),
click
()
{
const
row
=
document
.
getElementById
(
pid
.
toString
());
if
(
row
)
{
clipboard
.
writeText
(
row
.
innerText
);
}
});
}
});
items
.
push
({
label
:
localize
(
'
copyAll
'
,
"
Copy All
"
),
click
()
{
const
processList
=
document
.
getElementById
(
'
process-list
'
);
if
(
processList
)
{
clipboard
.
writeText
(
processList
.
innerText
);
}
items
.
push
({
label
:
localize
(
'
copyAll
'
,
"
Copy All
"
),
click
()
{
const
processList
=
document
.
getElementById
(
'
process-list
'
);
if
(
processList
)
{
clipboard
.
writeText
(
processList
.
innerText
);
}
}
});
if
(
item
&&
isLocal
&&
isDebuggable
(
item
.
cmd
))
{
items
.
push
({
type
:
'
separator
'
});
const
item
=
processList
.
filter
(
process
=>
process
.
pid
===
pid
)[
0
];
if
(
item
&&
isDebuggable
(
item
.
cmd
))
{
items
.
push
({
type
:
'
separator
'
});
items
.
push
({
label
:
localize
(
'
debug
'
,
"
Debug
"
),
click
()
{
attachTo
(
item
);
}
});
}
}
else
{
items
.
push
({
label
:
localize
(
'
copyAll
'
,
"
Copy All
"
),
label
:
localize
(
'
debug
'
,
"
Debug
"
),
click
()
{
const
processList
=
document
.
getElementById
(
'
process-list
'
);
if
(
processList
)
{
clipboard
.
writeText
(
processList
.
innerText
);
}
attachTo
(
item
);
}
});
}
...
...
@@ -273,6 +328,22 @@ function showContextMenu(e: MouseEvent) {
popup
(
items
);
}
function
requestProcessList
(
totalWaitTime
:
number
):
void
{
setTimeout
(()
=>
{
const
nextRequestTime
=
Date
.
now
();
const
waited
=
totalWaitTime
+
nextRequestTime
-
lastRequestTime
;
lastRequestTime
=
nextRequestTime
;
// Wait at least a second between requests.
if
(
waited
>
1000
)
{
ipcRenderer
.
send
(
'
windowsInfoRequest
'
);
ipcRenderer
.
send
(
'
vscode:listProcesses
'
);
}
else
{
requestProcessList
(
waited
);
}
},
200
);
}
export
function
startup
(
data
:
ProcessExplorerData
):
void
{
applyStyles
(
data
.
styles
);
applyZoom
(
data
.
zoomLevel
);
...
...
@@ -283,23 +354,14 @@ export function startup(data: ProcessExplorerData): void {
windows
.
forEach
(
window
=>
mapPidToWindowTitle
.
set
(
window
.
pid
,
window
.
title
));
});
setInterval
(()
=>
{
ipcRenderer
.
send
(
'
windowsInfoRequest
'
);
listProcesses
(
data
.
pid
).
then
(
processes
=>
{
processList
=
getProcessList
(
processes
);
updateProcessInfo
(
processList
);
const
tableRows
=
document
.
getElementsByTagName
(
'
tr
'
);
for
(
let
i
=
0
;
i
<
tableRows
.
length
;
i
++
)
{
const
tableRow
=
tableRows
[
i
];
tableRow
.
addEventListener
(
'
contextmenu
'
,
(
e
)
=>
{
showContextMenu
(
e
);
});
}
});
},
1200
);
ipcRenderer
.
on
(
'
vscode:listProcessesResponse
'
,
(
_event
:
Event
,
processRoots
:
{
[
key
:
string
]:
ProcessItem
})
=>
{
updateProcessInfo
(
processRoots
);
requestProcessList
(
0
);
});
lastRequestTime
=
Date
.
now
();
ipcRenderer
.
send
(
'
windowsInfoRequest
'
);
ipcRenderer
.
send
(
'
vscode:listProcesses
'
);
document
.
onkeydown
=
(
e
:
KeyboardEvent
)
=>
{
const
cmdOrCtrlKey
=
platform
.
isMacintosh
?
e
.
metaKey
:
e
.
ctrlKey
;
...
...
src/vs/platform/diagnostics/electron-main/diagnosticsService.ts
浏览文件 @
97f93d29
...
...
@@ -306,13 +306,13 @@ export class DiagnosticsService implements IDiagnosticsService {
output
.
push
(
'
CPU %
\t
Mem MB
\t
PID
\t
Process
'
);
if
(
rootProcess
)
{
this
.
formatProcessItem
(
mapPidToWindowTitle
,
output
,
rootProcess
,
0
);
this
.
formatProcessItem
(
info
.
mainPID
,
mapPidToWindowTitle
,
output
,
rootProcess
,
0
);
}
return
output
.
join
(
'
\n
'
);
}
private
formatProcessItem
(
mapPidToWindowTitle
:
Map
<
number
,
string
>
,
output
:
string
[],
item
:
ProcessItem
,
indent
:
number
):
void
{
private
formatProcessItem
(
ma
inPid
:
number
,
ma
pPidToWindowTitle
:
Map
<
number
,
string
>
,
output
:
string
[],
item
:
ProcessItem
,
indent
:
number
):
void
{
const
isRoot
=
(
indent
===
0
);
const
MB
=
1024
*
1024
;
...
...
@@ -320,7 +320,7 @@ export class DiagnosticsService implements IDiagnosticsService {
// Format name with indent
let
name
:
string
;
if
(
isRoot
)
{
name
=
`
${
product
.
applicationName
}
main`
;
name
=
item
.
pid
===
mainPid
?
`
${
product
.
applicationName
}
main`
:
'
remote agent
'
;
}
else
{
name
=
`
${
repeat
(
'
'
,
indent
)}
${
item
.
name
}
`
;
...
...
@@ -333,7 +333,7 @@ export class DiagnosticsService implements IDiagnosticsService {
// Recurse into children if any
if
(
Array
.
isArray
(
item
.
children
))
{
item
.
children
.
forEach
(
child
=>
this
.
formatProcessItem
(
mapPidToWindowTitle
,
output
,
child
,
indent
+
1
));
item
.
children
.
forEach
(
child
=>
this
.
formatProcessItem
(
ma
inPid
,
ma
pPidToWindowTitle
,
output
,
child
,
indent
+
1
));
}
}
}
...
...
src/vs/platform/issue/electron-main/issueService.ts
浏览文件 @
97f93d29
...
...
@@ -15,6 +15,8 @@ import { isMacintosh, IProcessEnvironment } from 'vs/base/common/platform';
import
{
ILogService
}
from
'
vs/platform/log/common/log
'
;
import
{
IWindowsService
}
from
'
vs/platform/windows/common/windows
'
;
import
{
IWindowState
}
from
'
vs/platform/windows/electron-main/windows
'
;
import
{
listProcesses
}
from
'
vs/base/node/ps
'
;
import
{
ProcessItem
}
from
'
vs/base/common/processes
'
;
const
DEFAULT_BACKGROUND_COLOR
=
'
#1E1E1E
'
;
...
...
@@ -44,6 +46,16 @@ export class IssueService implements IIssueService {
});
});
ipcMain
.
on
(
'
vscode:listProcesses
'
,
async
(
event
:
Event
)
=>
{
const
mainPid
=
await
this
.
launchService
.
getMainProcessId
();
const
rootProcess
=
await
listProcesses
(
mainPid
);
const
remoteProcesses
=
(
await
this
.
launchService
.
getRemoteDiagnostics
({
includeProcesses
:
true
}))
.
map
(
data
=>
data
.
processes
)
.
filter
((
x
):
x
is
ProcessItem
=>
!!
x
);
event
.
sender
.
send
(
'
vscode:listProcessesResponse
'
,
[
rootProcess
,
...
remoteProcesses
]);
});
ipcMain
.
on
(
'
vscode:issuePerformanceInfoRequest
'
,
(
event
:
Event
)
=>
{
this
.
getPerformanceInfo
().
then
(
msg
=>
{
event
.
sender
.
send
(
'
vscode:issuePerformanceInfoResponse
'
,
msg
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录