0

Files app: Add presubmit to block @ts-ignore in TS files.

Fix the `MockFile` to output the same string value of the
implementation.

Bug: b:289003444

Change-Id: I36529ef112af6e81a9e84f6dbb0777ce97e3d543
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4975179
Reviewed-by: Bruce Dawson <brucedawson@chromium.org>
Reviewed-by: Ben Reich <benreich@chromium.org>
Commit-Queue: Luciano Pacheco <lucmult@chromium.org>
Reviewed-by: Wenbo Jie <wenbojie@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1215153}
This commit is contained in:
Luciano Pacheco
2023-10-25 22:49:36 +00:00
committed by Chromium LUCI CQ
parent d15df6e85e
commit 23d752b0ca
4 changed files with 136 additions and 36 deletions

@ -209,6 +209,9 @@ class MockFile(object):
self._scm_diff += "+%s\n" % l
self._old_contents = old_contents
def __str__(self):
return self._local_path
def Action(self):
return self._action

@ -2,11 +2,32 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import sys
PRESUBMIT_VERSION = '2.0.0'
TEST_PATTERNS = [r'.+_test.py$']
class SaveSysPath():
"""Context manager to save and restore the sys.path.
>>> with SaveSysPath(['/path/to/append/to/sys/path']):
... # do stuff
>>> # sys.path is back to original value
"""
def __init__(self, additional_paths=None):
self._original_path = sys.path[:]
self._additional_paths = additional_paths
def __enter__(self):
if self._additional_paths:
sys.path.extend(self._additional_paths)
def __exit__(self, *args):
sys.path = self._original_path
def ChecksPatchFormatted(input_api, output_api):
return input_api.canned_checks.CheckPatchFormatted(input_api,
output_api,
@ -21,25 +42,32 @@ def ChecksUnitTests(input_api, output_api):
def ChecksCommon(input_api, output_api):
results = []
try:
import sys
old_sys_path = sys.path[:]
cwd = input_api.PresubmitLocalPath()
cwd = input_api.PresubmitLocalPath()
more_paths = [
input_api.os_path.join(cwd, '..', '..', 'tools'),
input_api.os_path.join(cwd, '..', 'chromeos'),
input_api.os_path.join(cwd),
]
sys.path += [input_api.os_path.join(cwd, '..', '..', 'tools')]
import web_dev_style.presubmit_support
results += web_dev_style.presubmit_support.CheckStyle(
input_api, output_api)
with SaveSysPath(more_paths):
from web_dev_style.presubmit_support import CheckStyle
from styles.presubmit_support import _CheckSemanticColors
from base.presubmit_support import _CheckNoDirectLitImport
results += CheckStyle(input_api, output_api)
results += _CheckSemanticColors(input_api, output_api)
results += _CheckNoDirectLitImport(input_api, output_api)
return results
def CheckBannedTsTags(input_api, output_api):
results = []
cwd = input_api.PresubmitLocalPath()
more_paths = [
input_api.os_path.join(cwd),
]
with SaveSysPath(more_paths):
from base.presubmit_support import _CheckBannedTsTags
results += _CheckBannedTsTags(input_api, output_api)
sys.path += [input_api.os_path.join(cwd, '..', 'chromeos')]
import styles.presubmit_support
results += styles.presubmit_support._CheckSemanticColors(
input_api, output_api)
sys.path += [input_api.os_path.join(cwd)]
import base.presubmit_support
results += base.presubmit_support._CheckNoDirectLitImport(
input_api, output_api)
finally:
sys.path = old_sys_path
return results

@ -47,3 +47,27 @@ def _CheckNoDirectLitImport(input_api, output_api):
break
return results
def _IsComment(line):
l = line.lstrip()
return l.startswith(('//', '/*', '* '))
def _CheckBannedTsTags(input_api, output_api):
ts_only = lambda f: f.LocalPath().endswith('.ts')
results = []
offending_files = []
for f in input_api.AffectedFiles(file_filter=ts_only):
for line_num, line in f.ChangedContents():
if not _IsComment(line):
continue
if '@ts-ignore' in line:
offending_files.append(f'{f}: {line_num}: {line[:100]}')
if offending_files:
results.append(
output_api.PresubmitError('@ts-ignore is banned in TS files.',
offending_files))
return results

@ -7,7 +7,7 @@ import os.path
import unittest
import sys
from presubmit_support import _CheckNoDirectLitImport
from presubmit_support import _CheckNoDirectLitImport, _CheckBannedTsTags
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi, MockFile
@ -21,26 +21,29 @@ class NoDirectLitImportPresubmit(unittest.TestCase):
self.mock_output_api = MockOutputApi()
def emulateJsAndTsFiles(self, lines):
ts_path = os.path.join('some', 'path', 'foo.ts')
js_path = os.path.join('some', 'path', 'foo.js')
foo_ts = MockFile(ts_path, lines)
foo_js = MockFile(js_path, lines)
self.mock_input_api.files.extend((foo_ts, foo_js))
return ts_path, js_path
def testWarningWithDirectLitImport(self):
"""
If a TS file foo.ts or a JS file foo.js is changed, and there's direct
Lit import in the file, show warnings.
"""
lines = [
"import {aaa} from 'a.js';"
"import {css} from 'chrome://resources/mwc/lit/index.js';"
"import {aaa} from 'a.js';",
"import {css} from 'chrome://resources/mwc/lit/index.js';",
]
ts_path = os.path.join('some', 'path', 'foo.ts')
js_path = os.path.join('some', 'path', 'foo.js')
foo_ts = MockFile(ts_path, lines)
foo_js = MockFile(js_path, lines)
self.mock_input_api.files.append(foo_ts)
self.mock_input_api.files.append(foo_js)
ts_path, js_path = self.emulateJsAndTsFiles(lines)
errors = _CheckNoDirectLitImport(self.mock_input_api,
self.mock_output_api)
self.assertEqual(2, len(errors))
self.assertTrue(ts_path + ':1' in errors[0].message)
self.assertTrue(js_path + ':1' in errors[1].message)
self.assertTrue(ts_path + ':2' in errors[0].message)
self.assertTrue(js_path + ':2' in errors[1].message)
def testNoWarningWithDirectLitImportInXfBase(self):
"""
@ -48,8 +51,8 @@ class NoDirectLitImportPresubmit(unittest.TestCase):
there's direct lit import in the file, no warnings.
"""
lines = [
"import {aaa} from 'a.js';"
"import {css} from 'chrome://resources/mwc/lit/index.js';"
"import {aaa} from 'a.js';",
"import {css} from 'chrome://resources/mwc/lit/index.js';",
]
xf_base_ts = MockFile(
os.path.join('ui', 'file_manager', 'file_manager', 'widgets',
@ -64,14 +67,56 @@ class NoDirectLitImportPresubmit(unittest.TestCase):
If a TS file foo.ts is changed, and there is no direct Lit import
in the file, no warnings.
"""
foo_ts = MockFile(os.path.join('some', 'path', 'foo.ts'), '')
foo_js = MockFile(os.path.join('some', 'path', 'foo.js'), '')
self.mock_input_api.files.append(foo_ts)
self.mock_input_api.files.append(foo_js)
self.emulateJsAndTsFiles(lines=[])
errors = _CheckNoDirectLitImport(self.mock_input_api,
self.mock_output_api)
self.assertEqual([], errors)
class BannedTsTagsTest(unittest.TestCase):
def setUp(self):
self.mock_input_api = MockInputApi()
self.mock_input_api.change.RepositoryRoot = lambda: os.path.join(
os.path.dirname(__file__), '..', '..', '..')
self.mock_output_api = MockOutputApi()
def emulateJsAndTsFiles(self, lines):
ts_path = os.path.join('some', 'path', 'foo.ts')
js_path = os.path.join('some', 'path', 'foo.js')
foo_ts = MockFile(ts_path, lines)
foo_js = MockFile(js_path, lines)
self.mock_input_api.files.extend((foo_ts, foo_js))
return ts_path, js_path
def testNoTags(self):
lines = [
"import {aaa} from 'a.js';",
"import {css} from 'chrome://resources/mwc/lit/index.js';",
]
self.emulateJsAndTsFiles(lines)
errors = _CheckBannedTsTags(self.mock_input_api, self.mock_output_api)
self.assertEqual(0, len(errors))
def testTagOutsideComment(self):
lines = [
"import {aaa} from 'a.js';",
"@ts-ignore randomly in the code",
]
self.emulateJsAndTsFiles(lines)
errors = _CheckBannedTsTags(self.mock_input_api, self.mock_output_api)
self.assertEqual(0, len(errors))
def testDetectInComments(self):
lines = [
"// @ts-ignore: It should block for TS",
"import {aaa} from 'a.js';",
]
ts_path, js_path = self.emulateJsAndTsFiles(lines)
errors = _CheckBannedTsTags(self.mock_input_api, self.mock_output_api)
self.assertEqual(1, len(errors))
self.assertIn(ts_path, errors[0].items[0])
if __name__ == '__main__':
unittest.main()