tools: Remove find-add-class tool.

I added this tool a few years ago, and I did have
a vision for how it would improve our codebase, but
I can't remember exactly where I was going with it.

At this point the tool is just a little too noisy
to be helpful.  An example of it creating confusion
was a recent PR where somebody was patching
user_circle_class in the PM list, and we already
had similar code in the buddy list, because they
use the same CSS.  I mean, there was possibly a way
that the code could have been structured to remove
some of the duplication, but it probably would have
just moved the complexity around.

I just don't think it's worth maintaining the tool
at this point.
This commit is contained in:
Steve Howell
2020-01-14 23:11:08 +00:00
committed by Tim Abbott
parent 29e63c0417
commit 752d6dc6df
4 changed files with 0 additions and 169 deletions

View File

@@ -185,14 +185,6 @@ that we exempt may be deemed not worthwhile to fix.
We check our JavaScript code in a few different ways:
- We run eslint.
- We perform custom Zulip regex checks on the code.
- We verify that all addClass calls, with a few exceptions, explicitly
contain a CSS class.
The last check happens via a call to `./tools/find-add-class`. This
particular check is a work in progress, as we are trying to evolve a
more rigorous system for weeding out legacy CSS styles, and the ability
to quickly introspect our JS code for `addClass` calls is part of our
vision.
#### Puppet manifests

View File

@@ -1,43 +0,0 @@
#!/usr/bin/env python3
from lib.find_add_class import display, find
import glob
import argparse
# check for the venv
from lib import sanity_check
sanity_check.check_venv(__file__)
def process_files():
# type: () -> None
description = '''
Use this tool to find HTML classes that we use in our JS code.
This looks for calls to addClass, and if you use the -v option,
you will get a display of (fn, html_class) tuples that
represent addClass calls.
If you call it with no options, the tool acts as a linter, and
it will complain if it can't resolve the class for an addClass()
call.
'''
parser = argparse.ArgumentParser(description=description)
parser.add_argument('-v', '--verbose',
action='store_true', default=False,
help='show where calls are')
parser.add_argument('targets', nargs=argparse.REMAINDER)
args = parser.parse_args()
if args.targets == []:
fns = glob.glob('static/js/*.js')
else:
fns = args.targets
if args.verbose:
display(fns)
else:
find(fns)
if __name__ == '__main__':
process_files()

View File

@@ -1,116 +0,0 @@
from typing import List, Set, Tuple
import os
import re
GENERIC_KEYWORDS = [
'active',
'alert',
'danger',
'condensed',
'disabled',
'enabled',
'error',
'expanded',
'fade-out',
'first',
'hide',
'in',
'show',
'notdisplayed',
'popover',
'no-border',
'rtl',
'second',
'selected',
'slide-left',
'success',
'text-error',
'warning',
'zoom-in', # TODO: clean these up, they are confusing
'zoom-out',
]
def raise_error(fn, i, line):
# type: (str, int, str) -> None
error = '''
In %s line %d there is the following line of code:
%s
Our tools want to be able to identify which modules
add which HTML/CSS classes, and we need two things to
happen:
- The code must explicitly name the class.
- Only one module can refer to that class (unless
it is something generic like an alert class).
If you get this error, you can usually address it by
refactoring your code to be more explicit, or you can
move the common code that sets the class to a library
module. If neither of those applies, you need to
modify %s
''' % (fn, i, line, __file__)
raise Exception(error)
def generic(html_class):
# type: (str) -> bool
for kw in GENERIC_KEYWORDS:
if kw in html_class:
return True
return False
def display(fns):
# type: (List[str]) -> None
for tup in find(fns):
# this format is for code generation purposes
print(' ' * 8 + repr(tup) + ',')
def find(fns):
# type: (List[str]) -> List[Tuple[str, str]]
encountered = set() # type: Set[str]
tups = [] # type: List[Tuple[str, str]]
for full_fn in fns:
# Don't check frontend tests, since they may do all sorts of
# extra hackery that isn't of interest to us.
if full_fn.startswith("frontend_tests"):
continue
lines = list(open(full_fn))
fn = os.path.basename(full_fn)
module_classes = set() # type: Set[str]
for i, line in enumerate(lines):
if 'addClass' in line:
html_classes = [] # type: List[str]
m = re.search(r'''addClass\(['"](.*?)['"]''', line)
if m:
html_classes = [m.group(1)]
if not html_classes:
if 'bar-success' in line:
html_classes = ['bar-success', 'bar-danger']
elif fn == 'hotspots.js' and 'arrow_placement' in line:
html_classes = ['arrow-top', 'arrow-left', 'arrow-bottom', 'arrow-right']
elif 'color_class' in line:
continue
elif 'stream_dark' in line:
continue
elif 'opts.' in line:
continue
elif fn == 'signup.js' and 'class_to_add' in line:
html_classes = ['error', 'success']
elif fn == 'ui_report.js' and 'status_classes' in line:
html_classes = ['alert']
if not html_classes:
raise_error(full_fn, i, line)
for html_class in html_classes:
if generic(html_class):
continue
if html_class in module_classes:
continue
if html_class in encountered:
raise_error(full_fn, i, line)
tups.append((fn, html_class))
module_classes.add(html_class)
encountered.add(html_class)
return tups

View File

@@ -51,8 +51,6 @@ def run():
'frontend': ['js', 'ts', 'css', 'scss', 'hbs', 'html', 'lock'],
}, exclude=EXCLUDED_FILES)
linter_config.external_linter('add_class', ['tools/find-add-class'], ['js'],
description="Compares addClass() between JavaSsript and CSS.")
linter_config.external_linter('css', ['node', 'node_modules/.bin/stylelint'], ['css', 'scss'],
fix_arg='--fix',
description="Standard CSS style and formatting linter "