Skip to content

Commit 49932df

Browse files
committed
refactor source view into separate component
1 parent 3b69973 commit 49932df

File tree

6 files changed

+188
-40
lines changed

6 files changed

+188
-40
lines changed

client/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"rollup-plugin-livereload": "^1.0.0",
1616
"rollup-plugin-svelte": "^5.0.3",
1717
"rollup-plugin-terser": "^5.1.2",
18-
"svelte": "^3.23.2"
18+
"svelte": "^3.24.0"
1919
},
2020
"dependencies": {
2121
"sirv-cli": "^0.4.4"

client/src/App.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
}
5656
5757
let diagramModes = ['HeapSize', 'HeapLive', 'HeapAllocated', 'ActiveThreads', 'RuntimeProfiling', 'CostCentreStack'];
58-
let diagramMode = 'HeapLive';
58+
let diagramMode = 'CostCentreStack';
5959
const diagramModeElim = cases => d => {
6060
return cases[diagramMode];
6161
}

client/src/CodeMirror.svelte

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
99
const dispatch = createEventDispatcher();
1010
11+
export let selectionsArray = [];
1112
export let firstLineNumber = 1;
1213
export let value = "";
1314
export let readonly = 'nocursor';
@@ -433,6 +434,20 @@
433434
function sleep(ms) {
434435
return new Promise(fulfil => setTimeout(fulfil, ms));
435436
}
437+
438+
$: {
439+
updating_externally = true;
440+
if (editor) {
441+
editor.setOption('firstLineNumber', firstLineNumber);
442+
editor.setValue(value);
443+
selectionsArray.forEach(s => {
444+
editor.getDoc().markText(s.anchor, s.head, {className: 'CodeMirror-selected'});
445+
});
446+
editor.getDoc().setSelections(selectionsArray);
447+
}
448+
updating_externally = false;
449+
}
450+
436451
</script>
437452

438453
<style>

client/src/CostCentreStack.svelte

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<script>
22
import * as d3 from 'd3';
33
import { postData } from './post-data.js';
4+
import { onMount } from 'svelte';
45
import CodeMirror from "./CodeMirror.svelte";
56
import CostCentreStackHeap from './CostCentreStackHeap.svelte';
6-
import { onMount } from 'svelte';
7+
import SourceRangeBox from './SourceRangeBox.svelte';
78
89
export let eventlogData;
910
@@ -260,11 +261,14 @@
260261
</h4>
261262

