Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Improve functions #312

Merged
merged 22 commits into from
Feb 28, 2016
Merged

Improve functions #312

merged 22 commits into from
Feb 28, 2016

Conversation

MaximSokolov
Copy link
Contributor

obj.foo = function(){}
obj.prototype.foo = bar;
obj.prototype = {}
function* foo(){}

Before:
objsupport.class
*storage.type
fooentity.name.function.js

After:
objvariable.other.object
*storage.modifier.generator
foovariable.other.property

Code for testing

Fixes #303
Fixes #309
Fixes #193
Fixes #223
Fixes #322
Closes #197
Replaces and closes #224

}
]
}
{
'begin': '([a-zA-Z_?$][\\w?$]*)\\s*(=)\\s*(?:(async)(?:\\s+))?(function\\*?)\\s*(\\*?)\\s*([a-zA-Z_?$][\\w?$]*)?\\s*(\\()'
# foo: function()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

#307 (comment):

I don't think this line [function name] is correct, as object-literal functions have to be anonymous.

¯\_(ツ)_/¯

var obj = {foo: function(){}}
console.log(obj.foo); //=> function(){}
obj = {foo: function abc(){}}
console.log(obj.foo); //=> function abc(){}

I rather keep it as is

@50Wliu
Copy link
Contributor

50Wliu commented Jan 29, 2016

@MaximSokolov Do you want this to be reviewed alongside #307?

@MaximSokolov
Copy link
Contributor Author

@50Wliu It's not necessary

@MaximSokolov MaximSokolov changed the title Improve functions [WIP] Improve functions Feb 4, 2016
Recognize function bodies.
Tokenize rest parameter
Tokenize arrow functions with one parameter
Don't scope not built-in objects as 'support'
@MaximSokolov
Copy link
Contributor Author

New approach of functions recognition:

{
  'begin': '(?=...)'
  'end': '...'
  'name': '3'
  'patterns': [
    {
      'begin': '\\G'
      'end': '...'
      'name': '1'
      'patterns': [ ... ]
    }
    {
      'include': '#function_body' # 2 
    }
  ]
}
function foo ( ... ) { ... }
^──────────────────^ |     | - 1
|                    ^─────^ - 2
^──────────────────────────^ - 3

( ... ) => { ... }
^────────^ |     | - 1
|          ^─────^ - 2
^────────────────^ - 3

x => x + x
^──^       - 1, 3

All these regions can be scoped. Not sure what profit of nested function bodies' blocks to autocompletion, syntax highlighting; so I'll keep meta.function for the 1'st region.

'name': 'meta.function.json.js'
# [param|(params)] => [expression|{statements}]
'begin': '(?=(?<![A-Za-z0-9])((\\(([^\\(\\)]*)?\\))|[\\w$]+)\\s*=>)'
'end': '(?!(\\s*{|\\G\\(|\\G[\\w$]+|/\\*))((?=\\s*\\S)|(?<=}))'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The end pattern definitely should be improved:

the_end

@MaximSokolov MaximSokolov changed the title [WIP] Improve functions Improve functions Feb 7, 2016
'name': 'meta.function.prototype.js'
# [async] function [name](params)
# function* name(params) – generator function declaration
'begin': '(?=(?:\\basync\\b\\s*)?\\bfunction\\b)'
Copy link
Contributor

Choose a reason for hiding this comment

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

No need for ?: non-capturing group because we're not capturing anything here anyway.

'name': 'punctuation.definition.parameters.end.js'
'name': 'meta.function.js'
# "foo": function...
'begin': '(?=((\'[^\']*?\')|("[^"]*?"))\\s*:\\s*(\\basync\\b\\s*)?\\bfunction\\b)'
Copy link
Contributor

Choose a reason for hiding this comment

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

So from some testing with other grammars I think the following will also work: ((\'.*?\')|(".*?"))

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Specs fail on

a.push("x" + y + ":function()");
a.push('x' + y + ':function()');

@@ -281,240 +281,283 @@
'name': 'variable.language.js'
}
{
'captures':
Copy link
Contributor

Choose a reason for hiding this comment

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

Why remove this capture?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

support.class -> variable.other.object for Sound as it isn't a built-in class

@50Wliu
Copy link
Contributor

50Wliu commented Feb 9, 2016

function_params doesn't catch this as invalid: function hi(a b) {}. Not a priority for getting this PR merged though.

'patterns': [
{
'include': '#function-params'
'match': '(\\.\\.\\.)([a-zA-Z_$][a-zA-Z_$0-9]*)'
Copy link
Contributor

Choose a reason for hiding this comment

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

Second square-brackets match can be shortened to [\\w$]*

@50Wliu
Copy link
Contributor

50Wliu commented Feb 9, 2016

function_params is also missing (01) => 1 + 2 or function test(1) {}.

@50Wliu
Copy link
Contributor

50Wliu commented Feb 9, 2016

Regression time:

function test()
{ //punctuation.definition.function.body.end.bracket.curly.js
    if(something)
    { // meta.brace.curly.js

    } // punctuation.definition.function.body.end.bracket.curly.js 
} // meta.brace.curly.js

We need to wrap curly bracket matching in a begin/end instead of a | match.

Also, in the case of Git.Repository.open(), should Repository really be tokenized as variable.other.property.js? Seems to me like it's an object just like Git.

@50Wliu
Copy link
Contributor

50Wliu commented Feb 10, 2016

Here's another problem I found: typing the following code (same as the above example) incorrectly marks the if as a function instead of a control keyword. Adding/removing a space to try to get the grammar to realize its mistake doesn't work, but copy/pasting the code elsewhere or reloading the file does.

function test()
{
    if(something)  // entity.name.function.js!!!
    {

    }
}

@MaximSokolov
Copy link
Contributor Author

function_params is also missing (01) => 1 + 2 or function test(1) {}

Numbers cannot be matched as illegal because of default parameters:

function multiply(a, b = 1){}

'patterns': [
{
'include': '#function-params'
'begin': '\\G'
'end': '(?<=\\))'
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@50Wliu any ideas why it's happening?

thimpq3r7n

function()

function(){}

Copy link
Contributor

Choose a reason for hiding this comment

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

Looking into it...what's the highlighted scope that's flickering?

Copy link
Contributor

Choose a reason for hiding this comment

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

Never mind, got it: meta.function.js. Not sure why though. It only seems to happen when there's an odd number of spaces.

Copy link
Contributor

Choose a reason for hiding this comment

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

Moving the function_body include above this match appears to fix it. For safety I would arrange the patterns like this:

  • comments
  • function_body
  • This one

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@MaximSokolov
Copy link
Contributor Author

Added support for:

{
  foo: p => {}
  "foo": p => {}
  'foo': p => {}
}

@50Wliu
Copy link
Contributor

50Wliu commented Feb 27, 2016

Looks good to me - can you just address the two style comments above?
#312 (diff)
and
#312 (diff)

I wasn't able to find any glaring bugs through some testing, so I think this is ready to 🚢 and get some more extensive testing on Atom master :).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.