Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pub/frama-c
  • proidiot/frama-c
  • lthls/frama-c
3 results
Show changes
Showing
with 156 additions and 155 deletions
......@@ -149,7 +149,7 @@ export interface evaluation {
/** Alarms raised by the evaluation */
alarms: [ "True" | "False" | "Unknown", string ][];
/** List of variables pointed by the value */
pointed_vars: [ string, marker ][];
pointedVars: [ string, marker ][];
}
/** Loose decoder for `evaluation` */
......@@ -167,12 +167,12 @@ export const jEvaluation: Json.Loose<evaluation> =
),'Union expected'),
Json.jFail(Json.jString,'String expected'),
))),
pointed_vars: Json.jList(
Json.jTry(
Json.jPair(
Json.jFail(Json.jString,'String expected'),
jMarkerSafe,
))),
pointedVars: Json.jList(
Json.jTry(
Json.jPair(
Json.jFail(Json.jString,'String expected'),
jMarkerSafe,
))),
});
/** Safe decoder for `evaluation` */
......@@ -183,33 +183,33 @@ export const jEvaluationSafe: Json.Safe<evaluation> =
export const byEvaluation: Compare.Order<evaluation> =
Compare.byFields
<{ value: string, alarms: [ "True" | "False" | "Unknown", string ][],
pointed_vars: [ string, marker ][] }>({
pointedVars: [ string, marker ][] }>({
value: Compare.string,
alarms: Compare.array(Compare.pair(Compare.structural,Compare.string,)),
pointed_vars: Compare.array(Compare.pair(Compare.string,byMarker,)),
pointedVars: Compare.array(Compare.pair(Compare.string,byMarker,)),
});
const getValues_internal: Server.GetRequest<
{ callstack?: callstack, target: marker },
{ v_else?: evaluation, v_then?: evaluation, v_after?: evaluation,
v_before?: evaluation }
{ vElse?: evaluation, vThen?: evaluation, vAfter?: evaluation,
vBefore?: evaluation }
> = {
kind: Server.RqKind.GET,
name: 'plugins.eva.values.getValues',
input: Json.jObject({ callstack: jCallstack, target: jMarkerSafe,}),
output: Json.jObject({
v_else: jEvaluation,
v_then: jEvaluation,
v_after: jEvaluation,
v_before: jEvaluation,
vElse: jEvaluation,
vThen: jEvaluation,
vAfter: jEvaluation,
vBefore: jEvaluation,
}),
signals: [],
};
/** Abstract values for the given marker */
export const getValues: Server.GetRequest<
{ callstack?: callstack, target: marker },
{ v_else?: evaluation, v_then?: evaluation, v_after?: evaluation,
v_before?: evaluation }
{ vElse?: evaluation, vThen?: evaluation, vAfter?: evaluation,
vBefore?: evaluation }
>= getValues_internal;
/* ------------------------------------- */
......@@ -39,7 +39,7 @@ export abstract class Client {
abstract disconnect(): void;
/** Send Request */
abstract send(kind: string, id: string, request: string, data: any): void;
abstract send(kind: string, id: string, request: string, data: json): void;
/** Signal ON */
abstract sigOn(id: string): void;
......
......@@ -95,7 +95,7 @@ class SocketClient extends Client {
}
/** Send Request */
send(kind: string, id: string, request: string, data: any): void {
send(kind: string, id: string, request: string, data: json): void {
this.queue.push({ cmd: kind, id, request, data });
this._flush();
}
......@@ -134,7 +134,7 @@ class SocketClient extends Client {
// --- Low-Level Management
// --------------------------------------------------------------------------
_flush() {
_flush(): void {
if (this.running) {
this.queue.forEach((cmd) => {
this._send(Buffer.from(JSON.stringify(cmd), 'utf8'));
......@@ -143,7 +143,7 @@ class SocketClient extends Client {
}
}
_send(data: Buffer) {
_send(data: Buffer): void {
const s = this.socket;
if (s) {
const len = data.length;
......@@ -164,7 +164,7 @@ class SocketClient extends Client {
if (len < 1) return;
const hd = msg.readInt8(0);
// 'S': 83, 'L': 76, 'W': 87
const phex = hd == 83 ? 4 : hd == 76 ? 8 : 16;
const phex = hd === 83 ? 4 : hd === 76 ? 8 : 16;
if (len < phex) return;
const size = Number.parseInt(msg.slice(1, phex).toString('ascii'), 16);
const offset = phex + size;
......@@ -173,7 +173,7 @@ class SocketClient extends Client {
return msg.slice(phex, offset).toString('utf8');
}
_receive(chunk: Buffer) {
_receive(chunk: Buffer): void {
this.buffer = Buffer.concat([this.buffer, chunk]);
while (true) {
const n0 = this.buffer.length;
......@@ -181,6 +181,7 @@ class SocketClient extends Client {
const n1 = this.buffer.length;
if (data === undefined || n0 <= n1) break;
try {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const cmd: any = JSON.parse(data);
if (cmd !== null && typeof (cmd) === 'object') {
switch (cmd.res) {
......
......@@ -62,7 +62,7 @@ class ZmqClient extends Client {
}
/** Send Request */
send(kind: string, id: string, request: string, data: any): void {
send(kind: string, id: string, request: string, data: string): void {
if (this.zmqSocket) {
this.queue.push(kind, id, request, data);
this._flush();
......@@ -95,7 +95,7 @@ class ZmqClient extends Client {
/** Polling */
poll(): void {
if (this.zmqSocket && this.queue.length == 0) {
if (this.zmqSocket && this.queue.length === 0) {
this.queue.push('POLL');
}
this._flush();
......@@ -114,7 +114,7 @@ class ZmqClient extends Client {
// --- Low-Level Management
// --------------------------------------------------------------------------
_flush() {
_flush(): void {
const socket = this.zmqSocket;
if (socket) {
const cmds = this.queue;
......@@ -133,7 +133,7 @@ class ZmqClient extends Client {
}
}
_receive(resp: string[]) {
_receive(resp: string[]): void {
try {
this._decode(resp);
} catch (err) {
......@@ -145,8 +145,8 @@ class ZmqClient extends Client {
}
/* eslint-disable @typescript-eslint/indent */
_decode(resp: string[]) {
const shift = () => resp.shift() ?? '';
_decode(resp: string[]): void {
const shift = (): string => resp.shift() ?? '';
while (resp.length) {
const cmd = shift();
switch (cmd) {
......
......@@ -37,7 +37,7 @@ import { getInfo } from 'frama-c/api/kernel/ast';
// --- Information Panel
// --------------------------------------------------------------------------
export default function ASTinfo() {
export default function ASTinfo(): JSX.Element {
const buffer = React.useMemo(() => new RichTextBuffer(), []);
const [selection, updateSelection] = States.useSelection();
......@@ -52,7 +52,7 @@ export default function ASTinfo() {
}, [buffer, data]);
// Callbacks
function onTextSelection(id: string) {
function onTextSelection(id: string): void {
// For now, the only markers are functions.
const location = { fct: id };
updateSelection({ location });
......
......@@ -20,6 +20,8 @@
/* */
/* ************************************************************************ */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
// --------------------------------------------------------------------------
// --- AST Source Code
// --------------------------------------------------------------------------
......
......@@ -68,7 +68,7 @@ interface FctItemProps {
onSelection: (name: string) => void;
}
function FctItem(props: FctItemProps) {
function FctItem(props: FctItemProps): JSX.Element {
const { name, signature, main, stdlib, builtin, defined } = props.fct;
const className = classes(
main && 'globals-main',
......@@ -95,7 +95,7 @@ function FctItem(props: FctItemProps) {
// --- Globals Section(s)
// --------------------------------------------------------------------------
export default () => {
export default function Globals(): JSX.Element {
// Hooks
const [selection, updateSelection] = States.useSelection();
......@@ -117,7 +117,7 @@ export default () => {
const multipleSelectionActive = multipleSelection?.allSelections.length > 0;
const evaComputed = States.useSyncValue(computationState) === 'computed';
function isSelected(fct: functionsData) {
function isSelected(fct: functionsData): boolean {
return multipleSelection?.allSelections.some(
(l) => fct.name === l?.fct,
);
......@@ -126,21 +126,21 @@ export default () => {
// Currently selected function.
const current: undefined | string = selection?.current?.fct;
function showFunction(fct: functionsData) {
function showFunction(fct: functionsData): boolean {
const visible =
(stdlib || !fct.stdlib)
&& (builtin || !fct.builtin)
&& (undef || fct.defined)
&& (!evaOnly || !evaComputed || (fct.eva_analyzed === true))
&& (!selected || !multipleSelectionActive || isSelected(fct));
return visible || (current && fct.name === current);
return visible || (!!current && fct.name === current);
}
function onSelection(name: string) {
function onSelection(name: string): void {
updateSelection({ location: { fct: name } });
}
async function onContextMenu() {
async function onContextMenu(): Promise<void> {
const items: Dome.PopupMenuItem[] = [
{
label: 'Show Frama-C builtins',
......@@ -198,6 +198,6 @@ export default () => {
</Section>
);
};
}
// --------------------------------------------------------------------------
......@@ -28,11 +28,11 @@ import React from 'react';
import * as Toolbar from 'dome/frame/toolbars';
import * as States from 'frama-c/states';
export default function History() {
export default function History(): JSX.Element {
const [selection, updateSelection] = States.useSelection();
const doPrevSelect = () => { updateSelection('HISTORY_PREV'); };
const doNextSelect = () => { updateSelection('HISTORY_NEXT'); };
const doPrevSelect = () => void updateSelection('HISTORY_PREV');
const doNextSelect = () => void updateSelection('HISTORY_NEXT');
return (
<Toolbar.ButtonGroup>
......
......@@ -42,7 +42,7 @@ import { markerInfo } from 'frama-c/api/kernel/ast';
type LocationId = States.Location & { id: number };
export default function LocationsTable() {
export default function LocationsTable(): JSX.Element {
// Hooks
const [selection, updateSelection] = States.useSelection();
......@@ -79,7 +79,7 @@ export default function LocationsTable() {
[updateSelection],
);
const reload = () => {
const reload = (): void => {
const location = multipleSelections.allSelections[multipleSelections.index];
updateSelection({ location });
};
......
......@@ -20,6 +20,8 @@
/* */
/* ************************************************************************ */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import * as React from 'react';
import * as Dome from 'dome';
import { TitleBar } from 'ivette';
......@@ -280,7 +282,7 @@ function MessageFilter(props: { filter: State<Filter> }) {
);
}
function FilterRatio({ model }: { model: Arrays.ArrayModel<any, any> }) {
function FilterRatio<K, R>({ model }: { model: Arrays.ArrayModel<K, R> }) {
const [filtered, total] = [model.getRowCount(), model.getTotalRowCount()];
const title = `${filtered} displayed messages / ${total} total messages`;
return (
......
......@@ -20,6 +20,8 @@
/* */
/* ************************************************************************ */
/* eslint-disable @typescript-eslint/explicit-function-return-type */
// --------------------------------------------------------------------------
// --- Properties
// --------------------------------------------------------------------------
......@@ -224,9 +226,9 @@ function filterEva(p: Property) {
function filterProperty(p: Property) {
return filterStatus(p.status)
&& filterKind(p.kind)
&& filterAlarm(p.alarm)
&& filterEva(p);
&& filterKind(p.kind)
&& filterAlarm(p.alarm)
&& filterEva(p);
}
// --------------------------------------------------------------------------
......@@ -258,7 +260,7 @@ const renderFile: Renderer<Ast.source> =
const renderPriority: Renderer<boolean> =
(prio: boolean) => (prio ? <Icon id="ATTENTION" /> : null);
const renderTaint: Renderer<any> =
const renderTaint: Renderer<States.Tag> =
(taint: States.Tag) => {
let id = null;
let color = 'black';
......@@ -335,7 +337,8 @@ const byColumn: Arrays.ByColumns<Property> = {
file: Compare.byFields<Property>({ source: byFile }),
};
class PropertyModel extends Arrays.CompactModel<Json.key<'#status'>, Property> {
class PropertyModel
extends Arrays.CompactModel<Json.key<'#property'>, Property> {
private filterFun?: string;
......
......@@ -60,7 +60,7 @@ const D = new Dome.Debug('Source Code');
// The SourceCode component, producing the GUI part showing the source code
// corresponding to the selected function.
export default function SourceCode() {
export default function SourceCode(): JSX.Element {
// Hooks
const [buffer] = React.useState(() => new RichTextBuffer());
......@@ -91,7 +91,7 @@ export default function SourceCode() {
// Updating the buffer content.
const text = React.useMemo(async () => {
const onError = () => {
const onError = (): string => {
if (file)
D.error(`Fail to load source code file ${file}`);
return '';
......@@ -150,7 +150,7 @@ export default function SourceCode() {
}, [buffer, selectCallback]);
const [command] = Settings.useGlobalSettings(Preferences.EditorCommand);
async function launchEditor(_?: editor, pos?: position) {
async function launchEditor(_?: editor, pos?: position): Promise<void> {
if (file !== '') {
const selectedLine = pos ? (pos.line + 1).toString() : '1';
const selectedChar = pos ? (pos.ch + 1).toString() : '1';
......@@ -169,7 +169,7 @@ export default function SourceCode() {
}
}
async function contextMenu(editor?: editor, pos?: position) {
async function contextMenu(editor?: editor, pos?: position): Promise<void> {
if (file !== '') {
const items = [
{
......
......@@ -46,11 +46,11 @@ const emptyMessage: MessageProps = { text: '', kind: 'none' };
const GlobalMessage = new GlobalState(emptyMessage);
export function setMessage(message: MessageProps) {
export function setMessage(message: MessageProps): void {
GlobalMessage.setValue(message);
}
export default function Message() {
export default function Message(): JSX.Element {
const [message] = useGlobalState(GlobalMessage);
return (
<>
......
......@@ -133,7 +133,7 @@ async function saveSession(): Promise<void> {
return;
}
export function init() {
export function init(): void {
Dome.addMenuItem({
menu: 'File',
label: 'Set source files…',
......
......@@ -49,6 +49,9 @@ import '@fortawesome/fontawesome-free/js/all';
import style from './style.json';
import layouts from './layouts.json';
const Debug = new Dome.Debug('dive');
interface Cxtcommand {
content: string;
select: () => void;
......@@ -56,8 +59,8 @@ interface Cxtcommand {
}
interface CytoscapeExtended extends Cytoscape.Core {
cxtmenu(options: any): void;
panzoom(options: any): void;
cxtmenu(options: unknown): void;
panzoom(options: unknown): void;
}
function callstackToString(callstack: API.callstack): string {
......@@ -68,17 +71,17 @@ function buildCxtMenu(
commands: Cxtcommand[],
content?: JSX.Element,
action?: () => void,
) {
): void {
commands.push({
content: content ? renderToString(content) : '',
select: action || (() => { }),
select: action || (() => { /* Do nothing */ }),
enabled: !!action,
});
}
/* double click events for Cytoscape */
function enableDoubleClickEvents(cy: Cytoscape.Core, delay = 350) {
function enableDoubleClickEvents(cy: Cytoscape.Core, delay = 350): void {
let last: Cytoscape.EventObject | undefined;
cy.on('click', (e) => {
if (last && last.target === e.target &&
......@@ -145,7 +148,7 @@ class Dive {
this.refresh();
}
onCxtMenu(node: Cytoscape.NodeSingular) {
onCxtMenu(node: Cytoscape.NodeSingular): Cxtcommand[] {
const data = node.data();
const commands = [] as Cxtcommand[];
buildCxtMenu(commands,
......@@ -167,7 +170,7 @@ class Dive {
return commands;
}
remove(node: Cytoscape.NodeSingular) {
remove(node: Cytoscape.NodeSingular): void {
const parent = node.parent();
node.remove();
this.cy.$id(`${node.id()}-more`).remove();
......@@ -217,9 +220,12 @@ class Dive {
trigger: 'manual',
appendTo: document.body,
lazy: false,
// Cytoscape extensions are not typed yet
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onCreate: (instance: any) => {
const { popperInstance } = instance;
if (popperInstance) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
popperInstance.reference = (node as any).popperRef();
}
},
......@@ -271,15 +277,15 @@ class Dive {
});
}
/* eslint-disable no-restricted-syntax */
receiveGraph(data: any): Cytoscape.CollectionReturnValue {
receiveGraph(data: API.graphData): Cytoscape.CollectionReturnValue {
let newNodes = this.cy.collection();
for (const node of data.nodes) {
let stops = undefined;
if (typeof node.range === 'number')
node.stops = `0% ${node.range}% ${node.range}% 100%`;
stops = `0% ${node.range}% ${node.range}% 100%`;
let ele = this.cy.$id(node.id);
let ele = this.cy.$id(node.id.toString());
if (ele.nonempty()) {
ele.removeData();
ele.data(node);
......@@ -294,7 +300,7 @@ class Dive {
ele = this.cy.add({
group: 'nodes',
data: { ...node, parent },
data: { ...(node as { [k: string]: unknown }), stops, parent },
classes: 'new',
});
this.addTips(ele);
......@@ -320,10 +326,14 @@ class Dive {
}
for (const dep of data.deps) {
const src = this.cy.$id(dep.src);
const dst = this.cy.$id(dep.dst);
const src = this.cy.$id(dep.src.toString());
const dst = this.cy.$id(dep.dst.toString());
this.cy.add({
data: { ...dep, source: dep.src, target: dep.dst },
data: {
...(dep as { [k: string]: unknown }),
source: dep.src,
target: dep.dst
},
group: 'edges',
classes: src?.hasClass('new') || dst?.hasClass('new') ? 'new' : '',
});
......@@ -332,11 +342,11 @@ class Dive {
return newNodes;
}
receiveData(data: any): Cytoscape.NodeSingular {
receiveData(data: API.diffData): Cytoscape.NodeSingular | undefined {
this.cy.startBatch();
for (const id of data.sub)
this.remove(this.cy.$id(id));
this.remove(this.cy.$id(id.toString()));
const newNodes = this.receiveGraph(data.add);
......@@ -344,7 +354,8 @@ class Dive {
this.recomputeLayout(newNodes);
return this.cy.$id(data.root);
const root = data.root;
return root ? this.cy.$id(root.toString()) : undefined;
}
get layout(): string {
......@@ -383,10 +394,10 @@ class Dive {
}
}
async exec<In, Out>(
request: Server.ExecRequest<In, Out>,
param: In,
) {
async exec<In>(
request: Server.ExecRequest<In, API.diffData | null>,
param: In): Promise<Cytoscape.NodeSingular | undefined>
{
try {
if (Server.isRunning()) {
await this.setMode();
......@@ -396,13 +407,13 @@ class Dive {
}
}
catch (err) {
console.error(err);
Debug.error(err);
}
return null;
return undefined;
}
async refresh() {
async refresh(): Promise<void> {
try {
if (Server.isRunning()) {
const data = await Server.send(API.graph, {});
......@@ -413,11 +424,11 @@ class Dive {
}
}
catch (err) {
console.error(err);
Debug.error(err);
}
}
static async setWindow(window: any): Promise<void> {
static async setWindow(window: API.explorationWindow): Promise<void> {
if (Server.isRunning())
await Server.send(API.window, window);
}
......@@ -433,7 +444,7 @@ class Dive {
case 'overview':
await Dive.setWindow({
perception: { backward: 4, forward: 1 },
horizon: { backward: null, forward: null },
horizon: { backward: undefined, forward: undefined },
});
break;
default: /* This is useless and impossible if the program is correctly
......@@ -446,13 +457,13 @@ class Dive {
this.exec(API.clear, null);
}
async add(marker: string) {
async add(marker: string): Promise<void> {
const node = await this.exec(API.add, marker);
if (node)
this.updateNodeSelection(node);
}
async explore(node: Cytoscape.NodeSingular) {
async explore(node: Cytoscape.NodeSingular): Promise<void> {
const id = parseInt(node.id(), 10);
if (id)
await this.exec(API.explore, id);
......@@ -470,7 +481,7 @@ class Dive {
this.exec(API.hide, id);
}
async clickNode(node: Cytoscape.NodeSingular) {
async clickNode(node: Cytoscape.NodeSingular): Promise<void> {
this.updateNodeSelection(node);
await this.explore(node);
......@@ -484,11 +495,13 @@ class Dive {
node.unselectify();
}
doubleClickNode(node: Cytoscape.NodeSingular) {
doubleClickNode(node: Cytoscape.NodeSingular): void {
this.cy.animate({ fit: { eles: node, padding: 10 } });
}
selectLocation(location: States.Location | undefined, doExplore: boolean) {
selectLocation(
location: States.Location | undefined,
doExplore: boolean): void {
if (!location) {
// Reset whole graph if no location is selected.
this.clear();
......@@ -506,7 +519,7 @@ class Dive {
}
updateNodeSelection(node: Cytoscape.NodeSingular): void {
const hasOrigin = (ele: Cytoscape.NodeSingular) => (
const hasOrigin = (ele: Cytoscape.NodeSingular): boolean => (
_.some(ele.data().origins, this.selectedLocation)
);
this.cy.$(':selected').forEach(unselect);
......@@ -520,7 +533,7 @@ class Dive {
}
}
function GraphView() {
function GraphView(): JSX.Element {
// Hooks
const [dive, setDive] = useState(() => new Dive());
......@@ -530,7 +543,7 @@ function GraphView() {
const [selectionMode, setSelectionMode] =
Dome.useStringSettings('dive.selectionMode', 'follow');
function setCy(cy: Cytoscape.Core) {
function setCy(cy: Cytoscape.Core): void {
if (cy !== dive.cy)
setDive(new Dive(cy));
}
......@@ -560,30 +573,30 @@ function GraphView() {
}, [dive, lock, selection, updateSelection]);
// Layout selection
const selectLayout = (layout?: string) => {
const selectLayout = (layout?: string): void => {
if (layout) {
dive.layout = layout;
}
};
const layoutsNames = ['cose-bilkent', 'dagre', 'cola', 'klay'];
const layoutItem = (id: string) => (
const layoutItem = (id: string): Dome.PopupMenuItem => (
{ id, label: id, checked: (id === dive.layout) }
);
const layoutMenu = () => {
const layoutMenu = (): void => {
Dome.popupMenu(layoutsNames.map(layoutItem), selectLayout);
};
// Selection mode
const selectMode = (id?: string) => id && setSelectionMode(id);
const selectMode = (id?: string) => void (id && setSelectionMode(id));
const modes = [
{ id: 'follow', label: 'Follow selection' },
{ id: 'add', label: 'Add selection to the graph' },
];
const checkMode =
(item: { id: string; label: string }) => (
(item: { id: string; label: string }): Dome.PopupMenuItem => (
{ checked: item.id === selectionMode, ...item }
);
const modeMenu = () => {
const modeMenu = (): void => {
Dome.popupMenu(modes.map(checkMode), selectMode);
};
......
module.exports = {
root: true,
overrides: [
{
files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
excludedFiles: 'Summary.tsx|Coverage.tsx|CoverageMeter.tsx',
extends: ["../../../../.eslintrc.js"]
},
{
files: ['Summary.tsx','Coverage.tsx'],
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
"@typescript-eslint/explicit-function-return-type": [
"error",
{ allowExpressions: true }
]
}
}
]
};
......@@ -32,7 +32,7 @@ import * as States from 'frama-c/states';
import * as Eva from 'frama-c/api/plugins/eva/general';
import CoverageMeter, { percent } from './CoverageMeter';
type key = Json.key<'#fct'>;
type key = Json.key<'#fundec'>;
type stats = Eva.functionStatsData;
// --- Coverage Table ---
......
......@@ -23,17 +23,22 @@
import React from 'react';
import { Meter } from 'dome/controls/displays';
export interface CoverageProps {
export interface Coverage {
reachable: number;
dead: number;
}
export function percent(coverage: CoverageProps): string {
export interface CoverageProps {
coverage: Coverage;
}
export function percent(coverage: Coverage): string {
const q = coverage.reachable / (coverage.reachable + coverage.dead);
return `${(q * 100).toFixed(1)}%`;
}
export default function(props: { coverage: CoverageProps }) {
export default function CoverageMeter(props: CoverageProps): JSX.Element {
const { reachable, dead } = props.coverage;
const total = reachable + dead;
......
......@@ -98,15 +98,15 @@ export type Evaluation = Values.evaluation;
const emptyEvaluation: Values.evaluation = {
value: '',
alarms: [],
pointed_vars: [],
pointedVars: [],
};
export interface EvaValues {
errors?: string;
v_before: Evaluation;
v_after?: Evaluation;
v_then?: Evaluation;
v_else?: Evaluation;
vBefore: Evaluation;
vAfter?: Evaluation;
vThen?: Evaluation;
vElse?: Evaluation;
size: Size;
}
......@@ -131,7 +131,7 @@ export class ValueCache {
this.state = state;
}
clear() {
clear(): void {
this.smax = EMPTY;
this.probes.clear();
this.stacks.clear();
......@@ -141,17 +141,17 @@ export class ValueCache {
// --- Cached Measures
getMaxSize() { return this.smax; }
getMaxSize(): Size { return this.smax; }
getProbeSize(target: Ast.marker) {
getProbeSize(target: Ast.marker): Size {
return this.probes.get(target) ?? EMPTY;
}
private static stackKey(fct: string, callstack: Values.callstack) {
private static stackKey(fct: string, callstack: Values.callstack): string {
return `${fct}::${callstack}`;
}
getStackSize(fct: string, callstack: Values.callstack) {
getStackSize(fct: string, callstack: Values.callstack): Size {
const key = ValueCache.stackKey(fct, callstack);
return this.stacks.get(key) ?? EMPTY;
}
......@@ -166,7 +166,7 @@ export class ValueCache {
const cache = this.vcache;
const cached = cache.get(key);
if (cached) return cached;
const newValue: EvaValues = { v_before: emptyEvaluation, size: EMPTY };
const newValue: EvaValues = { vBefore: emptyEvaluation, size: EMPTY };
if (callstack !== undefined && fct === undefined)
return newValue;
// callstack !== undefined ==> fct !== undefined)
......@@ -175,10 +175,10 @@ export class ValueCache {
.send(Values.getValues, { target: marker, callstack })
.then((r) => {
newValue.errors = undefined;
if (r.v_before) newValue.v_before = r.v_before;
newValue.v_after = r.v_after;
newValue.v_then = r.v_then;
newValue.v_else = r.v_else;
if (r.vBefore) newValue.vBefore = r.vBefore;
newValue.vAfter = r.vAfter;
newValue.vThen = r.vThen;
newValue.vElse = r.vElse;
if (this.updateLayout(marker, fct, callstack, newValue))
this.state.forceLayout();
else
......@@ -200,10 +200,10 @@ export class ValueCache {
v: EvaValues,
): boolean {
// measuring cell
let s = sizeof(v.v_before.value);
s = addS(s, v.v_after?.value);
s = addS(s, v.v_then?.value);
s = addS(s, v.v_else?.value);
let s = sizeof(v.vBefore.value);
s = addS(s, v.vAfter?.value);
s = addS(s, v.vThen?.value);
s = addS(s, v.vElse?.value);
v.size = s;
// max cell size
const { smax } = this;
......
......@@ -44,7 +44,7 @@ export class DiffBuffer {
this.push = this.push.bind(this);
}
clear() {
clear(): void {
this.added = false;
this.removed = false;
this.value = '';
......@@ -52,7 +52,7 @@ export class DiffBuffer {
this.contents = [];
}
push(c: Change) {
push(c: Change): void {
if (!c.added && !c.removed) {
this.flush();
this.value += c.value;
......@@ -66,7 +66,7 @@ export class DiffBuffer {
}
}
private flush() {
private flush(): void {
const { value, added, removed } = this;
if (added && removed) {
if (value) {
......@@ -99,7 +99,7 @@ export class DiffBuffer {
return React.Children.toArray(this.contents);
}
getScratch() {
getScratch(): string {
this.flush();
return this.scratch;
}
......@@ -115,7 +115,7 @@ export interface Diff2Props {
diff: string;
}
export function Diff2(props: Diff2Props) {
export function Diff2(props: Diff2Props): JSX.Element {
const { text, diff } = props;
const contents = React.useMemo<React.ReactNode>(() => {
if (text === diff) return text;
......@@ -137,7 +137,7 @@ export interface Diff3Props {
diffB: string;
}
export function Diff3(props: Diff3Props) {
export function Diff3(props: Diff3Props): JSX.Element {
const { text, diffA, diffB } = props;
const contents = React.useMemo<React.ReactNode>(() => {
if (text === diffA && text === diffB) return text;
......@@ -161,7 +161,8 @@ export interface DiffProps {
diff2?: string;
}
export function Diff(props: DiffProps) {
export function Diff(props: DiffProps): JSX.Element | null {
const { text, diff, diff2 } = props;
if (text === undefined)
return null;
......