Skip to content

Tidy improvements #21619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 6, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
# * check-stage$(stage)-$(crate) - Test a crate in a specific stage
# * check-stage$(stage)-{rpass,rfail,cfail,rmake,...} - Run tests in src/test/
# * check-stage1-T-$(target)-H-$(host) - Run cross-compiled-tests
# * tidy-basic - show file / line stats
# * tidy-errors - show the highest rustc error code
# * tidy-features - show the status of language and lib features
#
# Then mix in some of these environment variables to harness the
# ultimate power of The Rust Build System.
Expand Down
2 changes: 2 additions & 0 deletions mk/main.mk
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ endif
# numbers and dots here
CFG_VERSION_WIN = $(CFG_RELEASE_NUM)

CFG_INFO := $(info cfg: version $(CFG_VERSION))

######################################################################
# More configuration
Expand Down Expand Up @@ -179,6 +180,7 @@ endif

ifndef CFG_DISABLE_VALGRIND_RPASS
$(info cfg: enabling valgrind run-pass tests (CFG_ENABLE_VALGRIND_RPASS))
$(info cfg: valgrind-rpass command set to $(CFG_VALGRIND))
CFG_VALGRIND_RPASS :=$(CFG_VALGRIND)
else
CFG_VALGRIND_RPASS :=
Expand Down
74 changes: 23 additions & 51 deletions mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ $(foreach file,$(wildcard $(S)src/doc/trpl/*.md), \
######################################################################

# The main testing target. Tests lots of stuff.
check: cleantmptestlogs cleantestlibs check-notidy tidy
check: cleantmptestlogs cleantestlibs all check-stage2 tidy
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log

# As above but don't bother running tidy.
check-notidy: cleantmptestlogs cleantestlibs all check-stage2
Expand Down Expand Up @@ -235,57 +236,24 @@ cleantestlibs:
######################################################################

ifdef CFG_NOTIDY
.PHONY: tidy
tidy:
else

ALL_CS := $(wildcard $(S)src/rt/*.cpp \
$(S)src/rt/*/*.cpp \
$(S)src/rt/*/*/*.cpp \
$(S)src/rustllvm/*.cpp)
ALL_CS := $(filter-out $(S)src/rt/miniz.cpp \
$(wildcard $(S)src/rt/hoedown/src/*.c) \
$(wildcard $(S)src/rt/hoedown/bin/*.c) \
,$(ALL_CS))
ALL_HS := $(wildcard $(S)src/rt/*.h \
$(S)src/rt/*/*.h \
$(S)src/rt/*/*/*.h \
$(S)src/rustllvm/*.h)
ALL_HS := $(filter-out $(S)src/rt/valgrind/valgrind.h \
$(S)src/rt/valgrind/memcheck.h \
$(S)src/rt/msvc/typeof.h \
$(S)src/rt/msvc/stdint.h \
$(S)src/rt/msvc/inttypes.h \
$(wildcard $(S)src/rt/hoedown/src/*.h) \
$(wildcard $(S)src/rt/hoedown/bin/*.h) \
,$(ALL_HS))

# Run the tidy script in multiple parts to avoid huge 'echo' commands
tidy:
.PHONY: tidy
tidy: tidy-basic tidy-binaries tidy-errors tidy-features

endif

.PHONY: tidy-basic
tidy-basic:
@$(call E, check: formatting)
$(Q)find $(S)src -name '*.r[sc]' \
-and -not -regex '^$(S)src/jemalloc.*' \
-and -not -regex '^$(S)src/libuv.*' \
-and -not -regex '^$(S)src/llvm.*' \
-and -not -regex '^$(S)src/gyp.*' \
-and -not -regex '^$(S)src/libbacktrace.*' \
-print0 \
| xargs -0 -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)find $(S)src/etc -name '*.py' \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)find $(S)src/doc -name '*.js' \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)find $(S)src/etc -name '*.sh' \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)find $(S)src/etc -name '*.pl' \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)find $(S)src/etc -name '*.c' \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)find $(S)src/etc -name '*.h' \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)echo $(ALL_CS) \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)echo $(ALL_HS) \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q) $(CFG_PYTHON) $(S)src/etc/tidy.py $(S)src/

.PHONY: tidy-binaries
tidy-binaries:
@$(call E, check: binaries)
$(Q)find $(S)src -type f -perm +a+x \
-not -name '*.rs' -and -not -name '*.py' \
-and -not -name '*.sh' \
Expand All @@ -300,11 +268,16 @@ tidy:
| grep '^$(S)src/libbacktrace' -v \
| grep '^$(S)src/rust-installer' -v \
| xargs $(CFG_PYTHON) $(S)src/etc/check-binaries.py
$(Q) $(CFG_PYTHON) $(S)src/etc/errorck.py $(S)src/
$(Q) $(CFG_PYTHON) $(S)src/etc/featureck.py $(S)src/

.PHONY: tidy-errors
tidy-errors:
@$(call E, check: extended errors)
$(Q) $(CFG_PYTHON) $(S)src/etc/errorck.py $(S)src/

endif
.PHONY: tidy-features
tidy-features:
@$(call E, check: feature sanity)
$(Q) $(CFG_PYTHON) $(S)src/etc/featureck.py $(S)src/


######################################################################
Expand Down Expand Up @@ -639,7 +612,6 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \

ifdef CFG_VALGRIND_RPASS
ifdef GOOD_VALGRIND_$(2)
$(info cfg: valgrind-path set to $(CFG_VALGRIND_RPASS))
CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) += --valgrind-path "$(CFG_VALGRIND_RPASS)"
endif
endif
Expand Down
10 changes: 8 additions & 2 deletions src/etc/errorck.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
import os
import re

if len(sys.argv) < 2:
print "usage: errorck.py <src-dir>"
sys.exit(1)

src_dir = sys.argv[1]
errcode_map = {}
error_re = re.compile("(E\d\d\d\d)")
Expand Down Expand Up @@ -54,8 +58,10 @@
print("{1}: {2}\n{3}".format(*entry))
errors = True

print("{0} error codes".format(len(errcode_map)))
print("highest error code: " + max(all_errors))
print
print("* {0} error codes".format(len(errcode_map)))
print("* highest error code: " + max(all_errors))
print

if errors:
sys.exit(1)
8 changes: 5 additions & 3 deletions src/etc/featureck.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@

import sys, os, re

if len(sys.argv) < 2:
print "usage: featurkck.py <src-dir>"
sys.exit(1)

src_dir = sys.argv[1]

# Features that are allowed to exist in both the language and the library
Expand Down Expand Up @@ -234,10 +238,8 @@

lines.sort()

print
print "Rust feature summary:"
print
for line in lines:
print line
print "* " + line
print

5 changes: 0 additions & 5 deletions src/etc/licenseck.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@
\\1 except according to those terms.""")

exceptions = [
"rt/rust_android_dummy.cpp", # BSD, chromium
"rt/rust_android_dummy.h", # BSD, chromium
"rt/isaac/randport.cpp", # public domain
"rt/isaac/rand.h", # public domain
"rt/isaac/standard.h", # public domain
"libstd/sync/mpsc/mpsc_queue.rs", # BSD
"libstd/sync/mpsc/spsc_queue.rs", # BSD
"test/bench/shootout-binarytrees.rs", # BSD
Expand Down
177 changes: 127 additions & 50 deletions src/etc/tidy.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,78 +51,155 @@ def do_license_check(name, contents):
if not check_license(name, contents):
report_error_name_no(name, 1, "incorrect license")


file_names = [s for s in sys.argv[1:] if (not s.endswith("_gen.rs"))
and (not ".#" in s)]

current_name = ""
current_contents = ""
check_tab = True
check_cr = True
check_linelength = True

if len(sys.argv) < 2:
print "usage: tidy.py <src-dir>"
sys.exit(1)

src_dir = sys.argv[1]

try:
for line in fileinput.input(file_names,
count_lines = 0
count_non_blank_lines = 0

interesting_files = ['.rs', '.py', '.js', '.sh', '.c', '.h']

file_counts = {ext: 0 for ext in interesting_files}
file_counts['other'] = 0

def update_counts(current_name):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that using a dictionary to track the file counts will make it easier to maintain in the long run.

# Use a dictionary comprehension to populate file_counts
interesting_files = ['.rs', '.py', '.js']
file_counts = {ext: 0 for ext in interesting_files}
file_counts['other'] = 0

def update_counts(current_name):
    global file_counts
    _, ext = os.path.splitext(current_name)

    if ext in file_counts:
        file_counts[ext] += 1
    else:
        file_counts['other'] += 1

global file_counts
_, ext = os.path.splitext(current_name)

if ext in file_counts:
file_counts[ext] += 1
else:
file_counts['other'] += 1

all_paths = set()

for (dirpath, dirnames, filenames) in os.walk(src_dir):

# Skip some third-party directories
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, we could probably define a set/list of skippable directories near the start of the file.

skippable_dirs = {
    'src/jemalloc',
    'src/llvm',
    # ...
    'src/rust-installer'
}

if any(d in dirpath for d in skippable_dirs):
    continue

skippable_dirs = {
'src/jemalloc',
'src/llvm',
'src/gyp',
'src/libbacktrace',
'src/libuv',
'src/compiler-rt',
'src/rt/hoedown',
'src/rustllvm',
'src/rt/valgrind',
'src/rt/msvc',
'src/rust-installer'
}

if any(d in dirpath for d in skippable_dirs):
continue

def interesting_file(f):
if "miniz.c" in f \
or "jquery" in f \
or "rust_android_dummy" in f:
return False

return any(os.path.splitext(f)[1] == ext for ext in interesting_files)

file_names = [os.path.join(dirpath, f) for f in filenames
if interesting_file(f)
and not f.endswith("_gen.rs")
and not ".#" is f]

if not file_names:
continue

for line in fileinput.input(file_names,
openhook=fileinput.hook_encoded("utf-8")):

if "tidy.py" not in fileinput.filename():
filename = fileinput.filename()

if "tidy.py" not in filename:
if "TODO" in line:
report_err("TODO is deprecated; use FIXME")
match = re.match(r'^.*/(\*|/!?)\s*XXX', line)
if match:
report_err("XXX is no longer necessary, use FIXME")
match = re.match(r'^.*//\s*(NOTE.*)$', line)
if match and "TRAVIS" not in os.environ:
m = match.group(1)
if "snap" in m.lower():
report_warn(match.group(1))
match = re.match(r'^.*//\s*SNAP\s+(\w+)', line)
if match:
hsh = match.group(1)
date, rev = snapshot.curr_snapshot_rev()
if not hsh.startswith(rev):
report_err("snapshot out of date (" + date
+ "): " + line)
else:
if "SNAP" in line:
report_warn("unmatched SNAP line: " + line)

if cr_flag in line:
check_cr = False
if tab_flag in line:
check_tab = False
if linelength_flag in line:
check_linelength = False
if "TODO" in line:
report_err("TODO is deprecated; use FIXME")
match = re.match(r'^.*/(\*|/!?)\s*XXX', line)
if match:
report_err("XXX is no longer necessary, use FIXME")
match = re.match(r'^.*//\s*(NOTE.*)$', line)
if match and "TRAVIS" not in os.environ:
m = match.group(1)
if "snap" in m.lower():
report_warn(match.group(1))
match = re.match(r'^.*//\s*SNAP\s+(\w+)', line)
if match:
hsh = match.group(1)
date, rev = snapshot.curr_snapshot_rev()
if not hsh.startswith(rev):
report_err("snapshot out of date (" + date
+ "): " + line)
else:
if "SNAP" in line:
report_warn("unmatched SNAP line: " + line)

if check_tab and ('\t' in line and
"Makefile" not in fileinput.filename()):
report_err("tab character")
if check_cr and not autocrlf and '\r' in line:
report_err("CR character")
if line.endswith(" \n") or line.endswith("\t\n"):
report_err("trailing whitespace")
line_len = len(line)-2 if autocrlf else len(line)-1

if check_linelength and line_len > cols:
report_err("line longer than %d chars" % cols)

if fileinput.isfirstline() and current_name != "":
do_license_check(current_name, current_contents)

if fileinput.isfirstline():
current_name = fileinput.filename()
current_contents = ""
check_cr = True
check_tab = True
check_linelength = True

current_contents += line

if check_tab and ('\t' in line and
"Makefile" not in filename):
report_err("tab character")
if check_cr and not autocrlf and '\r' in line:
report_err("CR character")
if line.endswith(" \n") or line.endswith("\t\n"):
report_err("trailing whitespace")
line_len = len(line)-2 if autocrlf else len(line)-1

if check_linelength and line_len > cols:
report_err("line longer than %d chars" % cols)

if fileinput.isfirstline():
# This happens at the end of each file except the last.
if current_name != "":
update_counts(current_name)
assert len(current_contents) > 0
do_license_check(current_name, current_contents)

current_name = filename
current_contents = ""
check_cr = True
check_tab = True
check_linelength = True

# Put a reasonable limit on the amount of header data we use for
# the licenseck
if len(current_contents) < 1000:
current_contents += line

count_lines += 1
if line.strip():
count_non_blank_lines += 1

if current_name != "":
update_counts(current_name)
assert len(current_contents) > 0
do_license_check(current_name, current_contents)

except UnicodeDecodeError as e:
report_err("UTF-8 decoding error " + str(e))

print
for ext in file_counts:
print "* linted " + str(file_counts[ext]) + " " + ext + " files"
print "* total lines of code: " + str(count_lines)
print "* total non-blank lines of code: " + str(count_non_blank_lines)
print

sys.exit(err)
Loading