-
Notifications
You must be signed in to change notification settings - Fork 2k
Possible bug with dot at beginning of line, ternary and object #4150
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
Comments
There are many ways to confuse the compiler with leading periods. Please use parentheses to make your intentions clear: gulp.task 'stylus', ->
gulp.src([
'./src/stylus/vars.styl'
'./src/stylus/**/*.styl'
])
.pipe if argv.sourcemaps then require('gulp-sourcemaps').init() else gutil.noop()
.pipe require('gulp-concat') 'styles.styl'
.pipe(require('gulp-stylus')(
use: require('nib')())
).pipe(if isLocal() then gutil.noop() else require('gulp-minify-css')
compatibility: '' # Empty string is IE9+ (this is default)
).pipe if argv.sourcemaps then require('gulp-sourcemaps').write() else gutil.noop()
.pipe gulp.dest './dist/css' |
That's a shame. What's the point in the feature if you can't use it? Or what's the rule on when it can be used and when it can't? |
It works well when there aren’t indented lines inside the chaining ( It’s similar to how sometimes parentheses are required for function calls, for example if you have other code afterward on the same line. When you chain like this, you’re really creating one long line of code; so sometimes parentheses are required to disambiguate. So to answer your question: use chaining when each line starts with a period. If you need a multiline block in one of the parts of the chain, wrap that block in parentheses (like I did for |
I agree. Perhaps the logic for closing implicit calls for leading |
Would it help (and make sense? it would to me) to interpret deeper indentation on a following line as a continuation, versus equal (or lesser) indentation as the end of the preceding function call? Having said that, my own example would break that rule; the first |
Chaining is supposed to be unindented: $('#button')
.show()
.hide()
.css('color', 'red')
.show() Which is why it was surprising that your example worked at all. |
Does it actually make a difference to the parser at present? If the next line is starting with a I always presumed not, and liked to indent chaining lines as an extra visual clue that they are a continuation of something earlier. (And it always worked for me when I expected it to -- or almost always.) But I have no problem changing the way I write if it would disambiguate and help in keeping code and diffs terse (read: fewer parens). So perhaps the code example in this thread should now be this: gulp.task 'stylus', ->
gulp.src [
'./src/stylus/vars.styl'
'./src/stylus/**/*.styl'
]
.pipe if argv.sourcemaps then require('gulp-sourcemaps').init() else gutil.noop()
.pipe require('gulp-concat') 'styles.styl'
.pipe require('gulp-stylus')
use: require('nib')()
.pipe if isLocal() then gutil.noop() else require('gulp-minify-css')
compatibility: '' # Empty string is IE9+ (this is default)
.pipe if argv.sourcemaps then require('gulp-sourcemaps').write() else gutil.noop()
.pipe gulp.dest './dist/css' |
I've never heard about chaining being "supposed" to be in any particular way. All CoffeeScript I've ever written has used indented chaining (because that's what I'm used to from JavaScript). I don't think anyone knows the exact rules. What makes things harder is that the compiler has always been a little too permissive and since CoffeeScript has been around for so long now, it's hard to tell intended behavior from accidental. CoffeeScriptRedux tried to define sane rules for stuff like this, but people have come to depend on accidental quirks (which is one reason people sadly had problems adopting CSR). |
Chaining like this was not supposed to be supported in the first place. Originally, a leading But that got changed when the PR got merged years ago. |
Well that’s what happens when we don’t document a feature 😄 Its only documentation is in the changelog for 1.7.0: http://coffeescript.org/v2/#1.7.0, and there it’s unindented. I had always assumed the unindentation was intentional, since indentation implies a new block, and chaining most emphatically is not a new block—it’s really a single line of code. But clearly the compiler allows either. We could fix this as part of the breaking changes for 2, but I don’t think we really gain anything other than intellectual cohesiveness, at the expense of lots of people needing to revise their code for no real reason. |
But would it help in the context of this thread? Could it make it clear to the compiler what my intended meaning was? See the "I was expecting" list from my original post. I am increasingly getting the impression that this indentation conversation is actually not relevant to the bug(?) I was pointing out. I think the real issue is that there's something awry when a ternary and object argument are given as part of chains. The dot at the start of the line is supposed to close all preceding function calls, and in this case this is not happening. |
Related: #3866. |
Here’s a minimal example: a
.b if yes then 1 else c
d: 1
.e() a.b(true ? 1 : c({
d: 1
}).e()); should compile to: a.b(true ? 1 : c({
d: 1
})).e(); |
This is a bug, and should work regardless of indentation (I would prefer to enforce that the chain call be indented, but I guess a lot of ppl don't indent, including @GeoffreyBooth ). As the documentation says:
And clearly I would guess that #3866 is a separate issue. |
@xixixao When the feature was introduced, its only documentation was in the changelog (for 1.7.0) and that example didn’t indent. I assumed therefore that that was the only possible syntax, and that indentation would be invalid (as indentation implies a new block, but chaining is really a continuation of the previous line, certainly not a new block). At this point we’re stuck supporting both variants, since there’s a lot of code out there that uses one or the other style; but based on the documentation and the general meaning of indentation, the non-indented style should be the only accepted variant; or at least the default variant for purposes of documentation and testing. |
@GeoffreyBooth Yeah, I have no clue why I didn't indent that example (I have a hunch I took it over from somewhere, but I might be completely wrong). Maybe I'm skewed by over a year of writing in ES6, but I would definitely encourage everyone to indent the method calls (i.e. we should change that example). |
Again, we’re stuck supporting both styles now. But I think the example in the docs should stay as it is (and move into the regular documentation, not just in the changelog). Indentation in CoffeeScript represents a new block; indenting something and not having a new block form generally should throw an I understand that the indented style looks better, and that’s why it’s popular in JavaScript; but we have significant indentations here. |
1.7.0 added "Leading . now closes all open calls, allowing for simpler chaining syntax."
This is great, but I may have just stumbled on a bug with that when using the ternary operator and an object argument.
This is coming out as
I was expecting
compatibility: ''
object to be an argument torequire('gulp-minify-css')
-- in this case the result is as expected.pipe()
from the preceding line -- in this case the result is not as expected: the next.pipe()
is chained on the end of thegulp-minify-css
object.Note that the
gulp-stylus
pipe above also receives an object as an argument but does not have a ternary. This one compiles as I expect.Note also that the
gulp-sourcemaps
pipes have ternaries but no object argument, and these ones also compile as I expect.So it seems it's a combination of the tenary and the object argument on a new line.
Is this a bug or am I understanding something incorrectly?
The text was updated successfully, but these errors were encountered: