Giter Club home page Giter Club logo

quick-lint / quick-lint-js Goto Github PK

View Code? Open in Web Editor NEW
1.5K 1.5K 192.0 34.47 MB

quick-lint-js finds bugs in JavaScript programs

Home Page: https://quick-lint-js.com

License: GNU General Public License v3.0

CMake 1.49% C++ 89.27% Shell 0.72% JavaScript 2.95% Python 1.45% HTML 0.13% Ruby 0.02% Nix 0.15% Go 2.22% Emacs Lisp 0.29% Lua 0.06% PowerShell 0.06% Vim Script 0.21% Jinja 0.07% TLA 0.30% Dockerfile 0.14% Makefile 0.03% Diff 0.44%
beginner-friendly javascript linter parser

quick-lint-js's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quick-lint-js's Issues

Improve error recovery for unterminated string literals

Inspired by issue #53.

In the following code, the programmer probably intends to escape the newline with a backslash or use a template literal:

let x = "hello
world";

Currently, quick-lint-js will interpret this code as having the following tokens:

  1. kw_let
  2. identifier (x)
  3. equal
  4. string ("hello)
  5. identifier (world)
  6. string (";)

Ideally, instead, it'd interpret this code as having the following tokens:

  1. kw_let
  2. identifier (x)
  3. equal
  4. string ("helloworld")
  5. semicolon

We can't just munch until the next ", 'cus that would be poor error recovery for code like this:

console.log("starting se
startServer(port);

Idea: if we see an end-of-line when parsing a string literal, check the following line. If the following line has exactly one matching " or ', treat that matching quote as the end of the current string. Otherwise, treat the end-of-line as the end of the current string.

The code for string literal parsing is in lex.cpp, and the existing tests are in test-lex.cpp.

Build no-exception and no-RTTI variants on CI

quick-lint-js should build with C++ exceptions and RTTI disabled. To make sure this remains true, add variants to CI which build quick-lint-js with these features disabled.

For GCC and Clang, I think the options we need are -fno-exceptions and -fno-rtti.

CI rules are inside the .github/ directory.

Vim ALE plugin crash

The following file causes our Vim ALE integration to crash:

let = 3;
x = 4;
Error detected while processing function <SNR>67_VimCloseCallback[11]..<SNR>67_VimExitCallback[14]..<S
NR>63_HandleExit[43]..quick_lint_js_ale#parse_command_output:
line    9:
E491: json decode error at '../src/include/quick-lint-js/parse.h:177: fatal: token not implemented in
parse_and_visit_statement: equal on line 1 column 5]}'

Parse 1_234_567 numbers

JavaScript number literals can contain underscores. quick-lint-js doesn't parse these as numbers, but it should.

Change lex.cpp and test-lex.cpp to teach quick-lint-js about number literals like 1_234_567.

Strict mode

JavaScript's strict mode affects many things which a linter cares about, such as the parsing of identifiers and octal literals. Detect strict mode and implement some rules.

Strict mode is tricky. It's lexically scoped. There are several ways a program can opt into strict mode, such as in a class declaration or expression, a "use strict"; expression statement, or a module.

Parse debugger statements

JavaScript has a debugger keyword which is used for ... debugging. quick-lint-js gets confused when it sees a debugger statement.

  1. Tell quick-lint-js that debugger is a keyword, not a normal identifier. See lex.h, lex-keyword.gperf, and test-lex.cpp.
  2. Teach quick-lint-js about debugger statements. See parse.h and test-parse.cpp. debugger statements should have no impact on the linter (I think).

Clean up temp dirs created by tests

The tests in test-file.cpp create a temporary directory on the file system, but they don't clean up when they're done. When a test finishes, delete the temporary directory and any files which might exist inside.

Add --version option

Add a --version option to the quick-lint-js command-line utility which prints quick-lint-js' version number and exits without linting.

Detect --version in options.cpp, add a variable to the option struct in options.cpp, test the option parsing in test-option.cpp, and print the version message in main.cpp.

See also the --help option introduced in PR #20.

bug: variables named "get" produce kw_get errors

When linting the following file

let get;

I expect quick-lint-js to produce no diagnostics.

But instead it tells me:

get.js:1:1: error: let with no bindings
get.js:1:4: error: missing semicolon after expression
<...>/src/./quick-lint-js/parse.h:210: fatal: token not implemented in parse_and_visit_statement: kw_get on line 1 column 5

This issue feels distinct from #28 because it produces two erroneous diagnostics before crashing.

Support -h and -v options

quick-lint-js' command-line options parser supports --help, but not -h. Teach it to parse -h as if it was --help. Same with --version and -v.

bug: variables named "from" produce kw_from errors

When linting the following file

from;

I expect quick-lint-js to tell me:

hello.js:1:1: error: use of undeclared variable: from

But instead it tells me:

<...>/quick-lint-js/src/include/quick-lint-js/parse.h:179: fatal: token not implemented in parse_and_visit_statement: kw_from on line 1 column 1

Parse `with` statements

JavaScript has a rarely-used with statement. Make quick-lint-js parse such statements (instead of crashing) by augmenting parse.h.

I think with statements have a very similar syntax to while statements, so we might be able to copy-paste code to parse with statements.

Teaching the linter the semantics of with statements is out of scope for this task.

Add --help option

Add a --help option to the quick-lint-js command-line utility which lists other supported options.

Detect --help in options.cpp, add a variable to the option struct in options.cpp, test the option parsing in test-option.cpp, and print the help message in main.cpp.

"illegal instruction" crash

This code:

let i = "test
";

results in this output on my system:

/home/frank/tmp/test.js:1:9: error: unclosed string literal
/home/frank/tmp/test.js:2:1: error: unclosed string literal
../src/parse.cpp:563: fatal: token not implemented in parse_expression_remainder: string on line 2 column 1
Illegal instruction

Looks like the program crashed with an "illegal instruction".

Report error when binary/octal/hex number has no digits

In debug builds, quick-lint-js crashes on the following JavaScript snippets:

let x = 0x;
let y = 0b;

This is because quick-lint-js assumes that a digit follows 0x or 0b, which is not necessarily true.

Teach quick-lint-js to report a user-friendly error on incomplete number literals. For example:

hello.js:1:9: binary number literal has no digits

Note: support for 0o-prefixed octal number literals will be added in #7.

Count non-ASCII characters correctly for column numbers

quick-lint-js gives incorrect column numbers when the source code contains non-ASCII characters:

/*☃*/x

Expected:

$ ./build/quick-lint-js hello.js
hello.js:1:6: error: use of undeclared variable: x

Observed:

$ ./build/quick-lint-js hello.js
hello.js:1:8: error: use of undeclared variable: x

quick-lint-js' locator should count ☃ as one column, not three.

  • CLI
  • WASM demo
  • LSP
  • Vim

Support non-ASCII Unicode

quick-lint-js should support UTF-8 input files, not just ASCII input files.

  • Non-ASCII in identifiers (#64)
  • Non-ASCII in identifier escapes (#62)
  • Non-ASCII in string and template literals
  • Non-ASCII in comments
  • Non-ASCII in horizontal whitespace
  • Non-ASCII line terminators
  • Column numbers if line contains non-ASCII characters (#63)

Support wchar_t in command-line parsing

The command-line parser uses char. This is [likely] problematic on Windows if command-line arguments contain non-ASCII characters. Make the command-line parser support wchar_t and WinMain.

This change might have ripple effects, such as the CreateFileA call in read_file. We should probably do some UTF-16-to-UTF-8 conversions to ease the transition.

Request: please rename `master` branch to something less colonial

Hello, Mr. Strager.

I was looking for a fast way to lint our large javascript project when I came across this tool. This looks great, unfortunately I have some pretty strong issues about the name of your default branch.

The master branch is a term from when slave-masters would force their slaves to write their tests and maintenance tickets, as well as updating their dependencies.

Since slavery has been abolished, I feel that it is best to remove this vestige of slavery by giving the main branch more inclusive name like main, prod, or release.

Thank you for taking the time to read this. And if this racist code can be cleaned up a bit, I hope our team can start adopting quick-lint

Parse non-ASCII identifiers

JavaScript allows certain non-ASCII characters in identifiers. For example:

let Ƞ = "hello";
console.log(Ƞ);  // Prints 'hello'.

This confuses quick-lint-js. Make our lexer parse UTF-8 properly and recognize identifier characters.

Run CI on pull requests

The GitHub Actions workflows for building and testing only run on my branches, not on pull requests. Make them run on pull requests, too.

Previous attempt: strager@e55b699

Report error for trailing underscores in number literals

If a number literal has trailing underscores (123_), the syntax is invalid. quick-lint-js should report an error for such constructs. Edit error.h, lex.cpp, and test-lex.cpp to make quick-lint-js help users find this bug.

std::filesystem linking problem with GCC 8

etra0 had issues building quick-lint-js with GCC 8. In their words:

Used instructions in the README, which are:
$ cmake .
$ cmake --build .

and throws linking errors. Using the ones in travis.yml works:
$ cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=YES -S . -B .
$ cmake --build . --config Debug


$ CXX=g++-8 cmake .
-- The C compiler identification is GNU 7.5.0
-- The CXX compiler identification is GNU 8.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/g++-8
-- Check for working CXX compiler: /usr/bin/g++-8 -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Performing Test QUICK_LINT_JS_COMPILER_SUPPORTS_DESIGNATED_INITIALIZERS
-- Performing Test QUICK_LINT_JS_COMPILER_SUPPORTS_DESIGNATED_INITIALIZERS - Success
-- Performing Test QUICK_LINT_JS_HAVE_FCHAR8_T
-- Performing Test QUICK_LINT_JS_HAVE_FCHAR8_T - Failed
-- Failed to find LLVM FileCheck
-- Found Git: /usr/bin/git (found version "2.17.1")
-- git Version: v0.0.0
-- Version: 0.0.0
-- Performing Test HAVE_CXX_FLAG_STD_CXX11
-- Performing Test HAVE_CXX_FLAG_STD_CXX11 - Success
-- Performing Test HAVE_CXX_FLAG_WALL
-- Performing Test HAVE_CXX_FLAG_WALL - Success
-- Performing Test HAVE_CXX_FLAG_WEXTRA
-- Performing Test HAVE_CXX_FLAG_WEXTRA - Success
-- Performing Test HAVE_CXX_FLAG_WSHADOW
-- Performing Test HAVE_CXX_FLAG_WSHADOW - Success
-- Performing Test HAVE_CXX_FLAG_WERROR
-- Performing Test HAVE_CXX_FLAG_WERROR - Success
-- Performing Test HAVE_CXX_FLAG_WSHORTEN_64_TO_32
-- Performing Test HAVE_CXX_FLAG_WSHORTEN_64_TO_32 - Failed
-- Performing Test HAVE_CXX_FLAG_FSTRICT_ALIASING
-- Performing Test HAVE_CXX_FLAG_FSTRICT_ALIASING - Success
-- Performing Test HAVE_CXX_FLAG_WNO_DEPRECATED_DECLARATIONS
-- Performing Test HAVE_CXX_FLAG_WNO_DEPRECATED_DECLARATIONS - Success
-- Performing Test HAVE_CXX_FLAG_WNO_DEPRECATED
-- Performing Test HAVE_CXX_FLAG_WNO_DEPRECATED - Success
-- Performing Test HAVE_CXX_FLAG_FNO_EXCEPTIONS
-- Performing Test HAVE_CXX_FLAG_FNO_EXCEPTIONS - Success
-- Performing Test HAVE_CXX_FLAG_WSTRICT_ALIASING
-- Performing Test HAVE_CXX_FLAG_WSTRICT_ALIASING - Success
-- Performing Test HAVE_CXX_FLAG_WD654
-- Performing Test HAVE_CXX_FLAG_WD654 - Failed
-- Performing Test HAVE_CXX_FLAG_WTHREAD_SAFETY
-- Performing Test HAVE_CXX_FLAG_WTHREAD_SAFETY - Failed
-- Performing Test HAVE_CXX_FLAG_COVERAGE
-- Performing Test HAVE_CXX_FLAG_COVERAGE - Success
-- Performing Test HAVE_STD_REGEX
-- Performing Test HAVE_STD_REGEX
-- Performing Test HAVE_STD_REGEX -- success
-- Performing Test HAVE_GNU_POSIX_REGEX
-- Performing Test HAVE_GNU_POSIX_REGEX
-- Performing Test HAVE_GNU_POSIX_REGEX -- failed to compile
-- Performing Test HAVE_POSIX_REGEX
-- Performing Test HAVE_POSIX_REGEX
-- Performing Test HAVE_POSIX_REGEX -- success
-- Performing Test HAVE_STEADY_CLOCK
-- Performing Test HAVE_STEADY_CLOCK
-- Performing Test HAVE_STEADY_CLOCK -- success
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Check if compiler accepts -pthread
-- Check if compiler accepts -pthread - yes
-- Found Threads: TRUE
-- Performing Test QUICK_LINT_JS_HAVE_WARNING_OPTION__WNO_NULL_POINTER_ARITHMETIC
-- Performing Test QUICK_LINT_JS_HAVE_WARNING_OPTION__WNO_NULL_POINTER_ARITHMETIC - Success
-- Performing Test QUICK_LINT_JS_HAVE_WARNING_OPTION__WNO_MISSING_INCLUDE_DIRS
-- Performing Test QUICK_LINT_JS_HAVE_WARNING_OPTION__WNO_MISSING_INCLUDE_DIRS - Success
-- Found PythonInterp: /home/etra/miniconda3/bin/python (found version "3.8.5")
-- JsonCpp Version: 1.9.3
-- Looking for C++ include clocale
-- Looking for C++ include clocale - found
-- Looking for localeconv
-- Looking for localeconv - found
-- Looking for C++ include sys/types.h
-- Looking for C++ include sys/types.h - found
-- Looking for C++ include stdint.h
-- Looking for C++ include stdint.h - found
-- Looking for C++ include stddef.h
-- Looking for C++ include stddef.h - found
-- Check size of lconv
-- Check size of lconv - done
-- Performing Test HAVE_DECIMAL_POINT
-- Performing Test HAVE_DECIMAL_POINT - Success
-- Performing Test QUICK_LINT_JS_HAVE_STD_FILESYSTEM_WITH_STDCXXFS
-- Performing Test QUICK_LINT_JS_HAVE_STD_FILESYSTEM_WITH_STDCXXFS - Success
-- Performing Test QUICK_LINT_JS_HAVE_STD_EXPERIMENTAL_FILESYSTEM_WITH_STDCXXFS
-- Performing Test QUICK_LINT_JS_HAVE_STD_EXPERIMENTAL_FILESYSTEM_WITH_STDCXXFS - Success
-- Performing Test QUICK_LINT_JS_HAVE_WARNING_OPTION__WD26495
-- Performing Test QUICK_LINT_JS_HAVE_WARNING_OPTION__WD26495 - Failed
-- Performing Test QUICK_LINT_JS_HAVE_WARNING_OPTION__WD26812
-- Performing Test QUICK_LINT_JS_HAVE_WARNING_OPTION__WD26812 - Failed
-- Configuring done
-- Generating done
-- Build files have been written to: /mnt/c/Users/Sebastian/Documents/work/quick-lint-js
Scanning dependencies of target benchmark
[  1%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/benchmark.cc.o
[  2%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/benchmark_api_internal.cc.o
[  3%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/benchmark_name.cc.o
[  4%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/benchmark_register.cc.o
[  5%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/benchmark_runner.cc.o
[  7%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/colorprint.cc.o
[  8%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/commandlineflags.cc.o
[  9%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/complexity.cc.o
[ 10%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/console_reporter.cc.o
[ 11%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/counter.cc.o
[ 12%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/csv_reporter.cc.o
[ 14%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/json_reporter.cc.o
[ 15%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/reporter.cc.o
[ 16%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/sleep.cc.o
[ 17%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/statistics.cc.o
[ 18%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/string_util.cc.o
[ 20%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/sysinfo.cc.o
[ 21%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark.dir/timers.cc.o
[ 22%] Linking CXX static library libbenchmark.a
[ 22%] Built target benchmark
Scanning dependencies of target benchmark_main
[ 23%] Building CXX object vendor/benchmark/src/CMakeFiles/benchmark_main.dir/benchmark_main.cc.o
[ 24%] Linking CXX static library libbenchmark_main.a
[ 24%] Built target benchmark_main
Scanning dependencies of target boost_container
[ 25%] Building CXX object vendor/boost/libs/container/CMakeFiles/boost_container.dir/src/dlmalloc.cpp.o
[ 27%] Building CXX object vendor/boost/libs/container/CMakeFiles/boost_container.dir/src/global_resource.cpp.o
[ 28%] Building CXX object vendor/boost/libs/container/CMakeFiles/boost_container.dir/src/monotonic_buffer_resource.cpp.o
[ 29%] Building CXX object vendor/boost/libs/container/CMakeFiles/boost_container.dir/src/pool_resource.cpp.o
[ 30%] Building CXX object vendor/boost/libs/container/CMakeFiles/boost_container.dir/src/synchronized_pool_resource.cpp.o
[ 31%] Building CXX object vendor/boost/libs/container/CMakeFiles/boost_container.dir/src/unsynchronized_pool_resource.cpp.o
[ 32%] Building C object vendor/boost/libs/container/CMakeFiles/boost_container.dir/src/alloc_lib.c.o
[ 34%] Linking CXX static library libboost_container.a
[ 34%] Built target boost_container
Scanning dependencies of target gtest
[ 35%] Building CXX object vendor/googletest/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o
[ 36%] Linking CXX static library ../../../lib/libgtest.a
[ 36%] Built target gtest
Scanning dependencies of target gmock
[ 37%] Building CXX object vendor/googletest/googlemock/CMakeFiles/gmock.dir/src/gmock-all.cc.o
[ 38%] Linking CXX static library ../../../lib/libgmock.a
[ 38%] Built target gmock
Scanning dependencies of target gmock_main
[ 40%] Building CXX object vendor/googletest/googlemock/CMakeFiles/gmock_main.dir/src/gmock_main.cc.o
[ 41%] Linking CXX static library ../../../lib/libgmock_main.a
[ 41%] Built target gmock_main
Scanning dependencies of target gtest_main
[ 42%] Building CXX object vendor/googletest/googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o
[ 43%] Linking CXX static library ../../../lib/libgtest_main.a
[ 43%] Built target gtest_main
Scanning dependencies of target jsoncpp_lib
[ 44%] Building CXX object vendor/jsoncpp/src/lib_json/CMakeFiles/jsoncpp_lib.dir/json_reader.cpp.o
[ 45%] Building CXX object vendor/jsoncpp/src/lib_json/CMakeFiles/jsoncpp_lib.dir/json_value.cpp.o
[ 47%] Building CXX object vendor/jsoncpp/src/lib_json/CMakeFiles/jsoncpp_lib.dir/json_writer.cpp.o
[ 48%] Linking CXX static library libjsoncpp.a
[ 48%] Built target jsoncpp_lib
Scanning dependencies of target quick-lint-js-lib
[ 49%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/assert.cpp.o
[ 50%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/char8.cpp.o
[ 51%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/error.cpp.o
[ 52%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/file.cpp.o
[ 54%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/integer.cpp.o
[ 55%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/language.cpp.o
[ 56%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/lex-keyword.cpp.o
[ 57%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/lex.cpp.o
[ 58%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/lint.cpp.o
[ 60%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/location.cpp.o
[ 61%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/options.cpp.o
[ 62%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/padded-string.cpp.o
[ 63%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/parse.cpp.o
[ 64%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/text-error-reporter.cpp.o
[ 65%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/vector.cpp.o
[ 67%] Building CXX object src/CMakeFiles/quick-lint-js-lib.dir/vim-qflist-json-error-reporter.cpp.o
[ 68%] Linking CXX static library libquick-lint-js-lib.a
[ 68%] Built target quick-lint-js-lib
Scanning dependencies of target quick-lint-js-benchmark-location
[ 69%] Building CXX object benchmark/CMakeFiles/quick-lint-js-benchmark-location.dir/benchmark-location.cpp.o
[ 70%] Linking CXX executable quick-lint-js-benchmark-location
[ 70%] Built target quick-lint-js-benchmark-location
Scanning dependencies of target quick-lint-js-benchmark-lex
[ 71%] Building CXX object benchmark/CMakeFiles/quick-lint-js-benchmark-lex.dir/benchmark-lex.cpp.o
[ 72%] Linking CXX executable quick-lint-js-benchmark-lex
[ 72%] Built target quick-lint-js-benchmark-lex
Scanning dependencies of target quick-lint-js-benchmark-parse
[ 74%] Building CXX object benchmark/CMakeFiles/quick-lint-js-benchmark-parse.dir/benchmark-parse.cpp.o
[ 75%] Linking CXX executable quick-lint-js-benchmark-parse
[ 75%] Built target quick-lint-js-benchmark-parse
Scanning dependencies of target quick-lint-js
[ 76%] Building CXX object src/CMakeFiles/quick-lint-js.dir/main.cpp.o
[ 77%] Linking CXX executable quick-lint-js
[ 77%] Built target quick-lint-js
Scanning dependencies of target quick-lint-js-test
[ 78%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/error-collector.cpp.o
[ 80%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/spy-visitor.cpp.o
[ 81%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-assert.cpp.o
[ 82%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-buffering-visitor.cpp.o
[ 83%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-file.cpp.o
[ 84%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-integer.cpp.o
[ 85%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-lex.cpp.o
[ 87%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-lint-parse.cpp.o
[ 88%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-lint.cpp.o
[ 89%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-location.cpp.o
[ 90%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-narrow-cast.cpp.o
[ 91%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-options.cpp.o
[ 92%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-padded-string.cpp.o
[ 94%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-parse-expression.cpp.o
[ 95%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-parse.cpp.o
[ 96%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-text-error-reporter.cpp.o
[ 97%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-vector.cpp.o
[ 98%] Building CXX object test/CMakeFiles/quick-lint-js-test.dir/test-vim-qflist-json-error-reporter.cpp.o
[100%] Linking CXX executable quick-lint-js-test
CMakeFiles/quick-lint-js-test.dir/test-file.cpp.o: In function `quick_lint_js::(anonymous namespace)::make_temporary_directory()':
test-file.cpp:(.text+0x1aa1): undefined reference to `std::filesystem::temp_directory_path[abi:cxx11]()'
CMakeFiles/quick-lint-js-test.dir/test-file.cpp.o: In function `std::filesystem::__cxx11::path::path(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&, std::filesystem::__cxx11::path::format)':
test-file.cpp:(.text._ZNSt10filesystem7__cxx114pathC2EONSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS1_6formatE[_ZNSt10filesystem7__cxx114pathC5EONSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS1_6formatE]+0x4f): undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()'
CMakeFiles/quick-lint-js-test.dir/test-file.cpp.o: In function `std::filesystem::__cxx11::path::operator/=(std::filesystem::__cxx11::path const&)':
test-file.cpp:(.text._ZNSt10filesystem7__cxx114pathdVERKS1_[_ZNSt10filesystem7__cxx114pathdVERKS1_]+0x3d): undefined reference to `std::filesystem::__cxx11::path::has_filename() const'
test-file.cpp:(.text._ZNSt10filesystem7__cxx114pathdVERKS1_[_ZNSt10filesystem7__cxx114pathdVERKS1_]+0x98): undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()'
CMakeFiles/quick-lint-js-test.dir/test-file.cpp.o: In function `std::filesystem::__cxx11::path::is_absolute() const':
test-file.cpp:(.text._ZNKSt10filesystem7__cxx114path11is_absoluteEv[_ZNKSt10filesystem7__cxx114path11is_absoluteEv]+0x14): undefined reference to `std::filesystem::__cxx11::path::has_root_directory() const'
CMakeFiles/quick-lint-js-test.dir/test-file.cpp.o: In function `std::filesystem::__cxx11::path::path<char [8], std::filesystem::__cxx11::path>(char const (&) [8], std::filesystem::__cxx11::path::format)':
test-file.cpp:(.text._ZNSt10filesystem7__cxx114pathC2IA8_cS1_EERKT_NS1_6formatE[_ZNSt10filesystem7__cxx114pathC5IA8_cS1_EERKT_NS1_6formatE]+0x6d): undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()'
CMakeFiles/quick-lint-js-test.dir/test-file.cpp.o: In function `std::filesystem::__cxx11::path::path<char [18], std::filesystem::__cxx11::path>(char const (&) [18], std::filesystem::__cxx11::path::format)':
test-file.cpp:(.text._ZNSt10filesystem7__cxx114pathC2IA18_cS1_EERKT_NS1_6formatE[_ZNSt10filesystem7__cxx114pathC5IA18_cS1_EERKT_NS1_6formatE]+0x6d): undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()'
CMakeFiles/quick-lint-js-test.dir/test-file.cpp.o: In function `std::filesystem::__cxx11::path::path<char [21], std::filesystem::__cxx11::path>(char const (&) [21], std::filesystem::__cxx11::path::format)':
test-file.cpp:(.text._ZNSt10filesystem7__cxx114pathC2IA21_cS1_EERKT_NS1_6formatE[_ZNSt10filesystem7__cxx114pathC5IA21_cS1_EERKT_NS1_6formatE]+0x6d): undefined reference to `std::filesystem::__cxx11::path::_M_split_cmpts()'
collect2: error: ld returned 1 exit status
make[2]: *** [test/quick-lint-js-test] Error 1
test/CMakeFiles/quick-lint-js-test.dir/build.make:544: recipe for target 'test/quick-lint-js-test' failed
make[1]: *** [test/CMakeFiles/quick-lint-js-test.dir/all] Error 2
CMakeFiles/Makefile2:1990: recipe for target 'test/CMakeFiles/quick-lint-js-test.dir/all' failed
make: *** [all] Error 2
Makefile:140: recipe for target 'all' failed

Report an error if `throw` is given no expression

The following snippets of code are invalid JavaScript:

throw;
throw
  new Error();

Unfortunately, quick-lint-js accepts these snippets without reporting an error. Teach quick-lint-js to report an error by editing parse.h, test-parse.cpp, and error.h.

Parse <!-- --> comments

JavaScript allows <!-- and --> for comments. quick-lint-js doesn't understand such comments. Edit lex.cpp and test-lex.cpp. See skip_block_comment and skip_line_comment for related code.

  • <!--
  • -->

Parse escaped newlines in string and template literals

JavaScript string literals and template literals can contain backslash-escaped newlines:

let s = "hello\
world";
let t = `hello\
world`;

Make sure these parse correctly as part of the string/template. Test in test-lex.cpp, fix in lex.cpp.

Report one error instead of two for assign-before-decl + assign-to-const

For the following snippet of code, quick-lint-js reports two errors:

x = 42;
const x;
hello.js:1:1: error: assignment to const variable
hello.js:2:7: note: const variable declared here
hello.js:1:1: error: variable assigned before its declaration
hello.js:2:7: note: variable declared here

Edit error.h, lint.cpp, and test-lint.cpp to combine these errors into a new type of error to reduce noise. For example:

hello.js:1:1: error: assignment to const variable before its declaration
hello.js:2:7: note: const variable declared here

Run fuzzers on CI

It'd be cool if we could set up continuous or occasional fuzzing. Perhaps Microsoft's new service might help?

Parse octal number literals

quick-lint-js understands hexadecimal, binary, and decimal number literals, but doesn't understand octal number literals.

Teach quick-lint-js to parse octal number literals in lex.cpp and in test-lex.cpp.

Error on invalid hex escape sequences: "hello\x1qworld"

String literals can contain hexadecimal escape sequences (starting with \x). If the escape sequence is invalid, quick-lint-js should report an error. Teach quick-lint-js about such errors in lex.cpp, error.h, and test-lex.cpp.

Report warning if number literal will lose precision

JavaScript interprets the literal 9999999999999999 as the number 10000000000000000. Report a warning in this case.

  • Research limits of JavaScript integer literals.
  • Create an error type in error.h. (Error types can have a severity of warning.)
  • Add some tests for the error cases in test-lex.cpp.
  • Emit the errors in lex.cpp.

Distinguish warnings from errors

Note: I think this task needs a bit more C++ skill than other good-first-issue issues.

Currently, all issues reported by quick-lint-js are called "errors". Some issues, such as use-of-undeclared-variable, are really warnings, not errors. Make quick-lint-js label such issues as warnings.

  • text_error_reporter: say "warning:" instead of "error:"
  • vim_qflist_json_error_reporter: set error type to "W" instead of "E"
  • lsp_error_reporter: set severity to Warning (2) instead of Error (1)

Relevant code exists in error.h, error-formatter.h, *-error-reporter.cpp, and test-*-error-reporter.cpp.

7$: `x += 1` reports two errors, should report one

If you run quick-lint-js on the following program, the linter reports two issues:

x += 4;
hello.js:1:1: error: use of undeclared variable: x
hello.js:1:1: error: assignment to undeclared variable

quick-lint-js should instead report just one error. For example:

hello.js:1:1: error: use and assignment of undeclared variable: x

Tweak variable-analyzer.cpp, diagnostic-types.h, and test-variable-analyzer.cpp to make quick-lint-js be less noisy.

Run precise benchmarks on CI

We could run some precise benchmarks on CI. Examples:

  • Maximum memory usage (ASLR should be disabled)
  • Instruction count (ASLR should be disabled?)
  • Cycle count (ASLR should be disabled) (needs a CPU emulator)

Valgrind might help a lot.

Also, we need to store the collected data somewhere, and have some fancy dashboards to present the data.

Convert \u{} in identifiers into UTF-8

When quick-lint-js encounters an identifier with an escape sequence, it replaces the escape sequence with the escaped character:

let a = "hello";
console.log(\u{61});  // Prints 'hello'. '\u{61}' is replaced with 'a' in-place during lexing.

Currently, we only support ASCII characters. We should support non-ASCII characters:

let \u{0220} = "hello";
console.log(\u{61});  // Prints 'hello'. '\u{0220}' should be replaced with bytes 0xC8 0xA0 in-place during lexing.

Note: Recognizing unescaped non-ASCII characters is out of scope for this task.

Default loctation of qljs executable after building

When building qljs with cmake --build ., the executable is placed at src/quick-lint-js.

Not familiar other projects' patterns, but wondering if it is normal to place the compiled target in the src directory.

But, truth is, this whole issue was just an excuse to use GitHub CLI to create an issue. And it was a resounding success

Exit non-zero if any errors

Note: I think this task needs a bit more C++ skill than other good-first-issue issues.

If quick-lint-js's CLI reports an error in a JavaScript program, it should return a non-zero exit code like other linters. Our CLI currently returns zero always.

Idea for implementation:

  1. Create an error_reporter-derived class which tracks if any errors were detected, forwarding errors to another error_reporter object.
  2. In main.cpp, use the wrapping error_reporter created in step 1.

Disallow lone number literals in object literals

({ foo }) is a valid JavaScript expression, but ({ 42 }) is not. Make quick-lint-js report an error for the latter code. Look at parse-expression.cpp, parse.cpp, and error.h. (There's a TODO comment in parse.cpp.)

Support underscores in hex literals: 0x1234_5678

JavaScript supports underscores in number literals, including hex literals. quick-lint-js understands underscores in decimal literals (123_456), but doesn't understand underscores in hexadecimal literals (0x1234_5678).

Edit lex.cpp and test-lex.cpp to teach quick-lint-js to ignore underscores in hex literals.

Report error for extra underscores in number literals

If a number literal has doubled underscores (123__456) or trailing underscores (123_), the syntax is invalid. quick-lint-js should report an error for such constructs. Edit error.h, lex.cpp, and test-lex.cpp to make quick-lint-js help users find this bug.

Report error for let x=x

For the following code, the linter can't do a good job with what the parser gives it:

let x = x;

Current behavior of parser:

  1. variable_use: x
  2. variable_declaration: let x

Desired behavior of parser:

  1. variable_declaration: let x
  2. variable_use: x
  3. variable_assignment: x

Report error for invalid hexadecimal digits: 0x12abq

quick-lint-js reports an error if a decimal or binary number literal contains bogus digits:

// hello.js:2:5: error: unexpected characters in number literal
1234abcd

Give hexadecimal literals the same error-reporting treatment. See parse_binary_number in lex.cpp, and tests in test-lex.cpp.

Lint loop labels

JavaScript loops can have labels, and break and continue statements can refer to those labels:

outer: for (let y of ys) {
  for (let x of xs) {
    if (x == y) {
      break outer;
    }
  }
}

quick-lint-js currently doesn't ensure labels in break and continue statements refer to breakable or continuable loops. Teach the variable analyzer (or something else) to detect problems related to loop labels, such as the following:

  • break/continue: label doesn't exist at all in the current function
  • break/continue: Label is attached to an unrelated loop
  • label: Label is not attached to a loop statement (maybe not? doesn't seem like a serious problem to complain about by default.)

The parser doesn't report visits for a lot of information needed to do this analysis (such as the labels themselves, or loop structures), so this is a decently involved task.

Error parsing 'const'.

quick-lint-js/src/parse.cpp:504: fatal: token not implemented in parse_expression_remainder: kw_const on line 3 column 1

I'm parsing a file with const in it ... I guess that is the issue. This was on master.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.