jsduck 4.0.1 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 : */