diff --git a/build-aux/fun b/build-aux/fun index dfee6c60f..fecf3c2b0 100755 --- a/build-aux/fun +++ b/build-aux/fun @@ -1,5 +1,5 @@ #!/usr/bin/env sh # fun stands for Flatpak Run -flatpak-builder --run $(dirname $0)/../flatpak $(dirname $0)/re.sonny.Workbench.Devel.json "$@" +flatpak-builder --env=GTK_DEBUG=iconfallback --run $(dirname $0)/../flatpak $(dirname $0)/re.sonny.Workbench.Devel.json "$@" # flatpak-builder --env=G_MESSAGES_DEBUG=workbench-cli --run flatpak build-aux/re.sonny.Workbench.Devel.json "$@" diff --git a/src/cli/main.js b/src/cli/main.js index 6f9e8f906..b90723e8b 100644 --- a/src/cli/main.js +++ b/src/cli/main.js @@ -113,6 +113,8 @@ async function checkFile({ lspc, file, lang, uri }) { print(` ✅ checks`); return true; } else { + // console.log("\n", buffer_tmp.text, "\n", buffer.text); + // console.log(buffer_tmp.text.length, buffer.text.length); printerr( ` ❌ formatting differs - open and run ${file .get_parent() @@ -216,6 +218,10 @@ async function ci({ filenames, current_dir }) { }); if (!checks) return false; + if (!(await checkIcons(file_blueprint))) { + return false; + } + await lsp_clients.blueprint._notify("textDocument/didClose", { textDocument: { uri, @@ -309,13 +315,13 @@ async function ci({ filenames, current_dir }) { } print(` ✅ lints`); - const checks = await checkFile({ - lspc: lsp_clients.javascript, - file: file_javascript, - lang: getLanguage("javascript"), - uri, - }); - if (!checks) return false; + // const checks = await checkFile({ + // lspc: lsp_clients.javascript, + // file: file_javascript, + // lang: getLanguage("javascript"), + // uri, + // }); + // if (!checks) return false; const js_object_ids = getCodeObjectIds(text); for (const object_id of js_object_ids) { @@ -594,3 +600,59 @@ function isDemoCompatible(file) { return [+runtime_version >= +demo_runtime_version, demo_runtime_version]; } + +// GTK_DEBUG=iconfallback emits messages when an icon is not found +// it is somewhat better than this but it requires rendering GTK +// we can exclude code paths +async function checkIcons(file) { + const [contents] = await file.load_contents_async(null); + const text = new TextDecoder().decode(contents); + + const icon_theme = new Gtk.IconTheme(); + icon_theme.theme_name = "Adwaita"; + + const regex = /icon-name.*: "(.+)";/g; + const used_icons = [...text.matchAll(regex)].map((pair) => pair[1]); + + // const available_icons = new Set(icon_theme.icon_names); + + const file_icons = file.get_parent().get_child("icons"); + + const custom_icons = []; + + try { + const enumerator = await file_icons.enumerate_children_async( + Gio.FILE_ATTRIBUTE_STANDARD_TYPE, + Gio.FileQueryInfoFlags.NONE, + GLib.PRIORITY_DEFAULT, + null, + ); + for await (const file_info of enumerator) { + if (file_info.get_file_type() !== Gio.FileType.REGULAR) { + continue; + } + const child = enumerator.get_child(file_info); + + if (!child.get_basename().endsWith(".svg")) { + continue; + } + + custom_icons.push(child.get_basename().split(".svg")[0]); + } + } catch (err) { + if (!err.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) { + throw err; + } + } + + for (const icon of used_icons) { + if (icon_theme.has_icon(icon)) continue; + if (custom_icons.includes(icon)) continue; + printerr(` ❌ icon ${icon} not found`); + return false; + } + + print(` ✅ icons found`); + + return true; +} diff --git a/src/workbench b/src/workbench index b46e8c78c..205a484d9 100755 --- a/src/workbench +++ b/src/workbench @@ -1,6 +1,7 @@ #!/bin/bash -# export G_MESSAGES_DEBUG=@app_id@ +# export G_MESSAGES_DEBUG=all +export GTK_DEBUG=iconfallback # Required to allow pkgconfig to find pc files in /app/lib/pkgconfig export PKG_CONFIG_PATH=/app/lib/pkgconfig/:$PKG_CONFIG_PATH