Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
frama-c
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pub
frama-c
Commits
c8f023c7
Commit
c8f023c7
authored
3 years ago
by
Maxime Jacquemin
Committed by
Maxime Jacquemin
3 years ago
Browse files
Options
Downloads
Patches
Plain Diff
[ivette] Some comments and a little bug fix
parent
b115fc84
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
ivette/src/frama-c/plugins/eva/valuetable.tsx
+222
-64
222 additions, 64 deletions
ivette/src/frama-c/plugins/eva/valuetable.tsx
with
222 additions
and
64 deletions
ivette/src/frama-c/plugins/eva/valuetable.tsx
+
222
−
64
View file @
c8f023c7
...
@@ -38,15 +38,12 @@ import { Inset, Button, ButtonGroup } from 'dome/frame/toolbars';
...
@@ -38,15 +38,12 @@ import { Inset, Button, ButtonGroup } from 'dome/frame/toolbars';
/* -------------------------------------------------------------------------- */
/* --- Miscellaneous definitions --- */
/* -------------------------------------------------------------------------- */
type
Request
<
A
,
B
>
=
(
a
:
A
)
=>
Promise
<
B
>
;
type
Request
<
A
,
B
>
=
(
a
:
A
)
=>
Promise
<
B
>
;
type
StateToDisplay
=
'
Before
'
|
'
After
'
|
'
Both
'
|
'
None
'
type
StateToDisplay
=
'
Before
'
|
'
After
'
|
'
Both
'
|
'
None
'
type
callstack
=
'
Summary
'
|
Values
.
callstack
function
useCallstacksCache
():
Request
<
Ast
.
marker
[],
callstack
[]
>
{
const
g
=
React
.
useCallback
((
m
)
=>
Server
.
send
(
Values
.
getCallstacks
,
m
),
[]);
const
toString
=
React
.
useCallback
((
ms
)
=>
ms
.
join
(
'
|
'
),
[]);
return
Dome
.
useCache
(
g
,
toString
);
}
type
Alarm
=
[
'
True
'
|
'
False
'
|
'
Unknown
'
,
string
]
type
Alarm
=
[
'
True
'
|
'
False
'
|
'
Unknown
'
,
string
]
function
getAlarmStatus
(
alarms
:
Alarm
[]
|
undefined
):
string
{
function
getAlarmStatus
(
alarms
:
Alarm
[]
|
undefined
):
string
{
...
@@ -72,14 +69,41 @@ function isPinnedMarker(status: MarkerStatus): boolean {
...
@@ -72,14 +69,41 @@ function isPinnedMarker(status: MarkerStatus): boolean {
return
kind
===
'
Pinned
'
;
return
kind
===
'
Pinned
'
;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Callstack related definitions --- */
/* -------------------------------------------------------------------------- */
/* Callstacks are declared by the server. We add the `Summary` construction to
* cleanly represent the summary of all the callstacks. */
type
callstack
=
'
Summary
'
|
Values
.
callstack
/* Builds a cached version of the `getCallstacks` request */
function
useCallstacksCache
():
Request
<
Ast
.
marker
[],
callstack
[]
>
{
const
g
=
React
.
useCallback
((
m
)
=>
Server
.
send
(
Values
.
getCallstacks
,
m
),
[]);
const
toString
=
React
.
useCallback
((
ms
)
=>
ms
.
join
(
'
|
'
),
[]);
return
Dome
.
useCache
(
g
,
toString
);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Callsite related definitions --- */
/* -------------------------------------------------------------------------- */
/* Representation of a callsite as described in the server */
interface
Callsite
{
interface
Callsite
{
callee
:
string
;
callee
:
string
;
caller
?:
string
;
caller
?:
string
;
stmt
?:
Ast
.
marker
;
stmt
?:
Ast
.
marker
;
}
}
/* Builds a cached version of the `getCallstackInfo` request */
function
useCallsitesCache
():
Request
<
callstack
,
Callsite
[]
>
{
function
useCallsitesCache
():
Request
<
callstack
,
Callsite
[]
>
{
const
get
=
React
.
useCallback
((
c
)
=>
{
const
get
=
React
.
useCallback
((
c
)
=>
{
if
(
c
!==
'
Summary
'
)
return
Server
.
send
(
Values
.
getCallstackInfo
,
c
);
if
(
c
!==
'
Summary
'
)
return
Server
.
send
(
Values
.
getCallstackInfo
,
c
);
...
@@ -88,52 +112,22 @@ function useCallsitesCache(): Request<callstack, Callsite[]> {
...
@@ -88,52 +112,22 @@ function useCallsitesCache(): Request<callstack, Callsite[]> {
return
Dome
.
useCache
(
get
);
return
Dome
.
useCache
(
get
);
}
}
interface
CallsiteCellProps
{
/* -------------------------------------------------------------------------- */
callstack
:
callstack
|
'
Header
'
|
'
Descr
'
;
index
?:
number
;
getCallsites
:
Request
<
callstack
,
Callsite
[]
>
;
selectedClass
?:
string
;
}
function
makeStackTitle
(
calls
:
Callsite
[]):
string
{
const
cs
=
calls
.
slice
(
1
);
if
(
cs
.
length
>
0
)
return
`Callstack:
${
cs
.
map
((
c
)
=>
c
.
callee
).
join
(
'
\
u2190
'
)}
`
;
return
'
Callstack Details
'
;
}
async
function
CallsiteCell
(
props
:
CallsiteCellProps
):
Promise
<
JSX
.
Element
>
{
const
{
callstack
,
index
,
getCallsites
,
selectedClass
=
''
}
=
props
;
const
baseClasses
=
classes
(
'
eva-table-callsite-box
'
,
selectedClass
);
switch
(
callstack
)
{
case
'
Header
'
:
{
const
cls
=
classes
(
baseClasses
,
'
eva-table-header-sticky
'
);
const
title
=
'
Corresponding callstack
'
;
return
<
td
className
=
{
cls
}
title
=
{
title
}
>
{
'
#
'
}
</
td
>;
}
case
'
Descr
'
:
{
const
cls
=
classes
(
baseClasses
,
'
eva-table-descr-sticky
'
);
const
title
=
'
Column description
'
;
return
<
td
className
=
{
cls
}
title
=
{
title
}
>
{
'
D
'
}
</
td
>;
}
default
:
{
const
cls
=
classes
(
baseClasses
,
'
eva-table-value-sticky
'
);
const
callsites
=
await
getCallsites
(
callstack
);
const
isSummary
=
callstack
===
'
Summary
'
;
const
infos
=
isSummary
?
'
Summary
'
:
makeStackTitle
(
callsites
);
const
text
=
isSummary
?
'
∑
'
:
(
index
?
index
.
toString
()
:
'
0
'
);
return
<
td
className
=
{
cls
}
title
=
{
infos
}
>
{
text
}
</
td
>;
}
}
}
/* -------------------------------------------------------------------------- */
/* --- Probe related definitions --- */
/* -------------------------------------------------------------------------- */
/* A Location is a marker in a function */
interface
Location
{
interface
Location
{
target
:
Ast
.
marker
;
target
:
Ast
.
marker
;
fct
:
string
;
fct
:
string
;
}
}
/* An Evaluation keeps track of the values at relevant control point around a
* statement, along with the potential errors */
interface
Evaluation
{
interface
Evaluation
{
errors
?:
string
;
errors
?:
string
;
vBefore
?:
Values
.
evaluation
;
vBefore
?:
Values
.
evaluation
;
...
@@ -142,6 +136,10 @@ interface Evaluation {
...
@@ -142,6 +136,10 @@ interface Evaluation {
vElse
?:
Values
.
evaluation
;
vElse
?:
Values
.
evaluation
;
}
}
/* A Probe is a location along with data representing textually what it is, the
* considered statement, if it is an effectfull one or one with conditions.
* Moreover, it gives a function that computes an Evaluation for a given
* callstack. This computation is asynchronous. */
interface
Probe
extends
Location
{
interface
Probe
extends
Location
{
code
?:
string
;
code
?:
string
;
stmt
?:
Ast
.
marker
;
stmt
?:
Ast
.
marker
;
...
@@ -151,12 +149,11 @@ interface Probe extends Location {
...
@@ -151,12 +149,11 @@ interface Probe extends Location {
evaluate
:
Request
<
callstack
,
Evaluation
>
evaluate
:
Request
<
callstack
,
Evaluation
>
}
}
const
LocToString
=
(
loc
:
Location
):
string
=>
`
${
loc
.
fct
}
:
${
loc
.
target
}
`
;
/* Builds a cached version of the `getValues` request */
type
LocStack
=
[
Location
,
callstack
]
function
useEvaluationCache
():
Request
<
[
Location
,
callstack
],
Evaluation
>
{
type
LocStack
=
[
Location
,
callstack
];
function
useEvaluationCache
():
Request
<
LocStack
,
Evaluation
>
{
const
toString
=
React
.
useCallback
(([
l
,
c
]
:
LocStack
):
string
=>
{
const
toString
=
React
.
useCallback
(([
l
,
c
]
:
LocStack
):
string
=>
{
return
`
${
LocToString
(
l
)
}
:
${
c
}
`
;
return
`
${
l
.
fct
}
:
${
l
.
target
}
:
${
c
}
`
;
},
[]);
},
[]);
const
get
:
Request
<
LocStack
,
Evaluation
>
=
React
.
useCallback
(([
l
,
c
])
=>
{
const
get
:
Request
<
LocStack
,
Evaluation
>
=
React
.
useCallback
(([
l
,
c
])
=>
{
const
callstack
=
c
===
'
Summary
'
?
undefined
:
c
as
Values
.
callstack
;
const
callstack
=
c
===
'
Summary
'
?
undefined
:
c
as
Values
.
callstack
;
...
@@ -165,6 +162,7 @@ function useEvaluationCache(): Request<LocStack, Evaluation> {
...
@@ -165,6 +162,7 @@ function useEvaluationCache(): Request<LocStack, Evaluation> {
return
Dome
.
useCache
(
get
,
toString
);
return
Dome
.
useCache
(
get
,
toString
);
}
}
/* Builds a cached function that builds a Probe given a Location */
function
useProbeCache
():
Request
<
Location
,
Probe
>
{
function
useProbeCache
():
Request
<
Location
,
Probe
>
{
const
toString
=
React
.
useCallback
((
l
)
=>
`
${
l
.
fct
}
:
${
l
.
target
}
`
,
[]);
const
toString
=
React
.
useCallback
((
l
)
=>
`
${
l
.
fct
}
:
${
l
.
target
}
`
,
[]);
const
cache
=
useEvaluationCache
();
const
cache
=
useEvaluationCache
();
...
@@ -176,8 +174,14 @@ function useProbeCache(): Request<Location, Probe> {
...
@@ -176,8 +174,14 @@ function useProbeCache(): Request<Location, Probe> {
return
Dome
.
useCache
(
get
,
toString
);
return
Dome
.
useCache
(
get
,
toString
);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Statement Component --- */
/* -------------------------------------------------------------------------- */
interface
StmtProps
{
interface
StmtProps
{
stmt
?:
Ast
.
marker
;
stmt
?:
Ast
.
marker
;
marker
?:
Ast
.
marker
;
marker
?:
Ast
.
marker
;
...
@@ -196,8 +200,14 @@ function Stmt(props: StmtProps): JSX.Element {
...
@@ -196,8 +200,14 @@ function Stmt(props: StmtProps): JSX.Element {
return
<
span
className
=
{
className
}
title
=
{
title
}
>
{
text
}
</
span
>;
return
<
span
className
=
{
className
}
title
=
{
title
}
>
{
text
}
</
span
>;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Informations on the alarms in a given callstack --- */
/* -------------------------------------------------------------------------- */
function
AlarmsInfos
(
probe
?:
Probe
):
Request
<
callstack
,
JSX
.
Element
>
{
function
AlarmsInfos
(
probe
?:
Probe
):
Request
<
callstack
,
JSX
.
Element
>
{
return
async
(
c
:
callstack
):
Promise
<
JSX
.
Element
>
=>
{
return
async
(
c
:
callstack
):
Promise
<
JSX
.
Element
>
=>
{
const
evaluation
=
await
probe
?.
evaluate
(
c
);
const
evaluation
=
await
probe
?.
evaluate
(
c
);
...
@@ -212,8 +222,14 @@ function AlarmsInfos(probe?: Probe): Request<callstack, JSX.Element> {
...
@@ -212,8 +222,14 @@ function AlarmsInfos(probe?: Probe): Request<callstack, JSX.Element> {
};
};
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Informations on the selected callstack --- */
/* -------------------------------------------------------------------------- */
interface
StackInfosProps
{
interface
StackInfosProps
{
callsites
:
Callsite
[];
callsites
:
Callsite
[];
isSelected
:
boolean
;
isSelected
:
boolean
;
...
@@ -255,8 +271,18 @@ async function StackInfos(props: StackInfosProps): Promise<JSX.Element> {
...
@@ -255,8 +271,18 @@ async function StackInfos(props: StackInfosProps): Promise<JSX.Element> {
return
<
Hpack
className
=
"eva-info"
>
{
children
}
</
Hpack
>;
return
<
Hpack
className
=
"eva-info"
>
{
children
}
</
Hpack
>;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Selected Probe Component --- */
/* -------------------------------------------------------------------------- */
/* --- Display informations on the currently selected probe, along with --- */
/* --- buttons to pin, remove and change the displayed columns, i.e. if --- */
/* --- we display the values before and/or after the statement. --- */
/* -------------------------------------------------------------------------- */
interface
ProbeInfosProps
{
interface
ProbeInfosProps
{
probe
?:
Probe
;
probe
?:
Probe
;
status
?:
MarkerStatus
;
status
?:
MarkerStatus
;
...
@@ -332,7 +358,16 @@ function SelectedProbeInfos(props: ProbeInfosProps): JSX.Element {
...
@@ -332,7 +358,16 @@ function SelectedProbeInfos(props: ProbeInfosProps): JSX.Element {
);
);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Probe Header Component --- */
/* -------------------------------------------------------------------------- */
/* --- Header of a column, describing the evaluated expression and its --- */
/* --- status inside the component (pinned, tracked, etc). --- */
/* -------------------------------------------------------------------------- */
interface
ProbeHeaderProps
{
interface
ProbeHeaderProps
{
probe
:
Probe
;
probe
:
Probe
;
...
@@ -393,7 +428,16 @@ function ProbeHeader(props: ProbeHeaderProps): JSX.Element {
...
@@ -393,7 +428,16 @@ function ProbeHeader(props: ProbeHeaderProps): JSX.Element {
);
);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Probe Description Component --- */
/* -------------------------------------------------------------------------- */
/* --- Description of a table column, i.e. if it contains values --- */
/* --- evaluated before or after the considered statement. --- */
/* -------------------------------------------------------------------------- */
interface
ProbeDescrProps
{
interface
ProbeDescrProps
{
summary
:
Evaluation
;
summary
:
Evaluation
;
...
@@ -433,8 +477,20 @@ function ProbeDescr(props: ProbeDescrProps): JSX.Element[] {
...
@@ -433,8 +477,20 @@ function ProbeDescr(props: ProbeDescrProps): JSX.Element[] {
return
elements
;
return
elements
;
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Probe Values Component --- */
/* -------------------------------------------------------------------------- */
/* --- This component represents the contents of one of the table that --- */
/* --- displays values information. As the content depends on the --- */
/* --- considered callstack, we decided to return a function that build --- */
/* --- the actual component when given a callstack. It avoids useless --- */
/* --- computational boilerplate. --- */
/* -------------------------------------------------------------------------- */
interface
ProbeValuesProps
{
interface
ProbeValuesProps
{
probe
:
Probe
;
probe
:
Probe
;
summary
:
Evaluation
;
summary
:
Evaluation
;
...
@@ -505,7 +561,60 @@ function ProbeValues(props: ProbeValuesProps): Request<callstack, JSX.Element> {
...
@@ -505,7 +561,60 @@ function ProbeValues(props: ProbeValuesProps): Request<callstack, JSX.Element> {
};
};
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Row header describing the corresponding callstack --- */
/* -------------------------------------------------------------------------- */
interface
CallsiteCellProps
{
callstack
:
callstack
|
'
Header
'
|
'
Descr
'
;
index
?:
number
;
getCallsites
:
Request
<
callstack
,
Callsite
[]
>
;
selectedClass
?:
string
;
}
function
makeStackTitle
(
calls
:
Callsite
[]):
string
{
const
cs
=
calls
.
slice
(
1
);
if
(
cs
.
length
>
0
)
return
`Callstack:
${
cs
.
map
((
c
)
=>
c
.
callee
).
join
(
'
\
u2190
'
)}
`
;
return
'
Callstack Details
'
;
}
async
function
CallsiteCell
(
props
:
CallsiteCellProps
):
Promise
<
JSX
.
Element
>
{
const
{
callstack
,
index
,
getCallsites
,
selectedClass
=
''
}
=
props
;
const
baseClasses
=
classes
(
'
eva-table-callsite-box
'
,
selectedClass
);
switch
(
callstack
)
{
case
'
Header
'
:
{
const
cls
=
classes
(
baseClasses
,
'
eva-table-header-sticky
'
);
const
title
=
'
Corresponding callstack
'
;
return
<
td
className
=
{
cls
}
title
=
{
title
}
>
{
'
#
'
}
</
td
>;
}
case
'
Descr
'
:
{
const
cls
=
classes
(
baseClasses
,
'
eva-table-descr-sticky
'
);
const
title
=
'
Column description
'
;
return
<
td
className
=
{
cls
}
title
=
{
title
}
>
{
'
D
'
}
</
td
>;
}
default
:
{
const
cls
=
classes
(
baseClasses
,
'
eva-table-value-sticky
'
);
const
callsites
=
await
getCallsites
(
callstack
);
const
isSummary
=
callstack
===
'
Summary
'
;
const
infos
=
isSummary
?
'
Summary
'
:
makeStackTitle
(
callsites
);
const
text
=
isSummary
?
'
∑
'
:
(
index
?
index
.
toString
()
:
'
0
'
);
return
<
td
className
=
{
cls
}
title
=
{
infos
}
>
{
text
}
</
td
>;
}
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Function Section Component --- */
/* -------------------------------------------------------------------------- */
interface
FunctionProps
{
interface
FunctionProps
{
fct
:
string
;
fct
:
string
;
...
@@ -539,14 +648,15 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
...
@@ -539,14 +648,15 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
const
{
addLoc
,
getCallstacks
:
getCS
}
=
props
;
const
{
addLoc
,
getCallstacks
:
getCS
}
=
props
;
const
{
setFolded
,
setByCallstacks
,
close
}
=
props
;
const
{
setFolded
,
setByCallstacks
,
close
}
=
props
;
const
{
startingCallstack
,
changeStartingCallstack
}
=
props
;
const
{
startingCallstack
,
changeStartingCallstack
}
=
props
;
const
displayTable
=
folded
?
'
none
'
:
'
table
'
;
const
displayTable
=
folded
||
state
===
'
None
'
?
'
none
'
:
'
table
'
;
const
onClick
=
(
c
:
callstack
):
()
=>
void
=>
()
=>
props
.
selectCallstack
(
c
);
const
onClick
=
(
c
:
callstack
):
()
=>
void
=>
()
=>
props
.
selectCallstack
(
c
);
/* Compute relevant callstacks */
/* Compute
s the
relevant callstacks */
const
markers
=
Array
.
from
(
props
.
markers
.
keys
());
const
markers
=
Array
.
from
(
props
.
markers
.
keys
());
const
callstacks
=
byCallstacks
?
(
await
getCS
(
markers
)
??
[])
:
[];
const
callstacks
=
byCallstacks
?
(
await
getCS
(
markers
)
??
[])
:
[];
const
summaryOnly
=
callstacks
.
length
===
1
;
const
summaryOnly
=
callstacks
.
length
===
1
;
/* Computes the relevant data for each marker */
interface
Data
{
probe
:
Probe
;
summary
:
Evaluation
;
status
:
MarkerStatus
}
interface
Data
{
probe
:
Probe
;
summary
:
Evaluation
;
status
:
MarkerStatus
}
const
entries
=
Array
.
from
(
props
.
markers
.
entries
());
const
entries
=
Array
.
from
(
props
.
markers
.
entries
());
const
data
=
await
Promise
.
all
(
entries
.
map
(
async
([
target
,
status
])
=>
{
const
data
=
await
Promise
.
all
(
entries
.
map
(
async
([
target
,
status
])
=>
{
...
@@ -555,6 +665,7 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
...
@@ -555,6 +665,7 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
return
{
probe
,
summary
,
status
}
as
Data
;
return
{
probe
,
summary
,
status
}
as
Data
;
}));
}));
/* Computes the headers for each marker */
const
headerCall
=
await
CallsiteCell
({
getCallsites
,
callstack
:
'
Header
'
});
const
headerCall
=
await
CallsiteCell
({
getCallsites
,
callstack
:
'
Header
'
});
const
headers
=
await
Promise
.
all
(
data
.
map
((
d
:
Data
)
=>
{
const
headers
=
await
Promise
.
all
(
data
.
map
((
d
:
Data
)
=>
{
const
pinProbe
=
(
pin
:
boolean
):
void
=>
props
.
pinProbe
(
d
.
probe
,
pin
);
const
pinProbe
=
(
pin
:
boolean
):
void
=>
props
.
pinProbe
(
d
.
probe
,
pin
);
...
@@ -564,14 +675,17 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
...
@@ -564,14 +675,17 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
return
ProbeHeader
({
...
d
,
state
,
...
fcts
,
locEvt
});
return
ProbeHeader
({
...
d
,
state
,
...
fcts
,
locEvt
});
}));
}));
/* Computes the columns descriptions */
const
descrsCall
=
await
CallsiteCell
({
getCallsites
,
callstack
:
'
Descr
'
});
const
descrsCall
=
await
CallsiteCell
({
getCallsites
,
callstack
:
'
Descr
'
});
const
descrs
=
data
.
map
((
d
)
=>
ProbeDescr
({
...
d
,
state
}));
const
descrs
=
data
.
map
((
d
)
=>
ProbeDescr
({
...
d
,
state
}));
/* Computes the summary values */
const
miscs
=
{
state
,
addLoc
,
isSelectedCallstack
,
summaryOnly
};
const
miscs
=
{
state
,
addLoc
,
isSelectedCallstack
,
summaryOnly
};
const
builders
=
data
.
map
((
d
:
Data
)
=>
ProbeValues
({
...
d
,
...
miscs
}));
const
builders
=
data
.
map
((
d
:
Data
)
=>
ProbeValues
({
...
d
,
...
miscs
}));
const
summary
=
await
Promise
.
all
(
builders
.
map
((
b
)
=>
b
(
'
Summary
'
)));
const
summary
=
await
Promise
.
all
(
builders
.
map
((
b
)
=>
b
(
'
Summary
'
)));
const
summCall
=
await
CallsiteCell
({
callstack
:
'
Summary
'
,
getCallsites
});
const
summCall
=
await
CallsiteCell
({
callstack
:
'
Summary
'
,
getCallsites
});
/* Computes the values for each callstack */
const
start
=
Math
.
max
(
1
,
startingCallstack
);
const
start
=
Math
.
max
(
1
,
startingCallstack
);
const
stop
=
Math
.
min
(
start
+
PageSize
,
callstacks
.
length
);
const
stop
=
Math
.
min
(
start
+
PageSize
,
callstacks
.
length
);
const
values
=
await
Promise
.
all
(
callstacks
.
map
(
async
(
callstack
,
n
)
=>
{
const
values
=
await
Promise
.
all
(
callstacks
.
map
(
async
(
callstack
,
n
)
=>
{
...
@@ -589,6 +703,8 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
...
@@ -589,6 +703,8 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
);
);
}));
}));
/* We change the starting callstack dynamically when we reach the ends of the
* scroll to avoid to build the complete table */
const
onScroll
:
React
.
UIEventHandler
<
HTMLDivElement
>
=
(
event
)
=>
{
const
onScroll
:
React
.
UIEventHandler
<
HTMLDivElement
>
=
(
event
)
=>
{
const
{
scrollTop
,
scrollHeight
,
clientHeight
}
=
event
.
currentTarget
;
const
{
scrollTop
,
scrollHeight
,
clientHeight
}
=
event
.
currentTarget
;
if
(
scrollTop
/
(
scrollHeight
-
clientHeight
)
<=
0.1
)
if
(
scrollTop
/
(
scrollHeight
-
clientHeight
)
<=
0.1
)
...
@@ -602,12 +718,14 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
...
@@ -602,12 +718,14 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
}
}
};
};
/* Handles ctrl+scroll for horizontal scrolling */
const
onWheel
=
(
event
:
React
.
WheelEvent
):
void
=>
{
const
onWheel
=
(
event
:
React
.
WheelEvent
):
void
=>
{
const
tgt
=
event
.
currentTarget
;
const
tgt
=
event
.
currentTarget
;
const
left
=
event
.
deltaY
*
tgt
.
scrollWidth
/
tgt
.
scrollHeight
;
const
left
=
event
.
deltaY
*
tgt
.
scrollWidth
/
tgt
.
scrollHeight
;
if
(
event
.
ctrlKey
)
tgt
.
scrollLeft
+=
left
;
if
(
event
.
ctrlKey
)
tgt
.
scrollLeft
+=
left
;
};
};
/* Builds the component */
return
(
return
(
<>
<>
<
Hpack
className
=
"eva-function"
>
<
Hpack
className
=
"eva-function"
>
...
@@ -660,16 +778,26 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
...
@@ -660,16 +778,26 @@ async function FunctionSection(props: FunctionProps): Promise<JSX.Element> {
);
);
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Function Manager --- */
/* -------------------------------------------------------------------------- */
/* --- The Function Manager is responsible of all the data related to --- */
/* --- programs functions. --- */
/* -------------------------------------------------------------------------- */
/* Informations on one function */
class
FunctionInfos
{
class
FunctionInfos
{
readonly
fct
:
string
;
readonly
fct
:
string
;
// Function's name
readonly
pinned
=
new
Set
<
Ast
.
marker
>
();
readonly
pinned
=
new
Set
<
Ast
.
marker
>
();
// Pinned markers
readonly
tracked
=
new
Set
<
Ast
.
marker
>
();
readonly
tracked
=
new
Set
<
Ast
.
marker
>
();
// Tracked markers
startingCallstack
=
1
;
startingCallstack
=
1
;
// First displayed callstack
byCallstacks
=
false
;
byCallstacks
=
false
;
// True if displayed by callstacks
folded
=
false
;
folded
=
false
;
// True if folded
constructor
(
fct
:
string
)
{
constructor
(
fct
:
string
)
{
this
.
fct
=
fct
;
this
.
fct
=
fct
;
...
@@ -712,8 +840,7 @@ class FunctionInfos {
...
@@ -712,8 +840,7 @@ class FunctionInfos {
}
}
/* State keeping tracks of informations for every relevant functions */
class
FunctionsManager
{
class
FunctionsManager
{
private
readonly
cache
=
new
Map
<
string
,
FunctionInfos
>
();
private
readonly
cache
=
new
Map
<
string
,
FunctionInfos
>
();
...
@@ -816,21 +943,41 @@ class FunctionsManager {
...
@@ -816,21 +943,41 @@ class FunctionsManager {
}
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* --- Eva Table Complet Component --- */
/* -------------------------------------------------------------------------- */
function
EvaTable
():
JSX
.
Element
{
function
EvaTable
():
JSX
.
Element
{
/* Component state */
const
[
selection
,
select
]
=
States
.
useSelection
();
const
[
selection
,
select
]
=
States
.
useSelection
();
const
[
state
,
setState
]
=
React
.
useState
<
StateToDisplay
>
(
'
After
'
);
const
[
state
,
setState
]
=
React
.
useState
<
StateToDisplay
>
(
'
After
'
);
const
[
cs
,
setCS
]
=
React
.
useState
<
callstack
>
(
'
Summary
'
);
const
[
cs
,
setCS
]
=
React
.
useState
<
callstack
>
(
'
Summary
'
);
const
[
fcts
]
=
React
.
useState
(
new
FunctionsManager
());
const
[
fcts
]
=
React
.
useState
(
new
FunctionsManager
());
const
[
focus
,
setFocus
]
=
React
.
useState
<
Probe
|
undefined
>
(
undefined
);
/* Used to force the component update. We cannot use the `forceUpdate` hook
* proposed by Dome as we need to be able to add dependencies on a changing
* value (here tac) explicitly. We need to force the update as modifications
* of the Function Manager internal data does NOT trigger the component
* update. */
const
[
tac
,
setTic
]
=
React
.
useState
(
0
);
const
[
tac
,
setTic
]
=
React
.
useState
(
0
);
/* Event use to communicate when a location is selected. Used to scroll
* related column into view if needed */
const
[
locEvt
]
=
React
.
useState
(
new
Dome
.
Event
<
Location
>
(
'
eva-location
'
));
const
[
locEvt
]
=
React
.
useState
(
new
Dome
.
Event
<
Location
>
(
'
eva-location
'
));
/* Build cached version of needed server's requests */
const
getProbe
=
useProbeCache
();
const
getProbe
=
useProbeCache
();
const
getCallsites
=
useCallsitesCache
();
const
getCallsites
=
useCallsitesCache
();
const
getCallstacks
=
useCallstacksCache
();
const
getCallstacks
=
useCallstacksCache
();
const
[
focus
,
setFocus
]
=
React
.
useState
<
Probe
|
undefined
>
(
undefined
);
/* Updated the focused Probe when the selection changes. Also emit on the
* `locEvent` event. */
React
.
useEffect
(()
=>
{
React
.
useEffect
(()
=>
{
const
target
=
selection
?.
current
?.
marker
;
const
target
=
selection
?.
current
?.
marker
;
const
fct
=
selection
?.
current
?.
fct
;
const
fct
=
selection
?.
current
?.
fct
;
...
@@ -842,12 +989,14 @@ function EvaTable(): JSX.Element {
...
@@ -842,12 +989,14 @@ function EvaTable(): JSX.Element {
else
setFocus
(
undefined
);
else
setFocus
(
undefined
);
},
[
fcts
,
selection
,
getProbe
,
setFocus
,
locEvt
]);
},
[
fcts
,
selection
,
getProbe
,
setFocus
,
locEvt
]);
/* Callback used to pin or unpin a location */
const
setLocPin
=
React
.
useCallback
((
loc
:
Location
,
pin
:
boolean
):
void
=>
{
const
setLocPin
=
React
.
useCallback
((
loc
:
Location
,
pin
:
boolean
):
void
=>
{
if
(
pin
)
fcts
.
pin
(
loc
);
if
(
pin
)
fcts
.
pin
(
loc
);
else
fcts
.
unpin
(
loc
);
else
fcts
.
unpin
(
loc
);
setTic
(
tac
+
1
);
setTic
(
tac
+
1
);
},
[
fcts
,
setTic
,
tac
]);
},
[
fcts
,
setTic
,
tac
]);
/* Callback used to remove a probe */
const
remove
=
React
.
useCallback
((
probe
:
Probe
):
void
=>
{
const
remove
=
React
.
useCallback
((
probe
:
Probe
):
void
=>
{
fcts
.
removeLocation
(
probe
);
fcts
.
removeLocation
(
probe
);
if
(
probe
.
target
===
focus
?.
target
)
if
(
probe
.
target
===
focus
?.
target
)
...
@@ -856,6 +1005,9 @@ function EvaTable(): JSX.Element {
...
@@ -856,6 +1005,9 @@ function EvaTable(): JSX.Element {
setTic
(
tac
+
1
);
setTic
(
tac
+
1
);
},
[
fcts
,
focus
,
setFocus
,
tac
]);
},
[
fcts
,
focus
,
setFocus
,
tac
]);
/* Builds the sections for each function. As the component is built
* asynchronously, we have to use the `usePromise` hook, which forces us to
* memoize the promises building. */
const
functionsPromise
=
React
.
useMemo
(()
=>
{
const
functionsPromise
=
React
.
useMemo
(()
=>
{
const
ps
=
fcts
.
map
((
infos
,
fct
)
=>
{
const
ps
=
fcts
.
map
((
infos
,
fct
)
=>
{
const
{
byCallstacks
,
folded
}
=
infos
;
const
{
byCallstacks
,
folded
}
=
infos
;
...
@@ -899,13 +1051,16 @@ function EvaTable(): JSX.Element {
...
@@ -899,13 +1051,16 @@ function EvaTable(): JSX.Element {
return
Promise
.
all
(
ps
.
map
(
FunctionSection
));
return
Promise
.
all
(
ps
.
map
(
FunctionSection
));
},
},
[
cs
,
fcts
,
focus
,
tac
,
getCallsites
,
setLocPin
,
[
cs
,
fcts
,
focus
,
tac
,
getCallsites
,
setLocPin
,
getCallstacks
,
getProbe
,
remove
,
select
,
state
,
locEvt
getCallstacks
,
getProbe
,
remove
,
select
,
state
,
locEvt
]);
]);
const
{
result
:
functions
}
=
Dome
.
usePromise
(
functionsPromise
);
const
{
result
:
functions
}
=
Dome
.
usePromise
(
functionsPromise
);
/* Builds the alarms component. As for the function sections, it is an
* asynchronous process. */
const
alarmsProm
=
React
.
useMemo
(()
=>
AlarmsInfos
(
focus
)(
cs
),
[
focus
,
cs
]);
const
alarmsProm
=
React
.
useMemo
(()
=>
AlarmsInfos
(
focus
)(
cs
),
[
focus
,
cs
]);
const
{
result
:
alarmsInfos
}
=
Dome
.
usePromise
(
alarmsProm
);
const
{
result
:
alarmsInfos
}
=
Dome
.
usePromise
(
alarmsProm
);
/* Builds the stacks component. As for the function sections, it is an
* asynchronous process. */
const
stackInfosPromise
=
React
.
useMemo
(
async
()
=>
{
const
stackInfosPromise
=
React
.
useMemo
(
async
()
=>
{
const
callsites
=
await
getCallsites
(
cs
);
const
callsites
=
await
getCallsites
(
cs
);
const
tgt
=
selection
.
current
?.
marker
;
const
tgt
=
selection
.
current
?.
marker
;
...
@@ -915,6 +1070,7 @@ function EvaTable(): JSX.Element {
...
@@ -915,6 +1070,7 @@ function EvaTable(): JSX.Element {
},
[
cs
,
select
,
getCallsites
,
selection
]);
},
[
cs
,
select
,
getCallsites
,
selection
]);
const
{
result
:
stackInfos
}
=
Dome
.
usePromise
(
stackInfosPromise
);
const
{
result
:
stackInfos
}
=
Dome
.
usePromise
(
stackInfosPromise
);
/* Builds the component */
return
(
return
(
<>
<>
<
Ivette
.
TitleBar
/>
<
Ivette
.
TitleBar
/>
...
@@ -933,10 +1089,10 @@ function EvaTable(): JSX.Element {
...
@@ -933,10 +1089,10 @@ function EvaTable(): JSX.Element {
{
stackInfos
}
{
stackInfos
}
</>
</>
);
);
}
}
/* Registers the component in Ivette */
Ivette
.
registerComponent
({
Ivette
.
registerComponent
({
id
:
'
frama-c.plugins.values
'
,
id
:
'
frama-c.plugins.values
'
,
group
:
'
frama-c.plugins
'
,
group
:
'
frama-c.plugins
'
,
...
@@ -945,3 +1101,5 @@ Ivette.registerComponent({
...
@@ -945,3 +1101,5 @@ Ivette.registerComponent({
title
:
'
Values inferred by the Eva analysis
'
,
title
:
'
Values inferred by the Eva analysis
'
,
children
:
<
EvaTable
/>,
children
:
<
EvaTable
/>,
});
});
/* -------------------------------------------------------------------------- */
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment