Skip to content
This repository has been archived by the owner on Oct 19, 2021. It is now read-only.

Several enhancements, including CJSX fixes #632

Closed
wants to merge 7 commits into from

Conversation

aminland
Copy link

@aminland aminland commented Jan 16, 2018

Fixes colon and comma spacing issues from CSX (JSX) format described in #629

@aminland aminland force-pushed the patch-1 branch 3 times, most recently from e4e882e to 7e80ca0 Compare January 17, 2018 03:48
@aminland
Copy link
Author

Also fixes #630 and #619

@aminland aminland force-pushed the patch-1 branch 5 times, most recently from c590760 to c673321 Compare February 6, 2018 08:46
@aminland
Copy link
Author

Until such time as you start accepting pull requests again, this code (with many more changes) will live at https://github.com/aminland/coffeelint2

named coffeelint2 for coffeescript 2 support. (also works nicely with eslint via my eslint-plugin-coffee)

@aminland aminland changed the title Don't break on CSX property assignment Support for Coffeescript 2 (including JSX) Feb 14, 2018
@swang
Copy link
Collaborator

swang commented Feb 16, 2018

Hi. Thanks for the PR

There seems to be 3 separate requests in this one PR.

  1. Update CoffeeScript, which I'll check and handle in a bit.
  2. Some kind of config extender? Not sure why that isn't mentioned at all in your description.
  3. I haven't found a proper solution to CSX but solving it should fix the issue for all rules. The code seems to only address 3 rules? Fixing coffeelint to handle CSX sounds very complicated without having some initial discussion first. To me handling CSX seems to entail something like:
    a. having the base lintToken class ignore everything in-between CSX tags but still lint the attributes and interpolated code generated.
    b. have a separate "rule" to handle CSX, including separate (from the rest of coffeelint) rules for spacing/linting attributes and interpolated code.
    c. Similar to a but have some "parseCSX" property in the class of the rules that signifies whether the rules want to parse CSX or not.

I haven't implemented anything because I haven't spent much time with CSX/CS2. I think if someone started a discussion and had a good way to implement it, I would merge it. But I think handling it for each individual rule sounds like a nightmare.

Also it looks like you deleted some tests and some code that don't seem clear to me why you're deleting them. The tests added should also provide enough coverage where I feel confident that the implementation is sound. I'm not saying I need 100 tests, but the tests should appear to have coverage for the general cases.

@aminland
Copy link
Author

Hi,

I've added more items since you last looked. In an effort to make this easier I rebased the hell out of my commits so that they're each somewhat self-contained in what they do.

In terms of the issues you raised:

  1. the config extend commit is so that one can, let's say, in package.json coffeeLintConfig, extend a relative path (e.g. "extends": "../coffeeLintConfig/index"). Without this commit you can only extend things that are installed in node_modules (thus preventing you from dynamically generating a config locally).

  2. Surprisingly, you don't need to do all that to get CJSX files to work correctly. The reason is simple: since we're using the CoffeeScript lexer, and that lexer supports CJSX via a hack of sorts, there's not much required to support it. At least in terms of the default rule configs, these basic changes are sufficient.
    If you find other situations where CJSX tags break other rules, I'll be glad to fix those as well.

What this PR doesn't do is enable new rules to be written that specifically apply only in a CJSX context.

  1. That last commit adds column numbers to the context for all errors (and for lexical lint rules, end positions as well). This is done so that when using an editor you can get proper highlighting.

--
The way I see it, coffeelint is mostly for syntax validation, and coffee-style preference checking. All of these changes were basically done with the aim of not running coffeelint directly, but rather, just using eslint. Eslint is much more powerful, and can do all sorts of extra things. With these changes in place, I was able to make eslint-plugin-coffee which enables full compatibility of eslint with coffee (and allowing direct checking / configuration of coffeelint style rules).

@@ -24,11 +24,17 @@ task 'compile:commandline', 'Compiles commandline.js', ->
coffeeSync 'src/cache.coffee', 'lib/cache.js'
coffeeSync 'src/ruleLoader.coffee', 'lib/ruleLoader.js'
fs.mkdirSync 'lib/reporters' unless fs.existsSync 'lib/reporters'
fs.mkdirSync 'lib/rules' unless fs.existsSync 'lib/rules'
Copy link
Author

Choose a reason for hiding this comment

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

This is needed so we can export the default rules for use in eslint.

