Skip to content

Commit

Permalink
[JavaScript] Various syntax improvements
Browse files Browse the repository at this point in the history
 - Added a syntax test
 - Remove string.unquoted from object keys
 - Remove constant.other.object.key.js from object key and :
 - Fix : after case in switch to not have keyword.operator.ternary.js
 - Implement support for class method to have a { on next line
 - Variables starting with $ get variable.other.dollar
 - Object keys starting with $ get meta.object-literal.key.dollar
 - Object keys not start with $ get meta.object-literal.key
 - $ at beginning of variable or object key get puntuation.dollar
 - Fix various string patterns to properly handle \ escapes
 - Removed keyword.other.jquery.js in favor of various "dollar" scopes
  • Loading branch information
wbond committed Feb 12, 2016
1 parent 11d919f commit 10073d7
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 26 deletions.
89 changes: 63 additions & 26 deletions JavaScript/JavaScript.sublime-syntax
Expand Up @@ -271,8 +271,8 @@ contexts:
- match: |-
(?x)
(?:
((')((?:[^']|\\')*)('))|
((")((?:[^"]|\\")*)("))
((')((?:[^'\\]+|\\.)*)('))|
((")((?:[^"\\]+|\\.)*)("))
)
\s*(:)
\s*(async)?
Expand All @@ -298,8 +298,8 @@ contexts:
- match: |-
(?x)
(?:
((')((?:[^']|\\')*)('))|
((")((?:[^"]|\\")*)("))
((')((?:[^'\\]+|\\.)*)('))|
((")((?:[^"\\]+|\\.)*)("))
)
\s*(:)
\s*(async)?
Expand Down Expand Up @@ -350,6 +350,17 @@ contexts:
- include: brackets
- include: comments
- include: literal-method
- match: '(?:(?:(static|async)|(get|set))\s+)?(?:\s*(\*)\s*)?([$_a-zA-Z][$\w]*)(?=\()'
captures:
1: storage.type.js
2: storage.type.accessor
3: keyword.generator.asterisk.js
4: entity.name.function.method.js
push:
- meta_scope: meta.method.js
- match: (?<=\))
pop: true
- include: function-declaration-parameters
literal-constructor:
- match: '(new)\s+(?=[_$a-zA-Z][$\w.]*)'
captures:
Expand Down Expand Up @@ -462,6 +473,13 @@ contexts:
pop: true
- include: function-declaration-parameters
literal-function-call:
- match: |-
(?x)
((?<![\w$])\$)\s*
(?=\()
scope: meta.function-call.with-arguments.js
captures:
1: variable.function.js variable.other.dollar.only.js punctuation.dollar.js
- match: |-
(?x)
([_$a-zA-Z][$\w]*)\s*
Expand Down Expand Up @@ -500,8 +518,8 @@ contexts:
- match: |-
(?x)
(?:
((')((?:[^']|\\')*)('))|
((")((?:[^"]|\\")*)("))
((')((?:[^'\\]+|\\.)*)('))|
((")((?:[^"\\]+|\\.)*)("))
)
\s*(:)
\s*(?:(async)\s+)?
Expand Down Expand Up @@ -544,22 +562,14 @@ contexts:
- match: (?<!\.)\b(break|continue|do|goto|while)\b
scope: keyword.control.loop.js
literal-labels:
- match: |-
(?x)
(?<!\?)(?<!\?\s)(?=(
((')((?:[^']|\\')*)('))|
((")((?:[^"]|\\")*)("))
)\s*:)
push:
- match: ":"
captures:
0: punctuation.separator.key-value.js
pop: true
- include: literal-string
- match: '(?<!\.|\?|\?\s)((\$)[$\w]*)\s*(:)'
captures:
1: meta.object-literal.key.dollar
2: punctuation.dollar
3: punctuation.separator.key-value.js
- match: '(?<!\.|\?|\?\s)([_$a-zA-Z][$\w]*)\s*(:)'
scope: constant.other.object.key.js
captures:
1: string.unquoted.label.js
1: meta.object-literal.key
2: punctuation.separator.key-value.js
literal-language-constant:
- match: (?<!\.)\btrue\b
Expand Down Expand Up @@ -820,7 +830,7 @@ contexts:
captures:
1: punctuation.definition.string.end.js
2: invalid.illegal.newline.js
pop: true
set: literal-string-key
- include: string-content
- match: '"'
captures:
Expand All @@ -831,8 +841,13 @@ contexts:
captures:
1: punctuation.definition.string.end.js
2: invalid.illegal.newline.js
pop: true
set: literal-string-key
- include: string-content
literal-string-key:
- match: (?!:)
pop: true
- match: ':'
scope: punctuation.separator.key-value.js
literal-switch:
- match: (?<!\.)\b(switch)\b
captures:
Expand All @@ -854,14 +869,38 @@ contexts:
captures:
1: keyword.control.switch.js
push:
- match: (?=:)
- match: ':'
pop: true
- match: "'"
captures:
0: punctuation.definition.string.begin.js
push:
- meta_scope: string.quoted.single.js
- match: (')|(\n)
captures:
1: punctuation.definition.string.end.js
2: invalid.illegal.newline.js
pop: true
- include: string-content
- match: '"'
captures:
0: punctuation.definition.string.begin.js
push:
- meta_scope: string.quoted.double.js
- match: (")|(\n)
captures:
1: punctuation.definition.string.end.js
2: invalid.illegal.newline.js
pop: true
- include: string-content
- include: expression
- include: main
literal-variable:
- match: '[A-Z][_$\dA-Z]*\b'
scope: variable.other.constant.js
- match: '(\$)[$\w]+'
- match: \$(?=(\(|\.)|\s)
scope: variable.other.dollar.only.js punctuation.dollar.js
- match: '(\$)[$\w]*'
scope: variable.other.dollar.js
captures:
1: punctuation.dollar.js
Expand Down Expand Up @@ -946,8 +985,6 @@ contexts:
scope: support.class.error.js
- match: (?<!\.)\b(debugger)\b
scope: keyword.other.js
- match: \$(?=(\(|\.))
scope: keyword.other.jquery.js
- match: (?<!\.)\b(document|window)\b
scope: support.type.object.dom.js
- match: (?<=\.)(s(hape|ystemId|c(heme|ope|rolling)|ta(ndby|rt)|ize|ummary|pecified|e(ctionRowIndex|lected(Index)?)|rc)|h(space|t(tpEquiv|mlFor)|e(ight|aders)|ref(lang)?)|n(o(Resize|tation(s|Name)|Shade|Href|de(Name|Type|Value)|Wrap)|extSibling|ame)|c(h(ildNodes|Off|ecked|arset)?|ite|o(ntent|o(kie|rds)|de(Base|Type)?|l(s|Span|or)|mpact)|ell(s|Spacing|Padding)|l(ear|assName)|aption)|t(ype|Bodies|itle|Head|ext|a(rget|gName)|Foot)|i(sMap|ndex|d|m(plementation|ages))|o(ptions|wnerDocument|bject)|d(i(sabled|r)|o(c(type|umentElement)|main)|e(clare|f(er|ault(Selected|Checked|Value)))|at(eTime|a))|useMap|p(ublicId|arentNode|r(o(file|mpt)|eviousSibling))|e(n(ctype|tities)|vent|lements)|v(space|ersion|alue(Type)?|Link|Align)|URL|f(irstChild|orm(s)?|ace|rame(Border)?)|width|l(ink(s)?|o(ngDesc|wSrc)|a(stChild|ng|bel))|a(nchors|c(ce(ssKey|pt(Charset)?)|tion)|ttributes|pplets|l(t|ign)|r(chive|eas)|xis|Link|bbr)|r(ow(s|Span|Index)|ules|e(v|ferrer|l|adOnly))|m(ultiple|e(thod|dia)|a(rgin(Height|Width)|xLength))|b(o(dy|rder)|ackground|gColor))\b
Expand Down
161 changes: 161 additions & 0 deletions JavaScript/syntax_test_js.js
@@ -0,0 +1,161 @@
// SYNTAX TEST "Packages/JavaScript/JavaScript.sublime-syntax"

import TheirClass from "./mypath";

function foo() {
// ^ storage.type.function
// ^ entity.name.function
}

var bar = function() {
// <- storage.type
// ^ entity.name.function
// ^ storage.type.function
}

baz = function*()
// <- entity.name.function
// ^ storage.type.function
// ^ keyword.generator.asterisk
{

}

if (true)
// <- keyword.control.conditional
{
bar()
}

var str = '\':';
var str2 = 0;
// <- storage.type
// ^ variable.other.readwrite
// ^ keyword.operator.assignment

var obj = {
key: bar,
// <- meta.object-literal.key
$key2: "string value",
// ^ meta.object-literal.key
// ^ - constant.other
// ^ string.quoted.double
$key3: 0
// <- meta.object-literal.key.dollar punctuation.dollar
// <- meta.object-literal.key.dollar - punctuation.dollar
"key4": true
// <- string.quoted.double
// ^ punctuation.separator.key-value - string
'key5': true
// <- string.quoted.single
// ^ punctuation.separator.key-value - string

static foo(bar) {
// ^ storage.type
// ^entity.name.function
}

*baz(){
// <- keyword.generator.asterisk
// ^ entity.name.function
}
}

var $ = function(baz) {
// ^ variable.other.dollar.only punctuation.dollar
}

$()
// <- variable.other.dollar.only punctuation.dollar

$foo = null;
// <- variable.other.dollar punctuation.dollar
// ^ variable.other.dollar - punctuation.dollar


baz = "";
// <- variable.other.readwrite
// ^ string.quoted.double

var qux = 100;
// <- storage.type
// ^ variable.other.readwrite
// ^ constant.numeric

if (100.0 > qux) {

}

switch ($foo) {
case foo:
// ^ keyword.control.switch
// ^ - punctuation.separator.key-value
qux = 1;
break;
// ^ keyword.control.loop
case "baz":
// ^ keyword.control.switch
// ^ - punctuation.separator.key-value string
qux = 2;
break;
// ^ keyword.control.loop
default:
// ^ keyword.control.switch
// ^ - punctuation.separator.key-value
qux = 3;
}

class MyClass extends TheirClass {
constructor(el)
// ^ entity.name.function
{
$.foo = "";
super(el);
}

get foo()
// <- storage.type.accessor
// ^ entity.name.function
{
return this._foo;
}

static foo(baz) {
// ^ storage.type
// ^ entity.name.function

}

qux()
{ }

get bar () {
// <- storage.type.accessor
// ^ entity.name.function
return false;
}

baz() { return null }
// <- entity.name.function
}

MyClass.foo = function() {}
// ^ support.class
// ^ entity.name.function

var simpleArrow = foo => bar
// ^ entity.name.function
// ^ variable.parameter.function
// ^ storage.type.function.arrow

var Proto = () => {
// ^ entity.name.function
// ^ storage.type.function.arrow
this._var = 1;
}

Proto.prototype.getVar = () => this._var
// ^ entity.name.class
// ^ support.constant.prototype
// ^ entity.name.function
// ^ storage.type.function.arrow

3 comments on commit 10073d7

@FichteFoll
Copy link
Collaborator

Choose a reason for hiding this comment

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

I suggest matching the escape sequences (at least the ones that you modified) as constant.character.escape.

@wbond
Copy link
Member Author

@wbond wbond commented on 10073d7 Feb 12, 2016

Choose a reason for hiding this comment

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

There will need to be more refactoring to support that, I imagine. You can open an issue if you'd like to see that happen. I won't remember every issue mentioned In a comment.

@FichteFoll
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, I might as well.

Please sign in to comment.