jsduck 4.0.1 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. data/Rakefile +14 -0
  2. data/esprima/esprima.js +210 -85
  3. data/jsduck.gemspec +3 -3
  4. data/lib/jsduck/accessors.rb +10 -8
  5. data/lib/jsduck/aggregator.rb +7 -7
  6. data/lib/jsduck/app.rb +24 -164
  7. data/lib/jsduck/app_data.rb +2 -4
  8. data/lib/jsduck/assets.rb +5 -2
  9. data/lib/jsduck/ast.rb +9 -4
  10. data/lib/jsduck/batch_formatter.rb +54 -0
  11. data/lib/jsduck/batch_parser.rb +106 -0
  12. data/lib/jsduck/categories.rb +5 -6
  13. data/lib/jsduck/class.rb +77 -239
  14. data/lib/jsduck/class_doc_expander.rb +0 -5
  15. data/lib/jsduck/class_formatter.rb +14 -10
  16. data/lib/jsduck/class_name.rb +23 -0
  17. data/lib/jsduck/class_writer.rb +9 -8
  18. data/lib/jsduck/doc_ast.rb +5 -6
  19. data/lib/jsduck/doc_formatter.rb +61 -272
  20. data/lib/jsduck/enum.rb +4 -4
  21. data/lib/jsduck/esprima.rb +10 -4
  22. data/lib/jsduck/examples.rb +5 -5
  23. data/lib/jsduck/export_writer.rb +62 -0
  24. data/lib/jsduck/exporter/app.rb +62 -0
  25. data/lib/jsduck/exporter/examples.rb +58 -0
  26. data/lib/jsduck/exporter/full.rb +60 -0
  27. data/lib/jsduck/file_categories.rb +7 -4
  28. data/lib/jsduck/function_ast.rb +99 -0
  29. data/lib/jsduck/grouped_asset.rb +27 -16
  30. data/lib/jsduck/guide_writer.rb +8 -7
  31. data/lib/jsduck/guides.rb +31 -29
  32. data/lib/jsduck/icons.rb +12 -1
  33. data/lib/jsduck/images.rb +3 -3
  34. data/lib/jsduck/importer.rb +7 -7
  35. data/lib/jsduck/index_html.rb +20 -6
  36. data/lib/jsduck/inherit_doc.rb +9 -12
  37. data/lib/jsduck/inline/example.rb +42 -0
  38. data/lib/jsduck/inline/img.rb +55 -0
  39. data/lib/jsduck/inline/link.rb +227 -0
  40. data/lib/jsduck/inline/video.rb +67 -0
  41. data/lib/jsduck/inline_examples.rb +7 -7
  42. data/lib/jsduck/js_parser.rb +5 -4
  43. data/lib/jsduck/lint.rb +14 -2
  44. data/lib/jsduck/logger.rb +5 -6
  45. data/lib/jsduck/members_index.rb +132 -0
  46. data/lib/jsduck/merger.rb +3 -9
  47. data/lib/jsduck/options.rb +39 -41
  48. data/lib/jsduck/override.rb +3 -7
  49. data/lib/jsduck/relations.rb +9 -9
  50. data/lib/jsduck/renderer.rb +3 -3
  51. data/lib/jsduck/return_values.rb +72 -0
  52. data/lib/jsduck/search_data.rb +16 -20
  53. data/lib/jsduck/shortener.rb +58 -0
  54. data/lib/jsduck/signature_renderer.rb +1 -2
  55. data/lib/jsduck/source/file.rb +98 -0
  56. data/lib/jsduck/source/file_parser.rb +72 -0
  57. data/lib/jsduck/source/writer.rb +89 -0
  58. data/lib/jsduck/tag/aside.rb +1 -1
  59. data/lib/jsduck/tag/since.rb +1 -1
  60. data/lib/jsduck/template_dir.rb +2 -2
  61. data/lib/jsduck/util/html.rb +27 -0
  62. data/lib/jsduck/util/io.rb +32 -0
  63. data/lib/jsduck/util/json.rb +60 -0
  64. data/lib/jsduck/util/null_object.rb +23 -0
  65. data/lib/jsduck/util/os.rb +14 -0
  66. data/lib/jsduck/util/parallel.rb +34 -0
  67. data/lib/jsduck/util/singleton.rb +35 -0
  68. data/lib/jsduck/util/stdout.rb +33 -0
  69. data/lib/jsduck/videos.rb +5 -5
  70. data/lib/jsduck/web_writer.rb +79 -0
  71. data/lib/jsduck/welcome.rb +6 -6
  72. data/spec/class_factory.rb +20 -0
  73. metadata +32 -20
  74. data/lib/jsduck/api_exporter.rb +0 -48
  75. data/lib/jsduck/app_exporter.rb +0 -60
  76. data/lib/jsduck/examples_exporter.rb +0 -56
  77. data/lib/jsduck/full_exporter.rb +0 -35
  78. data/lib/jsduck/html.rb +0 -25
  79. data/lib/jsduck/inline_img.rb +0 -53
  80. data/lib/jsduck/inline_video.rb +0 -58
  81. data/lib/jsduck/io.rb +0 -30
  82. data/lib/jsduck/json_duck.rb +0 -52
  83. data/lib/jsduck/lexer.rb +0 -251
  84. data/lib/jsduck/null_object.rb +0 -19
  85. data/lib/jsduck/os.rb +0 -11
  86. data/lib/jsduck/parallel_wrap.rb +0 -32
  87. data/lib/jsduck/source_file.rb +0 -97
  88. data/lib/jsduck/source_file_parser.rb +0 -70
  89. data/lib/jsduck/source_writer.rb +0 -87
  90. data/lib/jsduck/stats.rb +0 -103
  91. data/lib/jsduck/stdout.rb +0 -31