@@ -18,6 +18,9 @@
"space_operators": {
"level": "error"
},
"max_line_length": {
"value": "100"
Copy link
Author

Choose a reason for hiding this comment

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

80 is just wayyy too low, it was causing issues in the test files. Easier to just up the limit than to adhere to a dogmatic 80.

@@ -32,8 +32,8 @@
"strip-json-comments": "^1.0.2"
},
"devDependencies": {
"vows": ">=0.8.1",
"underscore": ">=1.4.4"
"underscore": ">=1.4.4",
Copy link
Author

Choose a reason for hiding this comment

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

npm automatically alphabeticalizes now.

@@ -310,9 +309,10 @@ coffeelint.lint = (source, userConfig = {}, literate = false) ->

# only do further checks if the syntax is okay, otherwise they just fail
# with syntax error exceptions
unless hasSyntaxError(source)
tokens = getTokens(source)
Copy link
Author

Choose a reason for hiding this comment

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

Here we were passing the source to Coffeescript before twice, which basically means we're doing twice as much work as needed.

return null if not config[attr]?
config = config[attr]

config.__location__ = filename
Copy link
Author

Choose a reason for hiding this comment

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

This is so we can remember where the config file is loaded from, so we can resolve the "extends" property relative to the location of the configfile (as opposed to the cwd)

unless config.extends
return config
try
parentConfig = require resolve config.extends,
Copy link
Author

Choose a reason for hiding this comment

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

if we cant resolve the path relative to our present directory, then we can look in node_modules

@@ -18,10 +18,10 @@ BaseLinter = require './base_linter.coffee'
#
module.exports = class LexicalLinter extends BaseLinter

constructor: (source, config, rules, CoffeeScript) ->
constructor: (source, config, rules, CoffeeScript, tokens) ->
Copy link
Author

Choose a reason for hiding this comment

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

This is so we can pass in the tokens from coffeelint.coffee (so we're not running CoffeeScript.tokens(source) twice)

@@ -57,7 +60,8 @@ module.exports = class ColonAssignmentSpacing
[isLeftSpaced, leftSpacing] = checkSpacing 'left'
[isRightSpaced, rightSpacing] = checkSpacing 'right'

if isLeftSpaced and isRightSpaced
if token.csxColon or isLeftSpaced and isRightSpaced
Copy link
Author

Choose a reason for hiding this comment

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

we have no control over spacing of "csxColons" (these are autogenerated by the compiler)

@trackStringStart()
@blocks = []

lintToken: (token, tokenApi) ->
Copy link
Author

Choose a reason for hiding this comment

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

I rewrote this function from scratch. To test for nested interpolation the old way is problematic since {} code blocks inside CSX tags are treated as nested interpolation in the old scheme.
In the new way, we keep track of visited string_start and string_end per csx tag. Each time we encounter a csx tag, we nest to another 'block', with its own tracking.

@@ -5,6 +5,7 @@ module.exports = class PreferEnglishOperator
level: 'ignore'
message: 'Don\'t use &&, ||, ==, !=, or !'
doubleNotLevel: 'ignore'
ops: ['and', 'or', 'not', 'is', 'isnt']
Copy link
Author

Choose a reason for hiding this comment

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

This was just a preference thing. Rather than making a new custom rule that does a subset of what this rule does, the rule is now configurable so people can specify which english operators they prefer. Much nicer this way, for those who aren't a fan of "isnt" as an operator...

# Coffeescript does some code generation when using CSX syntax, and it adds
# brackets & commas that are not marked as generated. The only way to check
# these is to see if the comma has the same column number as the last token.
isGenerated: (token, tokenApi) ->
Copy link
Author

@aminland aminland Feb 23, 2018

Choose a reason for hiding this comment

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

This function can be simplified later if the underlying coffeescript lexer starts marking things as generated.

@aminland aminland changed the title Support for Coffeescript 2 (including JSX) Several enhancements, including CJSX fixes Feb 23, 2018
@aminland
Copy link
Author

If you really want me to split to multiple PRs I can, but i don't see a need as I don't think i've done anything controversial...

@jaredmoody
Copy link

What's the status here, can this be merged - or should separate PRs be submitted - or something else?

I need jsx support on my project so would be nice to have this on the main repo instead of having to use a different package.

@aminland
Copy link
Author

bump.

@UziTech
Copy link

UziTech commented Jan 14, 2020

This will be added to @coffeelint/cli in coffeelint/coffeelint#8. Thanks!

@aminland aminland closed this Jul 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants