OffsetToLocation.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { adoptBuffer } from './adopt-buffer.js';
  2. import { isBOM } from './char-code-definitions.js';
  3. const N = 10;
  4. const F = 12;
  5. const R = 13;
  6. function computeLinesAndColumns(host) {
  7. const source = host.source;
  8. const sourceLength = source.length;
  9. const startOffset = source.length > 0 ? isBOM(source.charCodeAt(0)) : 0;
  10. const lines = adoptBuffer(host.lines, sourceLength);
  11. const columns = adoptBuffer(host.columns, sourceLength);
  12. let line = host.startLine;
  13. let column = host.startColumn;
  14. for (let i = startOffset; i < sourceLength; i++) {
  15. const code = source.charCodeAt(i);
  16. lines[i] = line;
  17. columns[i] = column++;
  18. if (code === N || code === R || code === F) {
  19. if (code === R && i + 1 < sourceLength && source.charCodeAt(i + 1) === N) {
  20. i++;
  21. lines[i] = line;
  22. columns[i] = column;
  23. }
  24. line++;
  25. column = 1;
  26. }
  27. }
  28. lines[sourceLength] = line;
  29. columns[sourceLength] = column;
  30. host.lines = lines;
  31. host.columns = columns;
  32. host.computed = true;
  33. }
  34. export class OffsetToLocation {
  35. constructor(source, startOffset, startLine, startColumn) {
  36. this.setSource(source, startOffset, startLine, startColumn);
  37. this.lines = null;
  38. this.columns = null;
  39. }
  40. setSource(source = '', startOffset = 0, startLine = 1, startColumn = 1) {
  41. this.source = source;
  42. this.startOffset = startOffset;
  43. this.startLine = startLine;
  44. this.startColumn = startColumn;
  45. this.computed = false;
  46. }
  47. getLocation(offset, filename) {
  48. if (!this.computed) {
  49. computeLinesAndColumns(this);
  50. }
  51. return {
  52. source: filename,
  53. offset: this.startOffset + offset,
  54. line: this.lines[offset],
  55. column: this.columns[offset]
  56. };
  57. }
  58. getLocationRange(start, end, filename) {
  59. if (!this.computed) {
  60. computeLinesAndColumns(this);
  61. }
  62. return {
  63. source: filename,
  64. start: {
  65. offset: this.startOffset + start,
  66. line: this.lines[start],
  67. column: this.columns[start]
  68. },
  69. end: {
  70. offset: this.startOffset + end,
  71. line: this.lines[end],
  72. column: this.columns[end]
  73. }
  74. };
  75. }
  76. };