data/Rakefile CHANGED
@@ -14,6 +14,20 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
14
14
  spec.pattern = "spec/**/*_spec.rb"
15
15
  end
16
16
 
17
+ desc "Run Jasmine specs for comments backend"
18
+ task :jasmine do
19
+ # Initialize database with test data
20
+ test_db = "comments_test"
21
+ system("echo 'DROP DATABASE IF EXISTS #{test_db};' | mysql")
22
+ system("echo 'CREATE DATABASE #{test_db};' | mysql")
23
+ system("mysql #{test_db} < comments/sql/schema.sql")
24
+ system("mysql #{test_db} < comments/sql/test_data.sql")
25
+ system("mysql #{test_db} < comments/sql/update_votes.sql")
26
+
27
+ # run jasmine tests against that database
28
+ system("node comments/node_modules/jasmine-node/lib/jasmine-node/cli.js comments/spec/")
29
+ end
30
+
17
31
  def load_sdk_vars
18
32
  if File.exists?("sdk-vars.rb")
19
33
  require "./sdk-vars.rb"
@@ -29,7 +29,7 @@
29
29
  */
30
30
 
31
31
  /*jslint bitwise:true plusplus:true */
32
- /*global esprima:true, exports:true,
32
+ /*global esprima:true, define:true, exports:true, window: true,
33
33
  throwError: true, createLiteral: true, generateStatement: true,
34
34
  parseAssignmentExpression: true, parseBlock: true, parseExpression: true,
35
35
  parseFunctionDeclaration: true, parseFunctionExpression: true,
@@ -37,7 +37,19 @@ parseFunctionSourceElements: true, parseVariableIdentifier: true,
37
37
  parseLeftHandSideExpression: true,
38
38
  parseStatement: true, parseSourceElement: true */
39
39
 
