From a81d3c0ac01e622a81a41ffb8d9b053ce23f92ac Mon Sep 17 00:00:00 2001 From: Patrick Baudin <patrick.baudin@cea.fr> Date: Mon, 13 Jun 2022 10:49:53 +0200 Subject: [PATCH] [Lint] using .gitattributes for lint target --- .git-blame-ignore-revs | 1 + .gitattributes | 11 +++ share/Makefile.linting | 193 ++++++++++++++++++++--------------------- 3 files changed, 107 insertions(+), 98 deletions(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index ba943a12c94..59694ae9ee4 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -33,3 +33,4 @@ a767fdcb7adda81a5ef192733ef7c62fd56b30e2 4130bab7a8b59d0c94a22d792b2a7d5a26d3484d 237d1bc71eb5efb7c5f32a097aacb90f90e0ff73 6cc1a6f2036b75c6b2451518ffbfbe025eb1a1f8 +1b7754fe7325a59ddbba62842a4bd907b0af6036 diff --git a/.gitattributes b/.gitattributes index ed8149fe409..e5a0c4bfdff 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15,6 +15,17 @@ Changelog merge=union *.pdf binary +################################## +# CHECK-SYNTAX/INDENT: set/unset # +################################## + +# SET +*.ml check-syntax check-indent +*.mli check-syntax check-indent + +# UNSET +/doc/**/*.ml* -check-syntax -check-indent + ######################### # HEADER_SPEC: CEA_LGPL # ######################### diff --git a/share/Makefile.linting b/share/Makefile.linting index 163f4a5f743..2ffa4583a86 100644 --- a/share/Makefile.linting +++ b/share/Makefile.linting @@ -20,124 +20,129 @@ # # ########################################################################## +.PHONY: check-ocp-indent-version +check-ocp-indent-version: + if command -v ocp-indent >/dev/null; then \ + if [ -z "$(shell ocp-indent --version)" ]; then echo "warning: ocp-indent returned an empty string, assuming it is the correct version"; \ + else \ + $(eval ocp_version_major := $(shell ocp-indent --version | $(SED) -E "s/^([0-9]+)\.[0-9]+\..*/\1/")) \ + $(eval ocp_version_minor := $(shell ocp-indent --version | $(SED) -E "s/^[0-9]+\.([0-9]+)\..*/\1/")) \ + if [ "$(ocp_version_major)" -lt 1 -o "$(ocp_version_minor)" -lt 7 ]; then \ + echo "error: ocp-indent 1.7.0 required for linting (got $(ocp_version_major).$(ocp_version_minor))"; \ + exit 1; \ + fi; \ + fi; \ + else \ + exit 1; \ + fi; + ################################ # Code prettyfication and lint # ################################ -# We're interested by any .ml[i]? file in src, except for scripts in test -# directories, and generated files (in particular lexers and parsers) -# Note: the find command below is *very* ugly, but it should be POSIX-compliant. +LINT.HAS_GIT:=$(wildcard .git) +ifeq ($(LINT.HAS_GIT),) -ALL_ML_FILES:=$(shell find src -name '*.ml' -print -o -name '*.mli' -print -o -path '*/tests' -prune '!' -name '*') -ALL_ML_FILES+=ptests/ptests.ml ptests/wtests.ml +.PHONY: +lint: + echo "lint target requires git" -ifeq ($(origin MANUAL_ML_FILES),undefined) -MANUAL_ML_FILES:=$(ALL_ML_FILES) -endif -MANUAL_ML_FILES:=\ - $(filter-out $(GENERATED) $(PLUGIN_GENERATED_LIST), $(MANUAL_ML_FILES)) +.PHONY: stats-lint +stats-lint: + echo "stats-lint: deprecated target" -# Allow control of files to be linted/fixed by external sources -# (e.g. pre-commit hook that will concentrate on files which have changed) +else -sinclude .Makefile.lint +.PHONY: +lint: + git ls-files -z | git check-attr --stdin -z check-syntax \ + | sed -zne 'x;n;n;s/^set$$//;t print;b;:print;x;p' \ + | xargs --null -IXX sh -c 'make LINT_FILE="XX" check-syntax || exit 255' + git ls-files -z | git check-attr --stdin -z check-indent \ + | sed -zne 'x;n;n;s/^set$$//;t print;b;:print;x;p' \ + | xargs --null -IXX sh -c 'make LINT_FILE="XX" check-indent || exit 255' -HAS_GIT_FILE:=$(wildcard .git/HEAD) +.PHONY: stats-lint +stats-lint: + echo "stats-lint: deprecated target" -ifeq ("$(HAS_GIT_FILE)","") -LINT_OTHER_SOURCES:= -else -LINT_OTHER_SOURCES:=\ - $(filter-out \ - $(shell git ls-tree --name-only HEAD src/plugins/*), \ - $(wildcard src/plugins/*)) endif -$(foreach dir,$(LINT_OTHER_SOURCES),$(eval sinclude $(dir)/.Makefile.lint)) +############################################################## -ML_LINT_MISSING:=$(filter-out $(MANUAL_ML_FILES), $(ML_LINT_KO)) +LINT_FILE.list=$(wildcard $(LINT_FILE)) +LINT_FILE.target=$(join $(dir $(LINT_FILE.list)),$(addprefix .lint/.%,$(notdir $(LINT_FILE.list)))) -# By default, also checks files with unknown status: -# this requires new files to pass lint checker from the beginning +define fix_indent_rule +$(dir $(1)).fix-indent/.$(notdir $(1)).lint-test: $(1) + mkdir -p $$(dir $$@) + touch $$@ +endef -ML_LINT_CHECK?=$(filter-out $(ML_LINT_KO), $(MANUAL_ML_FILES)) +$(foreach file,$(LINT_FILE.list),$(eval $(call fix_indent_rule,$(file)))) -# this NEWLINE variable containing a literal newline character is used to avoid -# the error "argument list too long", in some instances of "foreach". -# For details, see https://stackoverflow.com/questions/7039811 -define NEWLINE +LINT_FILE.lint-test= $(addsuffix .lint-test,$(LINT_FILE.list)) +.PHONY: lint-test +lint-test: $(LINT_FILE.lint-test) -endef +xxx: + echo "list=$(LINT_FILE.list)" + echo "lint-test=$(LINT_FILE.lint-test)" -# pre-requisite intentionally left blank: this target should only be used -# if the file is not present to generate it once and forall, -# and be edited manually afterwards -# double colon here tells make not to attempt updating the .Makefile.lint -# if it does not exist, but just to ignore it. -.Makefile.lint:: - echo "ML_LINT_KO:=" >> $@ - $(foreach file,$(sort $(MANUAL_ML_FILES)), \ - if ! $(MAKE) ML_LINT_CHECK=$(file) lint; \ - then echo "ML_LINT_KO+=$(file)" >> $@; fi;$(NEWLINE) ) - -$(foreach dir,$(LINT_OTHER_SOURCES),\ - $(eval $(dir)/.Makefile.lint:: ; \ - $(foreach file, $(sort $(filter $(dir)/%, $(MANUAL_ML_FILES))), \ - if ! $$(MAKE) ML_LINT_CHECK=$(file) lint; \ - then echo "ML_LINT_KO+=$(file)" >> $$@; fi; ))) +######################## -.PHONY: stats-lint -stats-lint: - echo \ - "scale = 2; bad = $(words $(ML_LINT_MISSING)); \ - all = $(words $(sort $(MANUAL_ML_FILES))); \ - fail = $(words $(ML_LINT_KO)); \ - \"lint coverage: \"; \ - ((all - fail) * 100) / all; " | bc - echo "number of files supposed to pass lint: $(words $(ML_LINT_CHECK))" - echo "number of files supposed to fail lint: $(words $(ML_LINT_KO))" -ifneq ($(strip $(ML_LINT_MISSING)),) - echo "number of files missing from src/ : $(words $(ML_LINT_MISSING))" - $(foreach file, $(ML_LINT_MISSING), echo $(file);) - exit 1 -endif -INDENT_TARGET= $(patsubst %,%.indent,$(ML_LINT_CHECK)) -LINT_TARGET= $(patsubst %,%.lint,$(ML_LINT_CHECK)) +LINT_FILE.check-syntax= $(addsuffix .check-syntax,$(LINT_FILE.list)) +LINT_FILE.check-indent= $(addsuffix .check-indent,$(LINT_FILE.list)) -FIX_SYNTAX_TARGET=$(patsubst %,%.fix-syntax,$(ML_LINT_CHECK)) +LINT_FILE.fix-syntax= $(addsuffix .fix-syntax,$(LINT_FILE.list)) +LINT_FILE.fix-indent= $(addsuffix .fix-indent,$(LINT_FILE.list)) -.PHONY: $(INDENT_TARGET) $(LINT_TARGET) $(FIX_SYNTAX_TARGET) \ - indent lint fix-syntax -indent: $(INDENT_TARGET) +lint.info: + echo "LINT.HAS_GIT='$(LINT.HAS_GIT)'" + echo "LINT_FILE.list='$(LINT_FILE.list)'" -lint:: $(LINT_TARGET) +############################### -check-ocp-indent-version: - if command -v ocp-indent >/dev/null; then \ - if [ -z "$(shell ocp-indent --version)" ]; then echo "warning: ocp-indent returned an empty string, assuming it is the correct version"; \ - else \ - $(eval ocp_version_major := $(shell ocp-indent --version | $(SED) -E "s/^([0-9]+)\.[0-9]+\..*/\1/")) \ - $(eval ocp_version_minor := $(shell ocp-indent --version | $(SED) -E "s/^[0-9]+\.([0-9]+)\..*/\1/")) \ - if [ "$(ocp_version_major)" -lt 1 -o "$(ocp_version_minor)" -lt 7 ]; then \ - echo "error: ocp-indent 1.7.0 required for linting (got $(ocp_version_major).$(ocp_version_minor))"; \ - exit 1; \ - fi; \ - fi; \ - else \ - exit 1; \ - fi; +.PHONY: check-syntax $(LINT_FILE.check-syntax) +check-syntax: $(LINT_FILE.check-syntax) + +.PHONY: fix-syntax $(LINT_FILE.fix-syntax) +fix-syntax: $(LINT_FILE.fix-syntax) + +.PHONY: check-indent $(LINT_FILE.check-indent) +check-indent: $(LINT_FILE.check-indent) -fix-syntax: $(FIX_SYNTAX_TARGET) +.PHONY: fix-indent $(LINT_FILE.fix-indent) +fix-indent: $(LINT_FILE.fix-indent) -$(INDENT_TARGET): %.indent: % check-ocp-indent-version +############################### +## INDENTATION ASPECT + +$(LINT_FILE.check-indent): %.check-indent: % check-ocp-indent-version + ocp-indent $< > $<.tmp + if cmp -s $< $<.tmp; \ + then rm -f $<.tmp; \ + else \ + echo "File $< is not indented correctly."; \ + echo "Please run: make LINT_FILE=$< fix-indent";\ + rm $<.tmp; \ + exit 1; \ + fi + +$(LINT_FILE.fix-indent): %.fix-indent: % check-ocp-indent-version + echo "Fixes indent: $<" ocp-indent -i $< -$(LINT_TARGET): %.lint: % check-ocp-indent-version + +############################### +## SYNTACTICAL ASPECT + +$(LINT_FILE.check-syntax): %.check-syntax: % # See SO 1825552 on mixing grep and \t (and cry) # For OK_NL, we have three cases: # - for empty files, the computation boils down to 0 - 0 == 0 @@ -154,20 +159,12 @@ $(LINT_TARGET): %.lint: % check-ocp-indent-version echo "$$OK_SPACE lines with spaces at end of line"; \ test $$OK_NL -eq 0 || echo "No newline at end of file"; \ test $$OK_EMPTY -eq 0 || echo "Empty line(s) at end of file"; \ - echo "Please run make ML_LINT_CHECK=$< fix-syntax"; \ + echo "Please run: make LINT_FILE=$< fix-syntax"; \ exit 1 ; \ fi - ocp-indent $< > $<.tmp; - if cmp -s $< $<.tmp; \ - then rm -f $<.tmp; \ - else \ - echo "File $< is not indented correctly."; \ - echo "Please run make ML_LINT_CHECK=$< indent";\ - rm $<.tmp; \ - exit 1; \ - fi - -$(FIX_SYNTAX_TARGET): %.fix-syntax: % + +$(LINT_FILE.fix-syntax): %.fix-syntax: % + echo "Fixes syntax: $<" $(ISED) -e 's/^ *\t\+/ /' $< $(ISED) -e 's/\(.*[^[:blank:]]\)[[:blank:]]\+$$/\1/' $< $(ISED) -e 's/^[ \t]\+$$//' $< -- GitLab