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
Commits on Source (209)
Showing
with 550 additions and 280 deletions
......@@ -280,6 +280,7 @@ DISTRIB_FILES:=\
share/analysis-scripts/parse-coverage.sh \
share/analysis-scripts/print_callgraph.py \
share/analysis-scripts/prologue.mk \
share/analysis-scripts/pyproject.toml \
share/analysis-scripts/README.md \
share/analysis-scripts/results_display.py \
share/analysis-scripts/script_for_creduce_fatal.sh \
......@@ -342,7 +343,7 @@ DISTRIB_TESTS=$(shell find \
-o -path 'tests/crowbar/*' -type d \! -name input -prune -false \
-o -type f \! -name "*\.log" \! -name "*\.o" \
\! -name '*~' \! -name "*\.cm*" \! -name "*.sav" \
-perm /u+w | sed -e 's/ /@/g')
-perm -u+w | sed -e 's/ /@/g')
# files that are needed to compile API documentation of external plugins
DOC_GEN_FILES:=$(addprefix doc/code/,\
......@@ -585,7 +586,7 @@ KERNEL_CMO=\
src/kernel_services/ast_printing/description.cmo \
src/kernel_services/abstract_interp/lattice_messages.cmo \
src/kernel_services/abstract_interp/abstract_interp.cmo \
src/kernel_services/abstract_interp/bottom.cmo \
src/kernel_services/abstract_interp/lattice_bounds.cmo \
src/kernel_services/abstract_interp/int_Base.cmo \
src/kernel_services/analysis/bit_utils.cmo \
src/kernel_services/abstract_interp/fc_float.cmo \
......@@ -864,7 +865,7 @@ endif
PLUGIN_CMO:= partitioning/split_strategy domains/domain_mode self parameters \
utils/eva_audit utils/eva_perf utils/eva_annotations \
utils/eva_dynamic utils/eva_utils utils/red_statuses \
utils/mark_noresults \
utils/active_behaviors \
utils/widen_hints_ext utils/widen \
partitioning/split_return \
partitioning/per_stmt_slevel \
......@@ -898,23 +899,24 @@ PLUGIN_CMO:= partitioning/split_strategy domains/domain_mode self parameters \
domains/cvalue/builtins_watchpoint \
domains/cvalue/builtins_float domains/cvalue/builtins_split \
domains/inout_domain \
legacy/eval_terms legacy/eval_annots \
domains/powerset engine/transfer_logic \
legacy/eval_terms \
domains/cvalue/cvalue_transfer domains/cvalue/cvalue_init \
domains/cvalue/cvalue_specification \
domains/cvalue/cvalue_domain \
utils/eva_results \
domains/powerset \
partitioning/auto_loop_unroll \
partitioning/partition partitioning/partitioning_parameters \
partitioning/partitioning_index partitioning/trace_partitioning \
engine/recursion engine/function_calls legacy/eval_annots \
engine/subdivided_evaluation engine/evaluation engine/abstractions \
engine/recursion engine/transfer_stmt engine/transfer_specification \
engine/transfer_logic engine/transfer_stmt engine/transfer_specification \
engine/mem_exec engine/iterator engine/initialization \
engine/compute_functions engine/analysis register \
domains/taint_domain \
$(APRON_CMO) $(NUMERORS_CMO) \
api/general_requests api/values_request \
utils/unit_tests utils/results
utils/eva_results \
utils/results api/general_requests api/values_request \
utils/unit_tests
PLUGIN_CMI:= values/abstract_value values/abstract_location \
domains/abstract_domain domains/simpler_domains
PLUGIN_DEPENDENCIES:=Server
......@@ -1995,6 +1997,7 @@ install:: install-lib-$(OCAMLBEST)
share/analysis-scripts/normalize_jcdb.py \
share/analysis-scripts/parse-coverage.sh \
share/analysis-scripts/prologue.mk \
share/analysis-scripts/pyproject.toml \
share/analysis-scripts/README.md \
share/analysis-scripts/results_display.py \
share/analysis-scripts/script_for_creduce_fatal.sh \
......@@ -2098,7 +2101,6 @@ uninstall::
HEADER_SPEC := $(DEFAULT_HEADER_SPEC)
# The list can be extended by external plugins using PLUGIN_HEADER_SPEC variable
HEADER_SPEC += $(PLUGIN_HEADER_SPEC_LIST)
HEADER_SPEC += ivette/./headers/header_spec.txt
# Default list of header specification files can be overloaded.
HEADER_SPEC_FILE?=$(HEADER_SPEC)
......@@ -2480,10 +2482,10 @@ DISTRIB_FILES += $(wildcard $(PLUGIN_DISTRIBUTED_LIST) \
DISTRIB_FILES:=$(filter-out $(GENERATED) $(PLUGIN_GENERATED_LIST),\
$(DISTRIB_FILES))
sinclude ivette/Makefile.distrib
DISTRIB_TESTS += $(wildcard $(PLUGIN_DIST_TESTS_LIST))
sinclude ivette/Makefile.distrib
sinclude ivette/Makefile.plugins
SPECIFIED_OPEN_SOURCE:=$(OPEN_SOURCE)
OPEN_SOURCE ?= no
......
......@@ -143,7 +143,7 @@
##########
| ".*\.py" -> frame open: "#" line: "#" close:"#"
| ".*\.py" -> skip multiline_match: "#!.*" multiline_match: "#-\*-.*"
| ".*\.py" -> skip multiline_match: "#!.*" multiline_match: "# -\*-.*"
##############
# Misc files #
......
......@@ -139,6 +139,7 @@ share/analysis-scripts/normalize_jcdb.py: CEA_LGPL
share/analysis-scripts/parse-coverage.sh: .ignore
share/analysis-scripts/print_callgraph.py: CEA_LGPL
share/analysis-scripts/prologue.mk: CEA_LGPL
share/analysis-scripts/pyproject.toml: .ignore
share/analysis-scripts/README.md: .ignore
share/analysis-scripts/results_display.py: CEA_LGPL
share/analysis-scripts/script_for_creduce_fatal.sh: .ignore
......@@ -479,8 +480,6 @@ src/kernel_services/abstract_interp/abstract_offset.ml: CEA_LGPL
src/kernel_services/abstract_interp/abstract_offset.mli: CEA_LGPL
src/kernel_services/abstract_interp/base.ml: CEA_LGPL
src/kernel_services/abstract_interp/base.mli: CEA_LGPL
src/kernel_services/abstract_interp/bottom.ml: CEA_LGPL
src/kernel_services/abstract_interp/bottom.mli: CEA_LGPL
src/kernel_services/abstract_interp/eva_lattice_type.mli: CEA_LGPL
src/kernel_services/abstract_interp/fc_float.ml: CEA_LGPL
src/kernel_services/abstract_interp/fc_float.mli: CEA_LGPL
......@@ -503,6 +502,8 @@ src/kernel_services/abstract_interp/int_val.ml: CEA_LGPL
src/kernel_services/abstract_interp/int_val.mli: CEA_LGPL
src/kernel_services/abstract_interp/ival.ml: CEA_LGPL
src/kernel_services/abstract_interp/ival.mli: CEA_LGPL
src/kernel_services/abstract_interp/lattice_bounds.ml: CEA_LGPL
src/kernel_services/abstract_interp/lattice_bounds.mli: CEA_LGPL
src/kernel_services/abstract_interp/lattice_messages.ml: CEA_LGPL
src/kernel_services/abstract_interp/lattice_messages.mli: CEA_LGPL
src/kernel_services/abstract_interp/lattice_type.mli: CEA_LGPL
......@@ -1443,6 +1444,8 @@ src/plugins/value/engine/compute_functions.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/engine/compute_functions.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/engine/evaluation.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/engine/evaluation.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/engine/function_calls.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/engine/function_calls.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/engine/initialization.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/engine/initialization.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/engine/iterator.ml: CEA_LGPL_OR_PROPRIETARY
......@@ -1497,6 +1500,8 @@ src/plugins/value/partitioning/trace_partitioning.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/partitioning/trace_partitioning.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/abstract.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/abstract.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/active_behaviors.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/active_behaviors.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/backward_formals.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/backward_formals.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/eva_annotations.ml: CEA_LGPL_OR_PROPRIETARY
......@@ -1517,8 +1522,6 @@ src/plugins/value/utils/red_statuses.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/red_statuses.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/library_functions.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/library_functions.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/mark_noresults.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/mark_noresults.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/results.ml: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/results.mli: CEA_LGPL_OR_PROPRIETARY
src/plugins/value/utils/structure.ml: CEA_LGPL_OR_PROPRIETARY
......
......@@ -14,5 +14,6 @@ yarn-error.log
/doc/html
/src/renderer/loader.ts
/src/dome/doc/guides/icons.md
/Makefile.plugins
# --------------------------------------------------------------------------
......@@ -31,7 +31,7 @@ DOME_CUSTOM_ENTRIES= yes
COPYRIGHT=CEA LIST / LSL
# --------------------------------------------------------------------------
.PHONY: all app dev pkg doc serve dist lint fixlint
.PHONY: all app dev pkg doc serve dist lint fixlint checkcase
all: pkg lint app
......@@ -39,11 +39,22 @@ app: dome-app
dev: dome-dev
dist: dome-dist
lint: dome-pkg dome-templ
lint: dome-pkg dome-templ checkcase
@echo "[Ivette] running typechecker & linter"
yarn run typecheck
yarn run lint
# In case-insensitive filesystems (macOS/Windows), import statements and
# filenames can have issues due to case differences
checkcase:
@echo "[Ivette] check case issues in imported filenames"
@err=0 ; for f in `find src | sed -E 's/(.ts|.tsx|.js|.jsx|.css|.json)$$//' | sort -f | uniq -di` ;\
do \
err=1; \
echo " - ambiguous $$f.*"; \
done ;\
exit $$err
tsc: dome-pkg dome-templ
@echo "[Ivette] running typechecker & linter (with cache & fix mode)"
yarn run typecheck
......@@ -72,37 +83,10 @@ $(LOADER): $(PACKAGES) ./configure.js ./Makefile
# --- Frama-C Source Distrib
# --------------------------------------------------------------------------
.PHONY: update-distrib-files update-distrib-plugins
SRC_DISTRIB=Makefile.distrib
SRC_HEADERS=headers/header_spec.txt
.PHONY: update-distrib-files
update-distrib-files:
@echo "Generating $(SRC_DISTRIB)"
@rm -f $(SRC_DISTRIB)
@rm -f $(SRC_HEADERS)
@for f in `git ls-files .` ;\
do \
echo "DISTRIB_FILES += ivette/$$f" >> $(SRC_DISTRIB) ;\
headers/register.sh "$$f" >> $(SRC_HEADERS) ; \
done
@chmod a-w $(SRC_DISTRIB)
@chmod a-w $(SRC_HEADERS)
update-distrib-plugins: update-distrib-files
@chmod a+w $(SRC_DISTRIB)
@chmod a+w $(SRC_HEADERS)
@for repo in `find . -type d -name ".git"` ;\
do \
echo "Distributing $$repo" ;\
for f in `git -C $$repo ls-files .` ;\
do \
echo "DISTRIB_FILES += ivette/$$f" >> $(SRC_DISTRIB) ;\
headers/register.sh "$$f" >> $(SRC_HEADERS) ; \
done \
done
@chmod a-w $(SRC_DISTRIB)
@chmod a-w $(SRC_HEADERS)
./distrib.sh
# --------------------------------------------------------------------------
# --- Frama-C API
......@@ -153,7 +137,9 @@ doc: $(NODEBIN)/typedoc icons
@rm -fr doc/html
@yarn run typedoc $(DOCFILES)
@echo "\n[Ivette] main page"
@echo " file://$(PWD)/doc/html/index.html"
@echo ""
@echo " file://$(PWD)/ivette/doc/html/index.html"
@echo ""
$(NODEBIN)/%:
@echo "[Node] install package $*"
......
HEADER_SPEC += ivette/./headers/header_spec.txt
DISTRIB_FILES += ivette/.babelrc
DISTRIB_FILES += ivette/.dome-pkg-app.lock
DISTRIB_FILES += ivette/.dome-pkg-dev.lock
......@@ -7,15 +8,13 @@ DISTRIB_FILES += ivette/.gitignore
DISTRIB_FILES += ivette/CONTRIBUTING.md
DISTRIB_FILES += ivette/INSTALL.md
DISTRIB_FILES += ivette/Makefile
DISTRIB_FILES += ivette/Makefile.distrib
DISTRIB_FILES += ivette/README.md
DISTRIB_FILES += ivette/configure.js
DISTRIB_FILES += ivette/distrib.sh
DISTRIB_FILES += ivette/doc/pandoc/href.lua
DISTRIB_FILES += ivette/doc/pandoc/index.json
DISTRIB_FILES += ivette/doc/pandoc/template.html
DISTRIB_FILES += ivette/electron-webpack.json
DISTRIB_FILES += ivette/headers/header_spec.txt
DISTRIB_FILES += ivette/headers/register.sh
DISTRIB_FILES += ivette/package.json
DISTRIB_FILES += ivette/src/dome/.gitignore
DISTRIB_FILES += ivette/src/dome/CONTRIBUTING.md
......@@ -93,6 +92,7 @@ DISTRIB_FILES += ivette/src/dome/renderer/controls/gallery.json
DISTRIB_FILES += ivette/src/dome/renderer/controls/icons.tsx
DISTRIB_FILES += ivette/src/dome/renderer/controls/labels.tsx
DISTRIB_FILES += ivette/src/dome/renderer/controls/style.css
DISTRIB_FILES += ivette/src/dome/renderer/dark.css
DISTRIB_FILES += ivette/src/dome/renderer/data/compare.ts
DISTRIB_FILES += ivette/src/dome/renderer/data/json.ts
DISTRIB_FILES += ivette/src/dome/renderer/data/library.js
......@@ -112,15 +112,18 @@ DISTRIB_FILES += ivette/src/dome/renderer/layout/forms.tsx
DISTRIB_FILES += ivette/src/dome/renderer/layout/grids.js
DISTRIB_FILES += ivette/src/dome/renderer/layout/splitters.tsx
DISTRIB_FILES += ivette/src/dome/renderer/layout/style.css
DISTRIB_FILES += ivette/src/dome/renderer/light.css
DISTRIB_FILES += ivette/src/dome/renderer/style.css
DISTRIB_FILES += ivette/src/dome/renderer/table/arrays.ts
DISTRIB_FILES += ivette/src/dome/renderer/table/models.ts
DISTRIB_FILES += ivette/src/dome/renderer/table/style.css
DISTRIB_FILES += ivette/src/dome/renderer/table/views.tsx
DISTRIB_FILES += ivette/src/dome/renderer/text/buffers.ts
DISTRIB_FILES += ivette/src/dome/renderer/text/dark-code.css
DISTRIB_FILES += ivette/src/dome/renderer/text/editors.tsx
DISTRIB_FILES += ivette/src/dome/renderer/text/pages.tsx
DISTRIB_FILES += ivette/src/dome/renderer/text/style.css
DISTRIB_FILES += ivette/src/dome/renderer/themes.tsx
DISTRIB_FILES += ivette/src/dome/template/Application.js
DISTRIB_FILES += ivette/src/dome/template/Preferences.js
DISTRIB_FILES += ivette/src/dome/template/babelrc.json
......@@ -150,6 +153,7 @@ DISTRIB_FILES += ivette/src/frama-c/kernel/Globals.tsx
DISTRIB_FILES += ivette/src/frama-c/kernel/History.tsx
DISTRIB_FILES += ivette/src/frama-c/kernel/Locations.tsx
DISTRIB_FILES += ivette/src/frama-c/kernel/Messages.tsx
DISTRIB_FILES += ivette/src/frama-c/kernel/PivotTable-style.css
DISTRIB_FILES += ivette/src/frama-c/kernel/PivotTable.tsx
DISTRIB_FILES += ivette/src/frama-c/kernel/Properties.tsx
DISTRIB_FILES += ivette/src/frama-c/kernel/SourceCode.tsx
......@@ -175,26 +179,17 @@ DISTRIB_FILES += ivette/src/frama-c/plugins/eva/CoverageMeter.tsx
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/Summary.tsx
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/api/general/index.ts
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/api/values/index.ts
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/cells.ts
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/diffed.tsx
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/index.tsx
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/layout.ts
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/model.ts
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/pkg.json
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/probeinfos.tsx
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/probes.ts
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/sized.tsx
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/stacks.ts
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/style.css
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/summary.css
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/valueinfos.tsx
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/style_summary.css
DISTRIB_FILES += ivette/src/frama-c/plugins/eva/valuetable.tsx
DISTRIB_FILES += ivette/src/frama-c/plugins/pivot/api/general/index.ts
DISTRIB_FILES += ivette/src/frama-c/plugins/studia/api/studia/index.ts
DISTRIB_FILES += ivette/src/frama-c/react-pivottable.d.ts
DISTRIB_FILES += ivette/src/frama-c/richtext.tsx
DISTRIB_FILES += ivette/src/frama-c/server.ts
DISTRIB_FILES += ivette/src/frama-c/states.ts
DISTRIB_FILES += ivette/src/frama-c/utils.ts
DISTRIB_FILES += ivette/src/ivette/index.tsx
DISTRIB_FILES += ivette/src/ivette/prefs.tsx
DISTRIB_FILES += ivette/src/ivette/sandbox.tsx
......
#!/bin/sh -e
# --------------------------------------------------------------------------
# --- Generate Files for Ivette Distribution
# --------------------------------------------------------------------------
Distribute() {
repo=$1
Distrib=$repo/Makefile.distrib
Headers=$repo/headers/header_spec.txt
rm -f $Distrib
rm -f $Headers
mkdir -p $1/headers
if [ "$repo" == "." ]
then
src=ivette
else
src=ivette/$repo
fi
echo "Distributing $src"
echo "HEADER_SPEC += $src/./headers/header_spec.txt" >> $Distrib
for f in $(git -C $repo ls-files .)
do
case $f in
Makefile.distrib | headers/* )
;;
*)
echo "DISTRIB_FILES += $src/$f" >> $Distrib
case $f in
*.sh | *.json | */dome/doc/* | configure.js | .* | webpack*.js )
echo "$f: .ignore" >> $Headers
;;
*Make* | *.js* | *.ts* | *.ml*)
echo "$f: CEA_LGPL" >> $Headers
;;
*)
echo "$f: .ignore" >> $Headers
;;
esac
esac
done
chmod a-w $Distrib
chmod a-w $Headers
if [ "$repo" != "." ]
then
echo "include ivette/$Distrib" >> Makefile.plugins
fi
}
## Distribute Core Ivette Files
Distribute .
## Distribute Ivette Plugins Files
rm -f Makefile.plugins
for rgit in $(find src -type d -name ".git")
do
Distribute $(dirname $rgit)
done
if [ -f Makefile.plugins ]
then
chmod a-w Makefile.plugins
fi
## Terminated.
exit 0
# --------------------------------------------------------------------------
......@@ -7,15 +7,13 @@
CONTRIBUTING.md: .ignore
INSTALL.md: .ignore
Makefile: CEA_LGPL
Makefile.distrib: .ignore
README.md: .ignore
configure.js: .ignore
distrib.sh: .ignore
doc/pandoc/href.lua: .ignore
doc/pandoc/index.json: .ignore
doc/pandoc/template.html: .ignore
electron-webpack.json: .ignore
headers/header_spec.txt: .ignore
headers/register.sh: .ignore
package.json: .ignore
src/dome/.gitignore: .ignore
src/dome/CONTRIBUTING.md: .ignore
......@@ -93,6 +91,7 @@ src/dome/renderer/controls/gallery.json: .ignore
src/dome/renderer/controls/icons.tsx: CEA_LGPL
src/dome/renderer/controls/labels.tsx: CEA_LGPL
src/dome/renderer/controls/style.css: .ignore
src/dome/renderer/dark.css: .ignore
src/dome/renderer/data/compare.ts: CEA_LGPL
src/dome/renderer/data/json.ts: CEA_LGPL
src/dome/renderer/data/library.js: CEA_LGPL
......@@ -112,15 +111,18 @@ src/dome/renderer/layout/forms.tsx: CEA_LGPL
src/dome/renderer/layout/grids.js: CEA_LGPL
src/dome/renderer/layout/splitters.tsx: CEA_LGPL
src/dome/renderer/layout/style.css: .ignore
src/dome/renderer/light.css: .ignore
src/dome/renderer/style.css: .ignore
src/dome/renderer/table/arrays.ts: CEA_LGPL
src/dome/renderer/table/models.ts: CEA_LGPL
src/dome/renderer/table/style.css: .ignore
src/dome/renderer/table/views.tsx: CEA_LGPL
src/dome/renderer/text/buffers.ts: CEA_LGPL
src/dome/renderer/text/dark-code.css: .ignore
src/dome/renderer/text/editors.tsx: CEA_LGPL
src/dome/renderer/text/pages.tsx: CEA_LGPL
src/dome/renderer/text/style.css: .ignore
src/dome/renderer/themes.tsx: CEA_LGPL
src/dome/template/Application.js: CEA_LGPL
src/dome/template/Preferences.js: CEA_LGPL
src/dome/template/babelrc.json: .ignore
......@@ -150,6 +152,7 @@ src/frama-c/kernel/Globals.tsx: CEA_LGPL
src/frama-c/kernel/History.tsx: CEA_LGPL
src/frama-c/kernel/Locations.tsx: CEA_LGPL
src/frama-c/kernel/Messages.tsx: CEA_LGPL
src/frama-c/kernel/PivotTable-style.css: .ignore
src/frama-c/kernel/PivotTable.tsx: CEA_LGPL
src/frama-c/kernel/Properties.tsx: CEA_LGPL
src/frama-c/kernel/SourceCode.tsx: CEA_LGPL
......@@ -175,26 +178,17 @@ src/frama-c/plugins/eva/CoverageMeter.tsx: CEA_LGPL
src/frama-c/plugins/eva/Summary.tsx: CEA_LGPL
src/frama-c/plugins/eva/api/general/index.ts: CEA_LGPL
src/frama-c/plugins/eva/api/values/index.ts: CEA_LGPL
src/frama-c/plugins/eva/cells.ts: CEA_LGPL
src/frama-c/plugins/eva/diffed.tsx: CEA_LGPL
src/frama-c/plugins/eva/index.tsx: CEA_LGPL
src/frama-c/plugins/eva/layout.ts: CEA_LGPL
src/frama-c/plugins/eva/model.ts: CEA_LGPL
src/frama-c/plugins/eva/pkg.json: .ignore
src/frama-c/plugins/eva/probeinfos.tsx: CEA_LGPL
src/frama-c/plugins/eva/probes.ts: CEA_LGPL
src/frama-c/plugins/eva/sized.tsx: CEA_LGPL
src/frama-c/plugins/eva/stacks.ts: CEA_LGPL
src/frama-c/plugins/eva/style.css: .ignore
src/frama-c/plugins/eva/summary.css: .ignore
src/frama-c/plugins/eva/valueinfos.tsx: CEA_LGPL
src/frama-c/plugins/eva/style_summary.css: .ignore
src/frama-c/plugins/eva/valuetable.tsx: CEA_LGPL
src/frama-c/plugins/pivot/api/general/index.ts: CEA_LGPL
src/frama-c/plugins/studia/api/studia/index.ts: CEA_LGPL
src/frama-c/react-pivottable.d.ts: CEA_LGPL
src/frama-c/richtext.tsx: CEA_LGPL
src/frama-c/server.ts: CEA_LGPL
src/frama-c/states.ts: CEA_LGPL
src/frama-c/utils.ts: CEA_LGPL
src/ivette/index.tsx: CEA_LGPL
src/ivette/prefs.tsx: CEA_LGPL
src/ivette/sandbox.tsx: CEA_LGPL
......
#!/bin/sh
case "$1" in
Makefile.distrib | *.json | src/dome/doc/* | */.eslintrc.js )
echo "$1: .ignore"
;;
*Make* | src/*/*.js* | src/*/*.ts* | src/*/*.ml*)
echo "$1: CEA_LGPL"
;;
*)
echo "$1: .ignore"
;;
esac
......@@ -13,12 +13,12 @@
},
"devDependencies": {
"@babel/cli": "",
"@babel/core": "^7.16.0",
"@babel/core": "^7.17.5",
"@babel/plugin-proposal-class-properties": "",
"@babel/plugin-proposal-object-rest-spread": "^7.16.0",
"@babel/plugin-proposal-object-rest-spread": "^7.17.3",
"@babel/plugin-transform-runtime": "",
"@babel/preset-env": "^7.16.4",
"@babel/preset-react": "^7.16.0",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"@babel/preset-typescript": "",
"@hot-loader/react-dom": "^16",
"@types/codemirror": "",
......@@ -35,6 +35,7 @@
"babel-loader": "^8.2.3",
"css-loader": "^5",
"electron": "^16",
"electron-builder": "^22.14.13",
"electron-devtools-installer": "^3.2.0",
"electron-webpack": "^2.8.2",
"eslint": "",
......@@ -57,7 +58,7 @@
"@fortawesome/fontawesome-free": "",
"@types/diff": "",
"@types/react-window": "",
"codemirror": "^5.64.0",
"codemirror": "^5.65.2",
"cytoscape": "",
"cytoscape-cola": "",
"cytoscape-cose-bilkent": "",
......@@ -67,7 +68,6 @@
"cytoscape-panzoom": "",
"cytoscape-popper": "",
"diff": "",
"electron-builder": "^22.14.5",
"immutable": "",
"lodash": "^4.17.21",
"react": "^16",
......
......@@ -59,6 +59,8 @@ export interface SVGprops {
Default is set to `-0.125` times the size).
*/
offset?: number;
className?: string;
fill?: string;
}
/**
......@@ -66,7 +68,7 @@ export interface SVGprops {
Only returns the identified `<svg/>` element from Icon base.
*/
export function SVG(props: SVGprops): null | JSX.Element {
const { id } = props;
const { id, className, fill } = props;
if (!id) return null;
const icon = Icons[id];
if (!icon) return <>{id}</>;
......@@ -82,9 +84,10 @@ export function SVG(props: SVGprops): null | JSX.Element {
width={size}
style={{ bottom: offset }}
viewBox={viewBox}
className = {className}
>
{title && <title>{title}</title>}
<path d={path} />
<path d={path} fill={fill} />
</svg>
);
}
......
......@@ -45,6 +45,7 @@
--default-button-hover: #364355;
--default-button-active: #303d4f;
--primary-button-color: #146bbf;
--primary-button-img: linear-gradient(to bottom, #146bbf 0%, #1960b2 100%);
--primary-button-hover: #0e65b9;
--primary-button-active: #085fb3;
......
......@@ -248,26 +248,29 @@ function useSettings<A>(
D: Driver,
K?: string,
): State<A> {
// Load value
const loader = () => (
// Local State
const [value, setValue] = React.useState<A>(() => (
JSON.jCatch(S.decoder, S.defaultValue)(D.load(K))
);
// Local state
const [value, setValue] = React.useState<A>(loader);
// Emit update event
));
// Foreign Settings Update
React.useEffect(() => {
const event = D.evt;
const callback = () => setValue(loader());
SysEmitter.on(event, callback);
return () => { SysEmitter.off(event, callback); };
const onUpdate = () => {
const fromSettings = JSON.jCatch(S.decoder, undefined)(D.load(K));
if (fromSettings !== undefined)
setValue(fromSettings);
};
SysEmitter.on(event, onUpdate);
return () => { SysEmitter.off(event, onUpdate); };
});
// Updates
// Hooked Settings Update
const updateValue = React.useCallback((newValue: A) => {
if (!isEqual(value, newValue)) {
setValue(newValue);
if (K) D.save(K, S.encoder(newValue));
}
}, [S, D, K, value]);
// Hook
return [value, updateValue];
}
......
......@@ -173,7 +173,7 @@ export function useEvent<A>(
return () => evt.off(callback);
}
return undefined;
});
}, [evt, callback]);
}
// --------------------------------------------------------------------------
......@@ -582,6 +582,29 @@ export function usePromise<T>(job: Promise<T>) {
return { result, error, loading };
}
/* Internal type alias */
type Serialize<A> = (a: A) => string;
/**
Hook to add a cache system to a function, allowing to reuse previous results.
As the equality used in JS maps does not allow to effectively implement a
cache for complex type, a serialization function can be procured.
The hook returns the cached version of the function.
*/
export function useCache<K, V>(r: (k: K) => V, s?: Serialize<K>): (k: K) => V {
const { current: cache } = React.useRef(new Map<string, V>());
const serialize = React.useMemo(() => s ? s : (k: K) => `${k}`, [s]);
const get = React.useCallback((k: K): V => {
const id = serialize(k);
if (cache.has(id))
return cache.get(id) as V;
const v = r(k);
cache.set(id, v);
return v;
}, [ cache, r, serialize ]);
return get;
}
// --------------------------------------------------------------------------
// --- Timer Hooks
// --------------------------------------------------------------------------
......@@ -704,11 +727,7 @@ export function useFlipSettings(
const [state, setState] = Settings.useWindowSettings(
key, Json.jBoolean, defaultValue,
);
const flipState = React.useCallback(
() => setState(!state),
[state, setState],
);
return [state, flipState];
return [state, () => setState(!state)];
}
/** Number window settings helper. Default is `0` unless specified. */
......
......@@ -430,68 +430,98 @@
}
/* -------------------------------------------------------------------------- */
/* --- Styling ToolBar Search Field --- */
/* --- Styling ToolBar Action Field --- */
/* -------------------------------------------------------------------------- */
.dome-xToolBar-control.dome-xToolBar-searchfield {
background-image: none ;
background-color: var(--background-alterning-odd);
padding-left: 20px ;
border-radius: 12px ;
border-color: var(--border);
color: var(--text);
width: 32px ;
transition: width 0.4s ease-in-out ;
.dome-xToolBar-actionComponent {
overflow: visible;
}
.dome-xToolBar-searchfield:focus,
.dome-xToolBar-searchfield:hover,
.dome-xToolBar-searchicon:hover + .dome-xToolBar-searchfield
{
width: 160px;
.dome-xToolBar-actionField {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
margin: 2px 1px 2px 1px;
padding: 0;
overflow: hidden;
font-size: 13px;
width: 28px;
border-radius: 12px;
transition: width 0.4s ease-in-out;
z-Index: +1;
}
.dome-xToolBar-searchicon {
position: relative ;
overflow: visible ;
z-Index: +1;
height: 0px;
width: 0px;
top: -7px ;
left: 12px ;
.dome-xToolBar-actionField:hover {
width: 228px;
}
.dome-xToolBar-searchmenu {
position: relative ;
width: 162px ;
max-height: 120px ;
overflow-x: hidden ;
overflow-y: auto ;
left: -7px ;
top: 4px ;
padding: 0px ;
border: 1pt solid var(--border) ;
background: var(--background-alterning-odd) ;
.dome-xToolBar-actionField:focus-within {
width: 228px !important;
box-shadow: 0 0 2px var(--border-discrete);
}
.dome-xToolBar-actionField div.dome-xToolBar-modeSelection {
position: relative;
padding: 3px 8px 0px 8px;
cursor: pointer;
}
.dome-xToolBar-actionField SVG.dome-xToolBar-modeIcon {
position: relative;
}
/* Style the search box inside the navigation bar */
.dome-xToolBar-actionField input[type=search] {
border: none;
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
text-indent: 4px;
height: 21px;
width: 200px;
outline: none;
background: var(--background-softer);
}
.dome-xToolBar-actionComponent div.dome-xToolBar-suggestions {
position: absolute;
overflow-x: hidden;
overflow-y: auto;
max-height: 120px;
z-index: +1;
width: 0px;
background: var(--background-alterning-odd);
border-radius: 12px;
}
.dome-xToolBar-actionComponent:focus-within div.dome-xToolBar-suggestions {
width: 230px;
}
.dome-xToolBar-searchitem {
color: var(--text);
display: block ;
width: 100% ;
margin-left: 0px ;
margin-right: 0px ;
padding-left: 4px ;
padding-right: 2px ;
display: block ;
width: 100% ;
margin-left: 0px ;
margin-right: 0px ;
padding-left: 4px ;
padding-right: 2px ;
}
.dome-xToolBar-searchitem:hover,
.dome-xToolBar-searchindex
{
background: var(--selected-element) !important;
.dome-xToolBar-searchitem:hover, .dome-xToolBar-searchindex {
background: var(--selected-element) !important;
}
.dome-xToolBar-searchitem:nth-child(even) {
background: var(--background-alterning-even);
background: var(--background-alterning-even);
}
.dome-xToolBar-searchMode {
background: var(--primary-button-color);
fill: var(--text-discrete);
}
.dome-xToolBar-modeOfModes {
background: var(--background-profound);
fill: var(--text-discrete);
}
/* -------------------------------------------------------------------------- */
......
......@@ -32,7 +32,7 @@
*/
import React from 'react';
import { Event, useEvent, find } from 'dome';
import { Event, find, usePromise } from 'dome';
import { SVG } from 'dome/controls/icons';
import { Label } from 'dome/controls/labels';
import { classes } from 'dome/misc/utils';
......@@ -124,6 +124,8 @@ export interface ButtonProps<A> {
selection?: A;
/** Selection callback. Receives the button's value. */
onClick?: (value: A | undefined) => void;
/** Button contents */
children?: React.ReactNode;
}
/** Toolbar Button. */
......@@ -145,6 +147,7 @@ export function Button<A = undefined>(props: ButtonProps<A>) {
>
{props.icon && <SVG id={props.icon} />}
{props.label && <label>{props.label}</label>}
{props.children}
</button>
);
}
......@@ -262,92 +265,187 @@ export function Select(props: SelectionProps<string>) {
}
// --------------------------------------------------------------------------
// --- SearchField
// --- ModalActionField necessary types
// --------------------------------------------------------------------------
const DEBOUNCED_SEARCH = 200;
const scrollToRef = (r: null | HTMLLabelElement) => {
if (r) r.scrollIntoView({ block: 'nearest' });
};
export interface Hint<A> {
/** Description of a hint used to populate the suggestions. */
export interface Hint {
id: string | number;
icon?: string;
label: string | JSX.Element;
title?: string;
value: A;
value(): void;
rank?: number;
}
export interface SearchFieldProps<A> {
/** Tooltip Text. */
title?: string;
/** Placeholder Text. */
/** Total order on hints. */
export function byHint(a: Hint, b: Hint) {
return (a.rank ?? 0) - (b.rank ?? 0);
}
/** Type alias for functions that build hints list from a pattern. */
export type HintsEvaluator = (pattern: string) => Promise<Hint[]>;
/** Description of an action mode. */
export interface ActionMode {
/** Mode tooltip text. */
title: string;
/** Mode placeholder text. */
placeholder?: string;
/** Provided search hints (with respect to last `onSearch()` callback). */
hints?: Hint<A>[];
/** Search callback. Triggered on Enter Key, Escape Key or Blur event. */
onSelect?: (pattern: string) => void;
/** Dynamic search callback. Triggered on key pressed (debounced). */
onSearch?: (pattern: string) => void;
/** Hint selection callback. */
onHint?: (hint: Hint<A>) => void;
/** Event that triggers a focus request (defaults to [[dome.find]]). */
event?: null | Event<void>;
/** Icon displayed when the mode is selected. */
icon: string;
/** CSS class for the mode section. */
className: string;
/** Hints provider. */
hints: HintsEvaluator;
/** Hint selection callback. Defaults to evaluate the <value> field. */
onHint?: (hint: Hint) => void;
/** Action to perform when Enter is hit. Useful for modes without hints. */
onEnter?: (pattern: string) => void;
/** Event that triggers a focus request. */
event?: Event<void>;
}
// --------------------------------------------------------------------------
// --- ModalActionField default mode: Search
// --------------------------------------------------------------------------
const searchEvaluators = new Map<string, HintsEvaluator>();
// Updates to the new evaluator if the id is already registered
export function registerSearchHints(id: string, search: HintsEvaluator) {
searchEvaluators.set(id, search);
}
interface Searching {
pattern?: string;
timer?: NodeJS.Timeout | undefined;
onSearch?: ((p: string) => void);
export function unregisterSearchHints(id: string) {
searchEvaluators.delete(id);
}
/**
Search Bar.
*/
export function SearchField<A = undefined>(props: SearchFieldProps<A>) {
const inputRef = React.useRef<HTMLInputElement | null>(null);
const blur = () => inputRef.current?.blur();
const focus = () => inputRef.current?.focus();
const [value, setValue] = React.useState('');
const [index, setIndex] = React.useState(-1);
const searching = React.useRef<Searching>({});
const { onHint, onSelect, onSearch, hints = [] } = props;
// Find event trigger
useEvent(props.event ?? find, focus);
// Lookup trigger
const triggerLookup = React.useCallback((pattern: string) => {
const s = searching.current;
s.pattern = pattern;
s.onSearch = onSearch;
if (!s.timer) {
s.timer = setTimeout(() => {
s.timer = undefined;
if (s.onSearch && s.pattern) s.onSearch(s.pattern);
}, DEBOUNCED_SEARCH);
}
}, [onSearch]);
async function searchHints(pattern: string) {
if (pattern === '') return [];
const promises = Array.from(searchEvaluators).map(([_id, E]) => E(pattern));
const hints = await Promise.all(promises);
return hints.flat().sort(byHint);
}
const searchMode: ActionMode = {
title: "Search",
placeholder: "Search…",
icon: "SEARCH",
className: 'dome-xToolBar-searchMode',
hints: searchHints,
event: find,
};
// --------------------------------------------------------------------------
// --- ModalActionField mode button component
// --------------------------------------------------------------------------
interface ModeButtonComponentProps {
current: ActionMode;
onClick: () => void;
}
function ModeButton(props: ModeButtonComponentProps) {
const { current, onClick } = props;
return (
<div
className={classes("dome-xToolBar-modeSelection", current.className)}
onClick={onClick}
>
<SVG
className="dome-xToolBar-modeIcon"
id={current.icon}
offset={-1}
/>
</div>
);
}
// --------------------------------------------------------------------------
// --- ModalActionField suggestions component
// --------------------------------------------------------------------------
interface SuggestionsProps {
hints: Hint[];
onHint: (hint: Hint) => void;
index: number;
}
function scrollToRef (r: null | HTMLLabelElement) {
if (r) r.scrollIntoView({ block: 'nearest' });
}
function Suggestions(props: SuggestionsProps) {
const { hints, onHint, index } = props;
// Computing the relevant suggestions. */
const suggestions = hints.map((h, k) => {
const selected = k === index || hints.length === 1;
const classSelected = selected && 'dome-xToolBar-searchindex';
const className = classes('dome-xToolBar-searchitem', classSelected);
return (
<Label
ref={selected ? scrollToRef : undefined}
key={h.id}
icon={h.icon}
title={h.title}
className={className}
onClick={() => onHint(h)}
>
{h.label}
</Label>
);
});
// Rendering the component.
return (
<div
style={{ visibility: suggestions.length > 0 ? 'visible' : 'hidden' }}
className='dome-xToolBar-suggestions'
onMouseDown={ (event) => event.preventDefault() }
>
{suggestions}
</div>
);
}
// --------------------------------------------------------------------------
// --- ModalActionField input field component
// --------------------------------------------------------------------------
interface ActionInputProps {
title: string;
placeholder?: string;
hints: Hint[];
onHint: (hint: Hint) => void;
onEnter?: (pattern: string) => void;
index: number;
setIndex: (n: number) => void;
pattern: string;
setPattern: (p: string) => void;
inputRef: React.MutableRefObject<HTMLInputElement | null>;
}
function ActionInput(props: ActionInputProps) {
const { title, placeholder, hints, onHint, onEnter } = props;
const { index, setIndex, pattern, setPattern, inputRef } = props;
// Blur Event
const onBlur = () => {
setValue('');
setIndex(-1);
if (onSearch) onSearch('');
};
const onBlur = () => { setPattern(''); setIndex(-1); };
// Key Events
const onKey = (evt: React.KeyboardEvent) => {
// Key Up Events
const onKeyUp = (evt: React.KeyboardEvent) => {
const blur = () => inputRef.current?.blur();
switch (evt.key) {
case 'Escape':
blur();
break;
case 'Enter':
if (index >= 0 && index < hints.length) {
if (onHint) onHint(hints[index]);
} else if (onSelect) onSelect(value);
blur();
if (index >= 0 && index < hints.length) onHint(hints[index]);
else if (hints.length === 1) onHint(hints[0]);
else if (onEnter) onEnter(pattern);
break;
case 'ArrowUp':
if (index < 0) setIndex(hints.length - 1);
......@@ -360,67 +458,138 @@ export function SearchField<A = undefined>(props: SearchFieldProps<A>) {
}
};
// Input Events
// Key Down Events. Disables the default behavior on ArrowUp and ArrowDown.
const onKeyDown = (evt: React.KeyboardEvent) => {
if (evt.key === 'ArrowUp' || evt.key === 'ArrowDown') evt.preventDefault();
};
// // Input Events
const onChange = (evt: React.ChangeEvent<HTMLInputElement>) => {
const newValue = evt.target.value;
triggerLookup(newValue);
setIndex(-1);
setValue(newValue);
setPattern(evt.target.value);
};
// Render Suggestions
const suggestions = hints.map((h, k) => {
const selected = k === index || hints.length === 1;
const className = classes(
'dome-xToolBar-searchitem',
selected && 'dome-xToolBar-searchindex',
);
return (
<Label
ref={selected ? scrollToRef : undefined}
key={h.id}
icon={h.icon}
title={h.title}
className={className}
onClick={() => {
if (onHint) onHint(h);
blur();
}}
>
{h.label}
</Label>
);
return (
<input
type="search"
placeholder={placeholder}
ref={inputRef}
title={title}
value={pattern}
onKeyUp={onKeyUp}
onKeyDown={onKeyDown}
onChange={onChange}
onBlur={onBlur}
/>
);
}
// --------------------------------------------------------------------------
// --- ModalActionField component
// --------------------------------------------------------------------------
export const RegisterMode: Event<ActionMode> =
new Event('dome.actionmode.register');
export const UnregisterMode: Event<ActionMode> =
new Event('dome.actionmode.unregister');
export function ModalActionField() {
// Internal state of the component along with useful functions acting on it.
const inputRef = React.useRef<HTMLInputElement | null>(null);
const [index, setIndex] = React.useState(-1);
const [pattern, setPattern] = React.useState('');
const [current, onModeChange] = React.useState<ActionMode>(searchMode);
const focus = () => inputRef.current?.focus();
const changeMode = (m: ActionMode) => () => { onModeChange(m); focus(); };
const toDefault = () => onModeChange(searchMode);
const reset = (m: ActionMode) => { if (current === m) toDefault(); };
// Set of all modes currently active. We populate it by reacting to
// RegisterMode and UnregisterMode events. We also activate the mode event if
// available. Everything is cleaned when the component is unmounted.
const [allModes] = React.useState<Set<ActionMode>>(new Set());
React.useEffect(() => {
const on = (m: ActionMode) => m.event?.on(changeMode(m));
const register = (m: ActionMode) => { allModes.add(m); on(m); };
const off = (m: ActionMode) => m.event?.off(changeMode(m));
const remove = (m: ActionMode) => { allModes.delete(m); off(m); reset(m); };
RegisterMode.on(register); UnregisterMode.on(remove);
return () => { RegisterMode.off(register); UnregisterMode.off(remove); };
});
const haspopup =
inputRef.current === document.activeElement
&& suggestions.length > 0;
const visibility = haspopup ? 'visible' : 'hidden';
// Render Component
// Register the search mode.
React.useEffect(() => RegisterMode.emit(searchMode));
// Compute the hints for the current mode.
const { hints, onHint = (h) => h.value(), onEnter } = current;
const hintsPromise = React.useMemo(() => hints(pattern), [pattern, hints]);
const { result = [] } = usePromise(hintsPromise);
// Auxiliary function that build a Hint from an ActionMode.
const modeToHint = (mode: ActionMode) => {
const { title, icon } = mode;
const id = 'ActionMode-' + title + '-' + icon;
const value = () => { onModeChange(mode); };
return { id, icon, label: title, title, value, rank: -1000 };
};
// Hints provider for the mode of all modes.
const modesHints = React.useCallback((input: string) => {
const p = input.toLowerCase();
const fit = (m: ActionMode) => m.title.toLowerCase().includes(p);
return Promise.resolve(Array.from(allModes).filter(fit).map(modeToHint));
}, [allModes]);
// Build the mode of all modes. This special mode is activated when clicking
// on the current mode icon and allows to change the current mode, displaying
// a list of all available modes as hints.
const modesMode = React.useMemo(() => {
const title = "Mode selection";
const placeholder = "Search mode";
const icon = "TUNINGS";
const className = 'dome-xToolBar-modeOfModes';
return { title, placeholder, icon, className, hints: modesHints };
}, [modesHints]);
// Build a new search engine for the search mode, adding available modes to
// the possible search hints.
const searchModeHints = React.useCallback(async (input: string) => {
const hs = await modesMode.hints(input);
const notCurrent = (h: Hint) => !(h.title?.includes(current.title));
return hs.filter(notCurrent);
}, [current.title, modesMode]);
// Register the new search engine.
React.useEffect(() => {
registerSearchHints('ModesMode', searchModeHints);
return () => unregisterSearchHints('ModesMode');
}, [searchModeHints]);
// Build the component.
const { title, placeholder } = current;
const handleModeClick = changeMode(modesMode);
const onBlur = () => reset(modesMode);
return (
<>
<div className="dome-xToolBar-searchicon">
<SVG id="SEARCH" />
<div
style={{ visibility }}
className="dome-xToolBar-searchmenu"
onMouseDown={(event) => event.preventDefault()}
>
{suggestions}
</div>
<div className="dome-xToolBar-actionComponent" onBlur={onBlur}>
<div className="dome-xToolBar-actionField">
<ModeButton current={current} onClick={handleModeClick} />
<ActionInput
title={title}
placeholder={placeholder}
hints={result}
onHint={onHint}
onEnter={onEnter}
index={index}
setIndex={setIndex}
pattern={pattern}
setPattern={setPattern}
inputRef={inputRef}
/>
</div>
<input
ref={inputRef}
type="search"
title={props.title}
value={value}
placeholder={props.placeholder}
className="dome-xToolBar-control dome-xToolBar-searchfield"
onKeyUp={onKey}
onChange={onChange}
onBlur={onBlur}
/>
</>
<Suggestions hints={result} onHint={onHint} index={index} />
</div>
);
}
......
......@@ -45,6 +45,7 @@
--default-button-hover: #ffffff;
--default-button-active: #f9f9f9;
--primary-button-color: #449bef;
--primary-button-img: linear-gradient(to bottom, #449bef 0%, #4990e2 100%);
--primary-button-hover: #00b6ff;
--primary-button-active: #ddd;
......
......@@ -72,6 +72,9 @@ export interface TextProps extends CodeMirror.EditorConfiguration {
/** The currently selected marker identifier. */
selection?: string;
/** Callback on hovered marker, if some. */
onHover?: (id?: string) => void;
/** Callback on identified marker selection. */
onSelection?: MarkerCallback;
......@@ -311,6 +314,8 @@ class CodeMirrorWrapper extends React.Component<TextProps> {
if (newMarker && newMarker.hover)
this._markElementsWith(newMarker.classNameId, CSS_HOVERED);
this.marker = newMarker;
const callback = this.props.onHover;
if (callback) callback(newMarker?.id);
}
}
......@@ -479,6 +484,7 @@ class CodeMirrorWrapper extends React.Component<TextProps> {
onFocus={this.onFocus}
onScroll={this.onScroll}
onMouseMove={this.onMouseMove}
onMouseLeave={this.onMouseMove}
/>
);
}
......
......@@ -2,7 +2,7 @@
/* */
/* This file is part of Frama-C. */
/* */
/* Copyright (C) 2007-2021 */
/* Copyright (C) 2007-2022 */
/* CEA (Commissariat à l'énergie atomique et aux énergies */
/* alternatives) */
/* */
......
......@@ -349,8 +349,9 @@ let makeDeclaration fmt names d =
Format.fprintf fmt " name: '%s',@\n" (Pkg.name_of_ident d.d_ident) ;
Format.fprintf fmt " input: %a,@\n" makeParam input ;
Format.fprintf fmt " output: %a,@\n" makeParam output ;
Format.fprintf fmt " signals: [%a],@\n"
(Pretty_utils.pp_list ~pre:"@[<hov 2>[ " ~sep:",@ " ~suf:"@ ]@]"
Format.fprintf fmt " signals: %a,@\n"
(Pretty_utils.pp_list
~empty:"[]" ~pre:"@[<hov 2>[ " ~sep:",@ " ~suf:"@ ]@]"
(fun fmt s -> Format.fprintf fmt "{ name: '%s' }" s))
rq.rq_signals;
Format.fprintf fmt "};@\n" ;
......