40
- (function (exports) {
40
+ (function (factory) {
41
+ 'use strict';
42
+
43
+ // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
44
+ // and plain browser loading,
45
+ if (typeof define === 'function' && define.amd) {
46
+ define(['exports'], factory);
47
+ } else if (typeof exports !== 'undefined') {
48
+ factory(exports);
49
+ } else {
50
+ factory((window.esprima = {}));
51
+ }
52
+ }(function (exports) {
41
53
  'use strict';
42
54
 
43
55
  var Token,
@@ -139,6 +151,7 @@ parseStatement: true, parseSourceElement: true */
139
151
  UnterminatedRegExp: 'Invalid regular expression: missing /',
140
152
  InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
141
153
  InvalidLHSInForIn: 'Invalid left-hand side in for-in',
154
+ MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
142
155
  NoCatchOrFinally: 'Missing catch or finally after try',
143
156
  UnknownLabel: 'Undefined label \'%0\'',
144
157
  Redeclaration: '%0 \'%1\' has already been declared',
@@ -948,7 +961,7 @@ parseStatement: true, parseSourceElement: true */
948
961
  }
949
962
 
950
963
  function scanRegExp() {
951
- var str = '', ch, start, pattern, flags, value, classMarker = false, restore;
964
+ var str = '', ch, start, pattern, flags, value, classMarker = false, restore, terminated = false;
952
965
 
953
966
  buffer = null;
954
967
  skipComment();
@@ -973,20 +986,18 @@ parseStatement: true, parseSourceElement: true */
973
986
  throwError({}, Messages.UnterminatedRegExp);
974
987
  }
975
988
  str += ch;
976
- }
977
- else if (ch === '/') {
989
+ } else if (ch === '/') {
990
+ terminated = true;
978
991
  break;
979
- }
980
- else if (ch === '[') {
992
+ } else if (ch === '[') {
981
993
  classMarker = true;
982
- }
983
- else if (isLineTerminator(ch)) {
994
+ } else if (isLineTerminator(ch)) {
984
995
  throwError({}, Messages.UnterminatedRegExp);
985
996
  }
986
997
  }
987
998
  }
988
999
 
989
- if (str.length === 1) {
1000
+ if (!terminated) {
990
1001
  throwError({}, Messages.UnterminatedRegExp);
991
1002
  }
992
1003
 
@@ -1163,7 +1174,6 @@ parseStatement: true, parseSourceElement: true */
1163
1174
  }
1164
1175
 
1165
1176
  function throwErrorTolerant() {
1166
- var error;
1167
1177
  try {
1168
1178
  throwError.apply(null, arguments);
1169
1179
  } catch (e) {
@@ -1179,8 +1189,6 @@ parseStatement: true, parseSourceElement: true */
1179
1189
  // Throw an exception because of the token.
1180
1190
 
1181
1191
  function throwUnexpected(token) {
1182
- var s;
1183
-
1184
1192
  if (token.type === Token.EOF) {
1185
1193
  throwError(token, Messages.UnexpectedEOS);
1186
1194
  }
@@ -1297,31 +1305,20 @@ parseStatement: true, parseSourceElement: true */
1297
1305
  // Return true if provided expression is LeftHandSideExpression
1298
1306
 
1299
1307
  function isLeftHandSide(expr) {
1300
- switch (expr.type) {
1301
- case 'AssignmentExpression':
1302
- case 'BinaryExpression':
1303
- case 'ConditionalExpression':
1304
- case 'LogicalExpression':
1305
- case 'SequenceExpression':
1306
- case 'UnaryExpression':
1307
- case 'UpdateExpression':
1308
- return false;
1309
- }
1310
- return true;
1308
+ return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
1311
1309
  }
1312
1310
 
1313
1311
  // 11.1.4 Array Initialiser
1314
1312
 
1315
1313
  function parseArrayInitialiser() {
1316
- var elements = [],
1317
- undef;
1314
+ var elements = [];
1318
1315
 
1319
1316
  expect('[');
1320
1317
 
1321
1318
  while (!match(']')) {
1322
1319
  if (match(',')) {
1323
1320
  lex();
1324
- elements.push(undef);
1321
+ elements.push(null);
1325
1322
  } else {
1326
1323
  elements.push(parseAssignmentExpression());
1327
1324
 
@@ -1355,7 +1352,11 @@ parseStatement: true, parseSourceElement: true */
1355
1352
  type: Syntax.FunctionExpression,
1356
1353
  id: null,
1357
1354
  params: param,
1358
- body: body
1355
+ defaults: [],
1356
+ body: body,
1357
+ rest: null,
1358
+ generator: false,
1359
+ expression: false
1359
1360
  };
1360
1361
  }
1361
1362
 
@@ -1438,7 +1439,7 @@ parseStatement: true, parseSourceElement: true */
1438
1439
  }
1439
1440
 
1440
1441
  function parseObjectInitialiser() {
1441
- var token, properties = [], property, name, kind, map = {}, toString = String;
1442
+ var properties = [], property, name, kind, map = {}, toString = String;
1442
1443
 
1443
1444
  expect('{');
1444
1445
 
@@ -1690,6 +1691,11 @@ parseStatement: true, parseSourceElement: true */
1690
1691
  if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
1691
1692
  throwError({}, Messages.StrictLHSPostfix);
1692
1693
  }
1694
+
1695
+ if (!isLeftHandSide(expr)) {
1696
+ throwError({}, Messages.InvalidLHSInAssignment);
1697
+ }
1698
+
1693
1699
  expr = {
1694
1700
  type: Syntax.UpdateExpression,
1695
1701
  operator: lex().value,
@@ -1713,6 +1719,11 @@ parseStatement: true, parseSourceElement: true */
1713
1719
  if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
1714
1720
  throwError({}, Messages.StrictLHSPrefix);
1715
1721
  }
1722
+
1723
+ if (!isLeftHandSide(expr)) {
1724
+ throwError({}, Messages.InvalidLHSInAssignment);
1725
+ }
1726
+
1716
1727
  expr = {
1717
1728
  type: Syntax.UpdateExpression,
1718
1729
  operator: token.value,
@@ -1803,34 +1814,19 @@ parseStatement: true, parseSourceElement: true */
1803
1814
 
1804
1815
  previousAllowIn = state.allowIn;
1805
1816
  state.allowIn = true;
1817
+
1806
1818
  expr = parseShiftExpression();
1807
- state.allowIn = previousAllowIn;
1808
1819
 
1809
- if (match('<') || match('>') || match('<=') || match('>=')) {
1820
+ while (match('<') || match('>') || match('<=') || match('>=') || (previousAllowIn && matchKeyword('in')) || matchKeyword('instanceof')) {
1810
1821
  expr = {
1811
1822
  type: Syntax.BinaryExpression,
1812
1823
  operator: lex().value,
1813
1824
  left: expr,
1814
- right: parseRelationalExpression()
1815
- };
1816
- } else if (state.allowIn && matchKeyword('in')) {
1817
- lex();
1818
- expr = {
1819
- type: Syntax.BinaryExpression,
1820
- operator: 'in',
1821
- left: expr,
1822
- right: parseRelationalExpression()
1823
- };
1824
- } else if (matchKeyword('instanceof')) {
1825
- lex();
1826
- expr = {
1827
- type: Syntax.BinaryExpression,
1828
- operator: 'instanceof',
1829
- left: expr,
1830
- right: parseRelationalExpression()
1825
+ right: parseShiftExpression()
1831
1826
  };
1832
1827
  }
1833
1828
 
1829
+ state.allowIn = previousAllowIn;
1834
1830
  return expr;
1835
1831
  }
1836
1832
 
@@ -1869,14 +1865,14 @@ parseStatement: true, parseSourceElement: true */
1869
1865
  return expr;
1870
1866
  }
1871
1867
 
1872
- function parseBitwiseORExpression() {
1868
+ function parseBitwiseXORExpression() {
1873
1869
  var expr = parseBitwiseANDExpression();
1874
1870
 
1875
- while (match('|')) {
1871
+ while (match('^')) {
1876
1872
  lex();
1877
1873
  expr = {
1878
1874
  type: Syntax.BinaryExpression,
1879
- operator: '|',
1875
+ operator: '^',
1880
1876
  left: expr,
1881
1877
  right: parseBitwiseANDExpression()
1882
1878
  };
@@ -1885,16 +1881,16 @@ parseStatement: true, parseSourceElement: true */
1885
1881
  return expr;
1886
1882
  }
1887
1883
 
1888
- function parseBitwiseXORExpression() {
1889
- var expr = parseBitwiseORExpression();
1884
+ function parseBitwiseORExpression() {
1885
+ var expr = parseBitwiseXORExpression();
1890
1886
 
1891
- while (match('^')) {
1887
+ while (match('|')) {
1892
1888
  lex();
1893
1889
  expr = {
1894
1890
  type: Syntax.BinaryExpression,
1895
- operator: '^',
1891
+ operator: '|',
1896
1892
  left: expr,
1897
- right: parseBitwiseORExpression()
1893
+ right: parseBitwiseXORExpression()
1898
1894
  };
1899
1895
  }
1900
1896
 
@@ -1904,7 +1900,7 @@ parseStatement: true, parseSourceElement: true */
1904
1900
  // 11.11 Binary Logical Operators
1905
1901
 
1906
1902
  function parseLogicalANDExpression() {
1907
- var expr = parseBitwiseXORExpression();
1903
+ var expr = parseBitwiseORExpression();
1908
1904
 
1909
1905
  while (match('&&')) {
1910
1906
  lex();
@@ -1912,7 +1908,7 @@ parseStatement: true, parseSourceElement: true */
1912
1908
  type: Syntax.LogicalExpression,
1913
1909
  operator: '&&',
1914
1910
  left: expr,
1915
- right: parseBitwiseXORExpression()
1911
+ right: parseBitwiseORExpression()
1916
1912
  };
1917
1913
  }
1918
1914
 
@@ -1970,7 +1966,7 @@ parseStatement: true, parseSourceElement: true */
1970
1966
 
1971
1967
  if (matchAssign()) {
1972
1968
  // LeftHandSideExpression
1973
- if (state.lastParenthesized !== expr && !isLeftHandSide(expr)) {
1969
+ if (!isLeftHandSide(expr)) {
1974
1970
  throwError({}, Messages.InvalidLHSInAssignment);
1975
1971
  }
1976
1972
 
@@ -2288,9 +2284,10 @@ parseStatement: true, parseSourceElement: true */
2288
2284
 
2289
2285
  if (matchKeyword('in')) {
2290
2286
  // LeftHandSideExpression
2291
- if (matchKeyword('in') && (state.lastParenthesized !== init && !isLeftHandSide(init))) {
2287
+ if (!isLeftHandSide(init)) {
2292
2288
  throwError({}, Messages.InvalidLHSInForIn);
2293
2289
  }
2290
+
2294
2291
  lex();
2295
2292
  left = init;
2296
2293
  right = parseExpression();
@@ -2555,7 +2552,7 @@ parseStatement: true, parseSourceElement: true */
2555
2552
  }
2556
2553
 
2557
2554
  function parseSwitchStatement() {
2558
- var discriminant, cases, oldInSwitch;
2555
+ var discriminant, cases, clause, oldInSwitch, defaultFound;
2559
2556
 
2560
2557
  expectKeyword('switch');
2561
2558
 
@@ -2579,12 +2576,20 @@ parseStatement: true, parseSourceElement: true */
2579
2576
 
2580
2577
  oldInSwitch = state.inSwitch;
2581
2578
  state.inSwitch = true;
2579
+ defaultFound = false;
2582
2580
 
2583
2581
  while (index < length) {
2584
2582
  if (match('}')) {
2585
2583
  break;
2586
2584
  }
2587
- cases.push(parseSwitchCase());
2585
+ clause = parseSwitchCase();
2586
+ if (clause.test === null) {
2587
+ if (defaultFound) {
2588
+ throwError({}, Messages.MultipleDefaultsInSwitch);
2589
+ }
2590
+ defaultFound = true;
2591
+ }
2592
+ cases.push(clause);
2588
2593
  }
2589
2594
 
2590
2595
  state.inSwitch = oldInSwitch;
@@ -2639,7 +2644,6 @@ parseStatement: true, parseSourceElement: true */
2639
2644
  return {
2640
2645
  type: Syntax.CatchClause,
2641
2646
  param: param,
2642
- guard: null,
2643
2647
  body: parseBlock()
2644
2648
  };
2645
2649
  }
@@ -2667,6 +2671,7 @@ parseStatement: true, parseSourceElement: true */
2667
2671
  return {
2668
2672
  type: Syntax.TryStatement,
2669
2673
  block: block,
2674
+ guardedHandlers: [],
2670
2675
  handlers: handlers,
2671
2676
  finalizer: finalizer
2672
2677
  };
@@ -2907,7 +2912,11 @@ parseStatement: true, parseSourceElement: true */
2907
2912
  type: Syntax.FunctionDeclaration,
2908
2913
  id: id,
2909
2914
  params: params,
2910
- body: body
2915
+ defaults: [],
2916
+ body: body,
2917
+ rest: null,
2918
+ generator: false,
2919
+ expression: false
2911
2920
  };
2912
2921
  }
2913
2922
 
@@ -2982,7 +2991,11 @@ parseStatement: true, parseSourceElement: true */
2982
2991
  type: Syntax.FunctionExpression,
2983
2992
  id: id,
2984
2993
  params: params,
2985
- body: body
2994
+ defaults: [],
2995
+ body: body,
2996
+ rest: null,
2997
+ generator: false,
2998
+ expression: false
2986
2999
  };
2987
3000
  }
2988
3001
 
@@ -3059,7 +3072,7 @@ parseStatement: true, parseSourceElement: true */
3059
3072
  // The following functions are needed only when the option to preserve
3060
3073
  // the comments is active.
3061
3074
 
3062
- function addComment(start, end, type, value) {
3075
+ function addComment(type, value, start, end, loc) {
3063
3076
  assert(typeof start === 'number', 'Comment must have valid position');
3064
3077
 
3065
3078
  // Because the way the actual token is scanned, often the comments
@@ -3073,14 +3086,15 @@ parseStatement: true, parseSourceElement: true */
3073
3086
  }
3074
3087
 
3075
3088
  extra.comments.push({
3076
- range: [start, end],
3077
3089
  type: type,
3078
- value: value
3090
+ value: value,
3091
+ range: [start, end],
3092
+ loc: loc
3079
3093
  });
3080
3094
  }
3081
3095
 
3082
3096
  function scanComment() {
3083
- var comment, ch, start, blockComment, lineComment;
3097
+ var comment, ch, loc, start, blockComment, lineComment;
3084
3098
 
3085
3099
  comment = '';
3086
3100
  blockComment = false;
@@ -3091,19 +3105,27 @@ parseStatement: true, parseSourceElement: true */
3091
3105
 
3092
3106
  if (lineComment) {
3093
3107
  ch = nextChar();
3094
- if (index >= length) {
3095
- lineComment = false;
3096
- comment += ch;
3097
- addComment(start, index, 'Line', comment);
3098
- } else if (isLineTerminator(ch)) {
3108
+ if (isLineTerminator(ch)) {
3109
+ loc.end = {
3110
+ line: lineNumber,
3111
+ column: index - lineStart - 1
3112
+ };
3099
3113
  lineComment = false;
3100
- addComment(start, index, 'Line', comment);
3114
+ addComment('Line', comment, start, index - 1, loc);
3101
3115
  if (ch === '\r' && source[index] === '\n') {
3102
3116
  ++index;
3103
3117
  }
3104
3118
  ++lineNumber;
3105
3119
  lineStart = index;
3106
3120
  comment = '';
3121
+ } else if (index >= length) {
3122
+ lineComment = false;
3123
+ comment += ch;
3124
+ loc.end = {
3125
+ line: lineNumber,
3126
+ column: length - lineStart
3127
+ };
3128
+ addComment('Line', comment, start, length, loc);
3107
3129
  } else {
3108
3130
  comment += ch;
3109
3131
  }
@@ -3133,7 +3155,11 @@ parseStatement: true, parseSourceElement: true */
3133
3155
  comment = comment.substr(0, comment.length - 1);
3134
3156
  blockComment = false;
3135
3157
  ++index;
3136
- addComment(start, index, 'Block', comment);
3158
+ loc.end = {
3159
+ line: lineNumber,
3160
+ column: index - lineStart
3161
+ };
3162
+ addComment('Block', comment, start, index, loc);
3137
3163
  comment = '';
3138
3164
  }
3139
3165
  }
@@ -3141,13 +3167,33 @@ parseStatement: true, parseSourceElement: true */
3141
3167
  } else if (ch === '/') {
3142
3168
  ch = source[index + 1];
3143
3169
  if (ch === '/') {
3170
+ loc = {
3171
+ start: {
3172
+ line: lineNumber,
3173
+ column: index - lineStart
3174
+ }
3175
+ };
3144
3176
  start = index;
3145
3177
  index += 2;
3146
3178
  lineComment = true;
3179
+ if (index >= length) {
3180
+ loc.end = {
3181
+ line: lineNumber,
3182
+ column: index - lineStart
3183
+ };
3184
+ lineComment = false;
3185
+ addComment('Line', comment, start, index, loc);
3186
+ }
3147
3187
  } else if (ch === '*') {
3148
3188
  start = index;
3149
3189
  index += 2;
3150
3190
  blockComment = true;
3191
+ loc = {
3192
+ start: {
3193
+ line: lineNumber,
3194
+ column: index - lineStart - 2
3195
+ }
3196
+ };
3151
3197
  if (index >= length) {
3152
3198
  throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
3153
3199
  }
@@ -3169,10 +3215,44 @@ parseStatement: true, parseSourceElement: true */
3169
3215
  }
3170
3216
  }
3171
3217
 
3218
+ function filterCommentLocation() {
3219
+ var i, entry, comment, comments = [];
3220
+
3221
+ for (i = 0; i < extra.comments.length; ++i) {
3222
+ entry = extra.comments[i];
3223
+ comment = {
3224
+ type: entry.type,
3225
+ value: entry.value
3226
+ };
3227
+ if (extra.range) {
3228
+ comment.range = entry.range;
3229
+ }
3230
+ if (extra.loc) {
3231
+ comment.loc = entry.loc;
3232
+ }
3233
+ comments.push(comment);
3234
+ }
3235
+
3236
+ extra.comments = comments;
3237
+ }
3238
+
3172
3239
  function collectToken() {
3173
- var token = extra.advance(),
3174
- range,
3175
- value;
3240
+ var start, loc, token, range, value;
3241
+
3242
+ skipComment();
3243
+ start = index;
3244
+ loc = {
3245
+ start: {
3246
+ line: lineNumber,
3247
+ column: index - lineStart
3248
+ }
3249
+ };
3250
+
3251
+ token = extra.advance();
3252
+ loc.end = {
3253
+ line: lineNumber,
3254
+ column: index - lineStart
3255
+ };
3176
3256
 
3177
3257
  if (token.type !== Token.EOF) {
3178
3258
  range = [token.range[0], token.range[1]];
@@ -3180,7 +3260,8 @@ parseStatement: true, parseSourceElement: true */
3180
3260
  extra.tokens.push({
3181
3261
  type: TokenName[token.type],
3182
3262
  value: value,
3183
- range: range
3263
+ range: range,
3264
+ loc: loc
3184
3265
  });
3185
3266
  }
3186
3267
 
@@ -3188,12 +3269,23 @@ parseStatement: true, parseSourceElement: true */
3188
3269
  }
3189
3270
 
3190
3271
  function collectRegex() {
3191
- var pos, regex, token;
3272
+ var pos, loc, regex, token;
3192
3273
 
3193
3274
  skipComment();
3194
3275
 
3195
3276
  pos = index;
3277
+ loc = {
3278
+ start: {
3279
+ line: lineNumber,
3280
+ column: index - lineStart
3281
+ }
3282
+ };
3283
+
3196
3284
  regex = extra.scanRegExp();
3285
+ loc.end = {
3286
+ line: lineNumber,
3287
+ column: index - lineStart
3288
+ };
3197
3289
 
3198
3290
  // Pop the previous token, which is likely '/' or '/='
3199
3291
  if (extra.tokens.length > 0) {
@@ -3208,12 +3300,34 @@ parseStatement: true, parseSourceElement: true */
3208
3300
  extra.tokens.push({
3209
3301
  type: 'RegularExpression',
3210
3302
  value: regex.literal,
3211
- range: [pos, index]
3303
+ range: [pos, index],
3304
+ loc: loc
3212
3305
  });
3213
3306
 
3214
3307
  return regex;
3215
3308
  }
3216
3309
 
3310
+ function filterTokenLocation() {
3311
+ var i, entry, token, tokens = [];
3312
+
3313
+ for (i = 0; i < extra.tokens.length; ++i) {
3314
+ entry = extra.tokens[i];
3315
+ token = {
3316
+ type: entry.type,
3317
+ value: entry.value
3318
+ };
3319
+ if (extra.range) {
3320
+ token.range = entry.range;
3321
+ }
3322
+ if (extra.loc) {
3323
+ token.loc = entry.loc;
3324
+ }
3325
+ tokens.push(token);
3326
+ }
3327
+
3328
+ extra.tokens = tokens;
3329
+ }
3330
+
3217
3331
  function createLiteral(token) {
3218
3332
  return {
3219
3333
  type: Syntax.Literal,
@@ -3274,12 +3388,12 @@ parseStatement: true, parseSourceElement: true */
3274
3388
  node = parseFunction.apply(null, arguments);
3275
3389
  if (typeof node !== 'undefined') {
3276
3390
 
3277
- if (range) {
3391
+ if (range && typeof node.range === 'undefined') {
3278
3392
  rangeInfo[1] = index;
3279
3393
  node.range = rangeInfo;
3280
3394
  }
3281
3395
 
3282
- if (loc) {
3396
+ if (loc && typeof node.loc === 'undefined') {
3283
3397
  locInfo.end = {
3284
3398
  line: lineNumber,
3285
3399
  column: index - lineStart
@@ -3301,6 +3415,15 @@ parseStatement: true, parseSourceElement: true */
3301
3415
  node.loc.start = node.object.loc.start;
3302
3416
  }
3303
3417
  }
3418
+
3419
+ if (node.type === Syntax.CallExpression) {
3420
+ if (typeof node.callee.range !== 'undefined') {
3421
+ node.range[0] = node.callee.range[0];
3422
+ }
3423
+ if (typeof node.callee.loc !== 'undefined') {
3424
+ node.loc.start = node.callee.loc.start;
3425
+ }
3426
+ }
3304
3427
  return node;
3305
3428
  }
3306
3429
  };
@@ -3533,9 +3656,11 @@ parseStatement: true, parseSourceElement: true */
3533
3656
  try {
3534
3657
  program = parseProgram();
3535
3658
  if (typeof extra.comments !== 'undefined') {
3659
+ filterCommentLocation();
3536
3660
  program.comments = extra.comments;
3537
3661
  }
3538
3662
  if (typeof extra.tokens !== 'undefined') {
3663
+ filterTokenLocation();
3539
3664
  program.tokens = extra.tokens;
3540
3665
  }
3541
3666
  if (typeof extra.errors !== 'undefined') {
@@ -3577,5 +3702,5 @@ parseStatement: true, parseSourceElement: true */
3577
3702
  return types;
3578
3703
  }());
3579
3704
 
3580
- }(typeof exports === 'undefined' ? (esprima = {}) : exports));
3705
+ }));
3581
3706
  /* vim: set sw=4 ts=4 et tw=80 : */