262263
{#each currentStackData as cc, i}
263-
<div class="list-group-item text-light" class:font-weight-bolder="{i === index}" style="word-wrap:break-word;background-image: {bgImage(i, cc.evSpec.heapProfCostCentreId)}; margin: 0.0em;">
264+
<div class="list-group-item text-light"
265+
class:font-weight-bolder="{i === index}"
266+
style="word-wrap:break-word;background-image: {bgImage(i, cc.evSpec.heapProfCostCentreId)}; margin: 0.0em;"
267+
>
264268

265-
<span style="color: lightgrey;">{cc.evSpec.heapProfModule}</span>
266-
<br>
267-
<span style="color: white;">{cc.evSpec.heapProfLabel}</span>
269+
<span style="color: lightgrey;">{cc.evSpec.heapProfModule}</span>
270+
<br>
271+
<span style="color: white;">{cc.evSpec.heapProfLabel}</span>
268272

269273
</div>
270274
{/each}
@@ -277,32 +281,19 @@
277281

278282
<div class="two">
279283
{#each currentStackData as cc, i}
280-
<div style="background-image: {bgImage2(0, cc.evSpec.heapProfCostCentreId)}; padding: 0.4em; margin: 0.1em 0">
281-
<section>
282-
<button class="btn btn-secondary"><span style="color:lightgrey;">{cc.evSpec.heapProfModule}.</span><span style="color:white;">{cc.evSpec.heapProfLabel}</span></button>
283-
284-
{#if moduleMap && moduleMap[cc.evSpec.heapProfModule]}
285-
<code class="my-right-note">
286-
<span class="my-right-note">{moduleMap[cc.evSpec.heapProfModule].packageName}</span>
287-
<br>
288-
<span class="my-right-note">{cc.evSpec.heapProfSrcLoc}</span>
289-
</code>
290-
{:else}
291-
<code style="float:right;font-size: 0.96em; color:lightgrey;padding: 0.5em; margin:0;">
292-
{cc.evSpec.heapProfSrcLoc}
293-
</code>
294-
{/if}
295-
296-
{#await getSourceCodeForModule(cc.evSpec.heapProfModule)}
297-
<br>
298-
<div class="spinner-border text-light"></div>
299-
{:then sourceCode}
300-
<button style="width:100%; margin: 0; padding: 0.1em 0.5em; border-radius: 0;border-radius: 3px 3px 0 0; text-align:right;">+5 lines</button>
301-
<CodeMirror value={sliceToSrcLoc(sourceCode, cc.evSpec.heapProfSrcLoc)} firstLineNumber={getSrcLocLine(cc.evSpec.heapProfSrcLoc)}/>
302-
<button style="width:100%; margin: 0; padding: 0.1em 0.5em;border-radius: 0;border-radius: 0 0 3px 3px; text-align:right;">+5 lines </button>
303-
{/await}
304-
</section>
305-
</div>
284+
{#await getSourceCodeForModule(cc.evSpec.heapProfModule)}
285+
<div class="spinner-border text-primary"></div>
286+
{:then sourceCode}
287+
<SourceRangeBox
288+
srcLocString={cc.evSpec.heapProfSrcLoc}
289+
moduleName={cc.evSpec.heapProfModule}
290+
functionLabel={cc.evSpec.heapProfLabel}
291+
292+
sourceCode={sourceCode}
293+
packageName={moduleMap && moduleMap[cc.evSpec.heapProfModule] && moduleMap[cc.evSpec.heapProfModule].packageName || ''}
294+
/>
295+
{/await}
296+
306297
{/each}
307298
</div>
308299
</div>
@@ -366,11 +357,4 @@
366357
margin: 0.5em;
367358
}
368359
369-
.my-right-note {
370-
float: right;
371-
font-size: 0.96em;
372-
color: lightgrey;
373-
padding: 0 0.1em;
374-
margin: 0;
375-
}
376360
</style>

client/src/SourceRangeBox.svelte

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<script>
2+
3+
import { parseSrcLoc } from './ghc-srcloc.js';
4+
import CodeMirror from "./CodeMirror.svelte";
5+
6+
// GHC eventlog related
7+
export let srcLocString;
8+
export let moduleName;
9+
export let functionLabel;
10+
11+
// GHC-WPC related
12+
export let sourceCode;
13+
export let packageName;
14+
15+
let originalSourceSpan = parseSrcLoc(srcLocString);
16+
17+
let startLineNumber = originalSourceSpan.startLineNumber;
18+
let endLineNumber = originalSourceSpan.endLineNumber;
19+
20+
let sourceCodeLines = sourceCode.split('\n');
21+
let selectionsArray = [];
22+
23+
function getSourceRange(startLine, endLine) {
24+
return sourceCodeLines.slice(startLine -1, endLine).join('\n');
25+
}
26+
27+
function toggleSource() {
28+
if (startLineNumber !== originalSourceSpan.startLineNumber || endLineNumber !== originalSourceSpan.endLineNumber) {
29+
startLineNumber = originalSourceSpan.startLineNumber;
30+
endLineNumber = originalSourceSpan.endLineNumber;
31+
selectionsArray = [];
32+
} else {
33+
startLineNumber = 1;
34+
endLineNumber = sourceCodeLines.length;
35+
}
36+
}
37+
38+
function extendStart() {
39+
startLineNumber -= 5;
40+
if (startLineNumber < 1) startLineNumber = 1;
41+
}
42+
43+
function extendEnd() {
44+
endLineNumber += 5;
45+
if (endLineNumber >= sourceCodeLines.length) endLineNumber = sourceCodeLines.length;
46+
}
47+
48+
$: if (startLineNumber !== originalSourceSpan.startLineNumber || endLineNumber !== originalSourceSpan.endLineNumber) {
49+
selectionsArray = [
50+
{ anchor: {line:originalSourceSpan.startLineNumber - startLineNumber, ch: originalSourceSpan.startColumn-1}
51+
, head: {line:originalSourceSpan.endLineNumber - startLineNumber + 1, ch: originalSourceSpan.endColumn}
52+
}]
53+
} else {
54+
selectionsArray = [];
55+
}
56+
57+
</script>
58+
59+
<div style="background-image: linear-gradient(to right, #8e508a, #5f5286); padding: 0.4em; margin: 0.1em 0">
60+
<section>
61+
<button class="btn btn-secondary" on:click={toggleSource}><span style="color:lightgrey;">{moduleName}.</span><span style="color:white;">{functionLabel}</span></button>
62+
63+
{#if packageName}
64+
<code class="my-right-note">
65+
<span class="my-right-note">{packageName}</span>
66+
<br>
67+
<span class="my-right-note">{srcLocString}</span>
68+
</code>
69+
{:else}
70+
<code style="float:right;font-size: 0.96em; color:lightgrey;padding: 0.5em; margin:0;">
71+
{srcLocString}
72+
</code>
73+
{/if}
74+
75+
<button style="width:100%; margin: 0; padding: 0.1em 0.5em; border-radius: 0;border-radius: 3px 3px 0 0; text-align:right;" on:click={extendStart}>+5 lines</button>
76+
<CodeMirror
77+
{selectionsArray}
78+
value={getSourceRange(startLineNumber, endLineNumber)}
79+
firstLineNumber={startLineNumber}
80+
/>
81+
<button style="width:100%; margin: 0; padding: 0.1em 0.5em;border-radius: 0;border-radius: 0 0 3px 3px; text-align:right;" on:click={extendEnd}>+5 lines </button>
82+
</section>
83+
</div>
84+
85+
<style>
86+
.my-right-note {
87+
float: right;
88+
font-size: 0.96em;
89+
color: lightgrey;
90+
padding: 0 0.1em;
91+
margin: 0;
92+
}
93+
</style>

client/src/ghc-srcloc.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
isPointRealSpan
3+
path:line:column
4+
/.*:(?<line>\d+):(?<column>\d+)$/
5+
6+
isOneLineRealSpan
7+
path:line:start_column-end_column
8+
/.*:(?<line>\d+):(?<start_column>\d+)-(?<end_column>\d+)$/
9+
10+
generic
11+
path:(start_line,start_column)-(end_line,end_column)
12+
/.*:\((?<start_line>\d+),(?<start_column>\d+)\)-\((?<end_line>\d+),(?<end_column>\d+)\)$/
13+
14+
EXAMPLE:
15+
src3.match(re4).groups
16+
*/
17+
18+
// source location parser
19+
const re1 = /.*:(?<line>\d+):(?<column>\d+)$/;
20+
const re2 = /.*:(?<line>\d+):(?<start_column>\d+)-(?<end_column>\d+)$/;
21+
const re3 = /.*:\((?<start_line>\d+),(?<start_column>\d+)\)-\((?<end_line>\d+),(?<end_column>\d+)\)$/;
22+
23+
export function parseSrcLoc(srcLoc) {
24+
let m;
25+
if (m = srcLoc.match(re1)) {
26+
// path:line:column
27+
return {
28+
startLineNumber: +m.groups.line,
29+
endLineNumber: +m.groups.line,
30+
startColumn: +m.groups.column,
31+
endColumn: +m.groups.column
32+
};
33+
} else if (m = srcLoc.match(re2)) {
34+
// path:line:start_column-end_column
35+
return {
36+
startLineNumber: +m.groups.line,
37+
endLineNumber: +m.groups.line,
38+
startColumn: +m.groups.start_column,
39+
endColumn: +m.groups.end_column
40+
};
41+
} else if (m = srcLoc.match(re3)) {
42+
// path:(start_line,start_column)-(end_line,end_column)
43+
return {
44+
startLineNumber: +m.groups.start_line,
45+
endLineNumber: +m.groups.end_line,
46+
startColumn: +m.groups.start_column,
47+
endColumn: +m.groups.end_column
48+
};
49+
}
50+
return {
51+
startLineNumber: 1,
52+
endLineNumber: undefined, // marks the end of the document
53+
startColumn: 1,
54+
endColumn: 1
55+
};
56+
}

0 commit comments

Comments
 (0)