Commit cb1408d4 authored by Rusty Russell's avatar Rusty Russell

ccanlint: detect unused dependencies, too.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 453fdc02
...@@ -16,44 +16,42 @@ ...@@ -16,44 +16,42 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
static bool has_dep(struct manifest *m, bool test_depend, const char *depname) static bool has_dep(struct manifest *m, char **deps, bool *used,
const char *depname)
{ {
struct manifest *i; unsigned int i;
/* We can include ourselves, of course. */ /* We can include ourselves, of course. */
if (streq(depname, m->basename)) if (streq(depname + strlen("ccan/"), m->basename))
return true; return true;
list_for_each(&m->deps, i, list) { for (i = 0; deps[i]; i++) {
if (streq(i->basename, depname)) if (streq(deps[i], depname)) {
used[i] = true;
return true; return true;
}
if (test_depend) {
list_for_each(&m->test_deps, i, list) {
if (streq(i->basename, depname))
return true;
} }
} }
return false; return false;
} }
static void check_dep_includes(struct manifest *m, struct score *score, static bool check_dep_includes(struct manifest *m,
struct ccan_file *f, bool test_depend) char **deps, bool *used,
struct score *score,
struct ccan_file *f)
{ {
unsigned int i; unsigned int i;
char **lines = get_ccan_file_lines(f); char **lines = get_ccan_file_lines(f);
struct line_info *li = get_ccan_line_info(f); struct line_info *li = get_ccan_line_info(f);
bool ok = true;
for (i = 0; lines[i]; i++) { for (i = 0; lines[i]; i++) {
char *mod; char *mod;
if (!strreg(f, lines[i], if (!strreg(f, lines[i],
"^[ \t]*#[ \t]*include[ \t]*[<\"]" "^[ \t]*#[ \t]*include[ \t]*[<\"]"
"ccan/+([^/]+)/", &mod)) "(ccan/+[^/]+)/", &mod))
continue; continue;
if (has_dep(m, test_depend, mod)) if (has_dep(m, deps, used, mod))
continue; continue;
/* FIXME: we can't be sure about /* FIXME: we can't be sure about
...@@ -62,35 +60,80 @@ static void check_dep_includes(struct manifest *m, struct score *score, ...@@ -62,35 +60,80 @@ static void check_dep_includes(struct manifest *m, struct score *score,
if (!li[i].cond) { if (!li[i].cond) {
score_file_error(score, f, i+1, score_file_error(score, f, i+1,
"%s not listed in _info", mod); "%s not listed in _info", mod);
ok = false;
} }
} }
return ok;
} }
static void check_depends_accurate(struct manifest *m, static void check_depends_accurate(struct manifest *m,
unsigned int *timeleft, struct score *score) unsigned int *timeleft, struct score *score)
{ {
struct list_head *list; struct list_head *list;
unsigned int i, core_deps, test_deps;
char **deps, **tdeps;
bool *used;
bool ok = true;
/* Get the *direct* dependencies. */
if (safe_mode) {
deps = get_safe_ccan_deps(m, m->dir, "depends", false);
tdeps = get_safe_ccan_deps(m, m->dir, "testdepends", false);
} else {
deps = get_deps(m, m->dir, "depends", false,
get_or_compile_info);
tdeps = get_deps(m, m->dir, "testdepends", false,
get_or_compile_info);
}
core_deps = talloc_array_length(deps) - 1;
test_deps = talloc_array_length(tdeps) - 1;
used = talloc_zero_array(m, bool, core_deps + test_deps + 1);
foreach_ptr(list, &m->c_files, &m->h_files) { foreach_ptr(list, &m->c_files, &m->h_files) {
struct ccan_file *f; struct ccan_file *f;
list_for_each(list, f, list) list_for_each(list, f, list)
check_dep_includes(m, score, f, false); ok &= check_dep_includes(m, deps, used, score, f);
} }
for (i = 0; i < core_deps; i++) {
if (!used[i])
score_file_error(score, m->info_file, 0,
"%s is an unused dependency",
deps[i]);
}
/* Now append test dependencies to deps. */
deps = talloc_realloc(NULL, deps, char *,
(core_deps + test_deps + 1) * sizeof(char *));
memcpy(&deps[core_deps], tdeps, test_deps * sizeof(char *));
/* ccan/tap is given a free pass. */
deps[core_deps + test_deps] = (char *)"ccan/tap";
deps[core_deps + test_deps + 1] = NULL;
foreach_ptr(list, &m->run_tests, &m->api_tests, foreach_ptr(list, &m->run_tests, &m->api_tests,
&m->compile_ok_tests, &m->compile_fail_tests, &m->compile_ok_tests, &m->compile_fail_tests,
&m->other_test_c_files) { &m->other_test_c_files) {
struct ccan_file *f; struct ccan_file *f;
list_for_each(list, f, list) list_for_each(list, f, list)
check_dep_includes(m, score, f, true); ok &= check_dep_includes(m, deps, used, score, f);
} }
if (!score->error) { for (i = core_deps; i < test_deps; i++) {
score->score = score->total; if (!used[i])
score->pass = true; score_file_error(score, m->info_file, 0,
"%s is an unused test dependency",
deps[i]);
} }
if (!score->error)
score->score = score->total;
/* We don't count unused dependencies as an error (yet!) */
score->pass = ok;
} }
struct ccanlint depends_accurate = { struct ccanlint depends_accurate = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment