Просмотр исходного кода

Refactor log parser tests

GitOrigin-RevId: 88bf35a04b8f6eca7bd6b4270403c15c53e17406
Eric Mc Sween 4 лет назад
Родитель
Сommit
3fb74c5cd4
1 измененных файлов с 127 добавлено и 336 удалено
  1. 127 336
      services/web/test/frontend/ide/log-parser/logParserTests.js

+ 127 - 336
services/web/test/frontend/ide/log-parser/logParserTests.js

@@ -7,487 +7,280 @@ const fs = require('fs')
 const path = require('path')
 
 describe('logParser', function (done) {
-  before(function () {
-    this.errorLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'errors.log'),
-      {
-        encoding: 'utf8',
-        flag: 'r',
-      }
-    )
-    this.warningLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'warnings.log'),
-      {
-        encoding: 'utf8',
-        flag: 'r',
-      }
-    )
-    this.badBoxesLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'bad-boxes.log'),
-      {
-        encoding: 'utf8',
-        flag: 'r',
-      }
-    )
-    this.biberWarningsLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'biber-warnings.log'),
-      { encoding: 'utf8', flag: 'r' }
-    )
-    this.natbibWarningsLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'natbib-warnings.log'),
-      { encoding: 'utf8', flag: 'r' }
-    )
-    this.geometryWarningsLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'geometry-warnings.log'),
-      { encoding: 'utf8', flag: 'r' }
-    )
-    this.captionWarningsLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'caption-warnings.log'),
-      { encoding: 'utf8', flag: 'r' }
-    )
-    this.runawayArgumentsLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'runaway-arguments.log'),
-      { encoding: 'utf8', flag: 'r' }
-    )
-    this.biberBlg = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'biber.blg'),
-      {
-        encoding: 'utf8',
-        flag: 'r',
-      }
-    )
-    this.bibtexBlg = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'bibtex.blg'),
-      {
-        encoding: 'utf8',
-        flag: 'r',
-      }
-    )
-    this.fileLineErrorLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'file-line-error.log'),
-      {
-        encoding: 'utf8',
-        flag: 'r',
-      }
-    )
-    this.filenamesLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'filenames.log'),
-      {
-        encoding: 'utf8',
-        flag: 'r',
-      }
-    )
-    this.secondaryFileLineErrorLog = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'file-line-error-2.log'),
-      {
-        encoding: 'utf8',
-        flag: 'r',
-      }
-    )
-    this.issue1023Log = fs.readFileSync(
-      path.resolve(__dirname, fixturePath + 'open-source-issue-1023.log'),
-      {
-        encoding: 'utf8',
-        flag: 'r',
-      }
-    )
-  })
-
   it('should parse errors', function () {
-    const latexParser = new LatexLogParser(this.errorLog, {
-      ignoreDuplicates: true,
-    })
-    const errors = latexParser.parse().errors
-
-    const expectedErrors = [
-      [29, 'Undefined control sequence.'] + '',
+    const { errors } = parseLatexLog('errors.log', { ignoreDuplicates: true })
+    expect(errors.map(e => [e.line, e.message])).to.deep.equal([
+      [29, 'Undefined control sequence.'],
       [
         30,
         'LaTeX Error: \\begin{equation} on input line 28 ended by \\end{equaion}.',
-      ] + '',
-      [30, 'Missing $ inserted.'] + '',
-      [30, 'Display math should end with $$.'] + '',
-      [46, 'Extra }, or forgotten \\right.'] + '',
-      [46, 'Missing \\right. inserted.'] + '',
-      [46, 'Missing } inserted.'] + '',
-    ]
-
-    expect(errors.length).to.equal(expectedErrors.length)
-    for (let i = 0; i < errors.length; i++) {
-      expect(
-        expectedErrors.indexOf([errors[i].line, errors[i].message] + '')
-      ).to.equal(i)
-    }
+      ],
+      [30, 'Missing $ inserted.'],
+      [30, 'Display math should end with $$.'],
+      [46, 'Extra }, or forgotten \\right.'],
+      [46, 'Missing \\right. inserted.'],
+      [46, 'Missing } inserted.'],
+    ])
   })
 
   it('should parse Badbox errors', function () {
-    const latexParser = new LatexLogParser(this.badBoxesLog)
-    const errors = latexParser.parse().typesetting
-
-    const expectedErrors = [
-      [9, 'Overfull \\hbox (29.11179pt too wide) in paragraph at lines 9--10'] +
-        '',
-      [11, 'Underfull \\hbox (badness 10000) in paragraph at lines 11--13'] +
-        '',
-      [27, 'Overfull \\vbox (12.00034pt too high) detected at line 27'] + '',
-      [46, 'Underfull \\vbox (badness 10000) detected at line 46'] + '',
-      [54, 'Underfull \\hbox (badness 10000) in paragraph at lines 54--55'] +
-        '',
-      [58, 'Underfull \\hbox (badness 10000) in paragraph at lines 58--60'] +
-        '',
-    ]
-
-    expect(errors.length).to.equal(expectedErrors.length)
-    for (let i = 0; i < errors.length; i++) {
-      expect(
-        expectedErrors.indexOf([errors[i].line, errors[i].message] + '')
-      ).to.equal(i)
-    }
+    const { typesetting } = parseLatexLog('bad-boxes.log')
+    expect(typesetting.map(e => [e.line, e.message])).to.deep.equal([
+      [9, 'Overfull \\hbox (29.11179pt too wide) in paragraph at lines 9--10'],
+      [11, 'Underfull \\hbox (badness 10000) in paragraph at lines 11--13'],
+      [27, 'Overfull \\vbox (12.00034pt too high) detected at line 27'],
+      [46, 'Underfull \\vbox (badness 10000) detected at line 46'],
+      [54, 'Underfull \\hbox (badness 10000) in paragraph at lines 54--55'],
+      [58, 'Underfull \\hbox (badness 10000) in paragraph at lines 58--60'],
+    ])
   })
 
   it('should parse Warnings', function () {
-    const latexParser = new LatexLogParser(this.warningLog)
-    const errors = latexParser.parse().warnings
-
-    const expectedErrors = [
+    const { warnings } = parseLatexLog('warnings.log')
+    expect(warnings.map(e => [e.line, e.message, e.file])).to.deep.equal([
       [
         7,
         "Citation `Lambert:2010iw' on page 1 undefined on input line 7.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/introduction.tex',
-      ] + '',
+      ],
       [
         7,
         "Citation `Lambert:2010iw' on page 1 undefined on input line 7.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/introduction.tex',
-      ] + '',
+      ],
       [
         72,
         "Citation `Manton:2004tk' on page 3 undefined on input line 72.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/instantons.tex',
-      ] + '',
+      ],
       [
         108,
         "Citation `Atiyah1978' on page 4 undefined on input line 108.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/instantons.tex',
-      ] + '',
+      ],
       [
         176,
         "Citation `Dorey:1996hu' on page 5 undefined on input line 176.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/instantons.tex',
-      ] + '',
+      ],
       [
         3,
         "Citation `Manton1982' on page 8 undefined on input line 3.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/moduli_space_approximation.tex',
-      ] + '',
+      ],
       [
         21,
         "Citation `Weinberg:2006rq' on page 9 undefined on input line 21.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/moduli_space_approximation.tex',
-      ] + '',
+      ],
       [
         192,
         "Citation `Bak:1999sv' on page 12 undefined on input line 192.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/moduli_space_approximation.tex',
-      ] + '',
+      ],
       [
         9,
         "Citation `Peeters:2001np' on page 13 undefined on input line 9.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/dynamics_of_single_instanton.tex',
-      ] + '',
+      ],
       [
         27,
         "Citation `Osborn:1981yf' on page 15 undefined on input line 27.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/dynamics_of_two_instantons.tex',
-      ] + '',
+      ],
       [
         27,
         "Citation `Peeters:2001np' on page 15 undefined on input line 27.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/dynamics_of_two_instantons.tex',
-      ] + '',
+      ],
       [
         20,
         "Citation `Osborn:1981yf' on page 22 undefined on input line 20.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/appendices.tex',
-      ] + '',
+      ],
       [
         103,
         "Citation `Osborn:1981yf' on page 23 undefined on input line 103.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/appendices.tex',
-      ] + '',
+      ],
       [
         103,
         "Citation `Peeters:2001np' on page 23 undefined on input line 103.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/appendices.tex',
-      ] + '',
+      ],
       [
         352,
         "Citation `Peeters:2001np' on page 27 undefined on input line 352.",
         'compiles/d1585ce575dea4cab55f784a22a88652/sections/appendices.tex',
-      ] + '',
-    ]
-
-    // there logs display an additional summary error for undefined references
-    const offsetErrorLen = errors.length - 1
-    expect(offsetErrorLen).to.equal(expectedErrors.length)
-
-    for (let i = 0; i < offsetErrorLen; i++) {
-      expect(expectedErrors[i]).to.equal(
-        [errors[i].line, errors[i].message, errors[i].file] + ''
-      )
-    }
+      ],
+      // the logs display an additional summary error for undefined references
+      [
+        null,
+        'There were undefined references.',
+        'compiles/d1585ce575dea4cab55f784a22a88652/instantons.tex',
+      ],
+    ])
   })
 
   it('should parse Biber warnings', function () {
-    const latexParser = new LatexLogParser(this.biberWarningsLog)
-    const errors = latexParser.parse().warnings
-
-    const expectedErrors = [
+    const { warnings } = parseLatexLog('biber-warnings.log')
+    expect(warnings.map(w => [w.line, w.message, w.file])).to.deep.equal([
       [
         null,
         'Package biblatex Warning: No "backend" specified, using Biber backend. To use BibTeX, load biblatex with the "backend=bibtex" option.',
         '/usr/local/texlive/2013/texmf-dist/tex/latex/biblatex/biblatex.sty',
-      ] + '',
+      ],
       [
         null,
         'Package biblatex Warning: The following entry could not be found in the database: Missing3 Please verify the spelling and rerun LaTeX afterwards.',
         '/compile/output.bbl',
-      ] + '',
+      ],
       [
         null,
         'Package biblatex Warning: The following entry could not be found in the database: Missing2 Please verify the spelling and rerun LaTeX afterwards.',
         '/compile/output.bbl',
-      ] + '',
+      ],
       [
         null,
         'Package biblatex Warning: The following entry could not be found in the database: Missing1 Please verify the spelling and rerun LaTeX afterwards.',
         '/compile/output.bbl',
-      ] + '',
-    ]
-
-    expect(errors.length).to.equal(expectedErrors.length)
-    for (let i = 0; i < errors.length; i++) {
-      expect(expectedErrors[i]).to.equal(
-        [errors[i].line, errors[i].message, errors[i].file] + ''
-      )
-    }
+      ],
+    ])
   })
 
   it('should parse Natbib warnings', function () {
-    const latexParser = new LatexLogParser(this.natbibWarningsLog)
-    const errors = latexParser.parse().warnings
-
-    const expectedErrors = [
+    const { warnings } = parseLatexLog('natbib-warnings.log')
+    expect(warnings.map(w => [w.line, w.message, w.file])).to.deep.equal([
       [
         6,
         "Package natbib Warning: Citation `blah' on page 1 undefined on input line 6.",
         '/compile/main.tex',
-      ] + '',
+      ],
       [
         null,
         'Package natbib Warning: There were undefined citations.',
         '/compile/main.tex',
-      ] + '',
-    ]
-
-    expect(errors.length).to.equal(expectedErrors.length)
-    for (let i = 0; i < errors.length; i++) {
-      expect(expectedErrors[i]).to.equal(
-        [errors[i].line, errors[i].message, errors[i].file] + ''
-      )
-    }
+      ],
+    ])
   })
 
   it('should parse Geometry warnings', function () {
-    const latexParser = new LatexLogParser(this.geometryWarningsLog)
-    const errors = latexParser.parse().warnings
-
-    const expectedErrors = [
+    const { warnings } = parseLatexLog('geometry-warnings.log')
+    expect(warnings.map(w => [w.line, w.message, w.file])).to.deep.equal([
       [
         null,
         "Package geometry Warning: Over-specification in `h'-direction. `width' (597.50787pt) is ignored.",
         '/compile/main.tex',
-      ] + '',
+      ],
       [
         null,
         "Package geometry Warning: Over-specification in `v'-direction. `height' (845.04684pt) is ignored.",
         '/compile/main.tex',
-      ] + '',
-    ]
-
-    expect(errors.length).to.equal(expectedErrors.length)
-    for (let i = 0; i < errors.length; i++) {
-      expect(expectedErrors[i]).to.equal(
-        [errors[i].line, errors[i].message, errors[i].file] + ''
-      )
-    }
+      ],
+    ])
   })
 
   it('should parse Caption warnings', function () {
-    const latexParser = new LatexLogParser(this.captionWarningsLog)
-    const errors = latexParser.parse().warnings
-
-    const expectedErrors = [
+    const { warnings } = parseLatexLog('caption-warnings.log')
+    expect(warnings.map(w => [w.line, w.message, w.file])).to.deep.equal([
       [
         null,
         'Package caption Warning: Unsupported document class (or package) detected, usage of the caption package is not recommended. See the caption package documentation for explanation.',
         '/usr/local/texlive/2014/texmf-dist/tex/latex/caption/caption.sty',
-      ] + '',
+      ],
       [
         46,
         "Package caption Warning: The option `hypcap=true' will be ignored for this particular \\caption on input line 46. See the caption package documentation for explanation.",
         '/compile/main.tex',
-      ] + '',
-    ]
-
-    expect(errors.length).to.equal(expectedErrors.length)
-    for (let i = 0; i < errors.length; i++) {
-      expect(expectedErrors[i]).to.equal(
-        [errors[i].line, errors[i].message, errors[i].file] + ''
-      )
-    }
+      ],
+    ])
   })
 
   it('should parse Runaway Arguments', function () {
-    const latexParser = new LatexLogParser(this.runawayArgumentsLog)
-    const errors = latexParser.parse().errors
-
-    const expectedErrors = [
-      [null, 'Runaway argument?', '/compile/runaway_argument.tex'] + '',
-      [null, 'Emergency stop.', '/compile/runaway_argument.tex'] + '',
-    ]
-
-    expect(errors.length).to.equal(expectedErrors.length)
-    for (let i = 0; i < errors.length; i++) {
-      expect(expectedErrors[i]).to.equal(
-        [errors[i].line, errors[i].message, errors[i].file] + ''
-      )
-    }
+    const { errors } = parseLatexLog('runaway-arguments.log')
+    expect(errors.map(e => [e.line, e.message, e.file])).to.deep.equal([
+      [null, 'Runaway argument?', '/compile/runaway_argument.tex'],
+      [null, 'Emergency stop.', '/compile/runaway_argument.tex'],
+    ])
   })
 
   it('should parse filenames', function () {
-    const latexParser = new LatexLogParser(this.filenamesLog)
-    const { errors, warnings, typesetting } = latexParser.parse()
+    const { errors, warnings, typesetting } = parseLatexLog('filenames.log')
 
-    const expectedErrors = [
+    expect(errors.map(e => [e.line, e.message, e.file])).to.deep.equal([
       [
         1,
         'Undefined control sequence.',
         '/compile/a folder with spaces/a subfolder with spaces/a subsubfolder with spaces/another file with spaces.tex',
-      ] + '',
-    ]
-
-    const expectedWarnings = [
+      ],
+    ])
+    expect(warnings.map(w => [w.line, w.message, w.file])).to.deep.equal([
       [
         9,
         "Citation `Peeters:2001np' on page 13 undefined on input line 9.",
         '/compile/main',
-      ] + '',
-    ]
-
-    const expectedTypesetting = [
+      ],
+    ])
+    expect(typesetting.map(e => [e.line, e.message, e.file])).to.deep.equal([
       [
         123,
         'Overfull \\hbox (4.56pt too wide) in paragraph at lines 123--456',
         '/compile/otherfile',
-      ] + '',
-    ]
-
-    expect(expectedErrors.length).to.equal(errors.length)
-    expect(warnings.length).to.equal(warnings.length)
-    expect(typesetting.length).to.equal(typesetting.length)
-
-    for (let i = 0; i < errors.length; i++) {
-      expect(expectedErrors[i]).to.equal(
-        [errors[i].line, errors[i].message, errors[i].file] + ''
-      )
-    }
-    for (let j = 0; j < warnings.length; j++) {
-      expect(expectedWarnings[j]).to.equal(
-        [warnings[j].line, warnings[j].message, warnings[j].file] + ''
-      )
-    }
-    for (let k = 0; k < typesetting.length; k++) {
-      expect(expectedTypesetting[k]).to.equal(
-        [typesetting[k].line, typesetting[k].message, typesetting[k].file] + ''
-      )
-    }
+      ],
+    ])
   })
 
   it('should perform file line error parsing', function () {
-    let latexParser = new LatexLogParser(this.fileLineErrorLog)
-    let errors = latexParser.parse().errors
-
-    let expectedErrors = [
+    const { errors } = parseLatexLog('file-line-error.log')
+    expect(errors.map(e => [e.line, e.message, e.file])).to.deep.equal([
       [
-        1,
+        '1',
         'Undefined control sequence.',
         '/compile/a folder with spaces/a subfolder with spaces/a subsubfolder with spaces/another file with spaces.tex',
-      ] + '',
-    ]
-
-    expect(errors.length).to.equal(expectedErrors.length)
-    for (let i = 0; i < errors.length; i++) {
-      expect(expectedErrors[i]).to.equal(
-        [errors[i].line, errors[i].message, errors[i].file] + ''
-      )
-    }
-
-    // again with a more complex example
-
-    latexParser = new LatexLogParser(this.secondaryFileLineErrorLog)
-    errors = latexParser.parse().errors
+      ],
+    ])
+  })
 
-    expectedErrors = [
+  it('should perform more complex file line error parsing', function () {
+    const { errors } = parseLatexLog('file-line-error-2.log')
+    expect(errors.map(e => [e.line, e.message, e.file])).to.deep.equal([
       [1, 'Misplaced alignment tab character &.', './acks/name.tex'],
       [14, 'Misplaced alignment tab character &.', './main.tex'],
-    ]
-
-    expect(errors.length).to.equal(expectedErrors.length)
-    for (let i = 0; i < errors.length; i++) {
-      expect(expectedErrors[i]).to.deep.equal([
-        errors[i].line,
-        errors[i].message,
-        errors[i].file,
-      ])
-    }
+    ])
   })
 
   it('should ignore duplicates', function () {
-    let latexParser = new LatexLogParser(this.errorLog)
-    let errors = latexParser.parse().errors
-
     // duplicates included
+    const { errors } = parseLatexLog('errors.log')
     expect(errors.length).to.equal(10)
 
-    latexParser = new LatexLogParser(this.errorLog, { ignoreDuplicates: true })
-    errors = latexParser.parse().errors
-
     // duplicates excluded
-    expect(errors.length).to.equal(7)
+    const { errors: errorsDeduplicated } = parseLatexLog('errors.log', {
+      ignoreDuplicates: true,
+    })
+    expect(errorsDeduplicated.length).to.equal(7)
   })
 
   it('should get file paths', function () {
-    let latexParser = new LatexLogParser(this.errorLog)
-    let errors = latexParser.parse().errors
+    const { errors } = parseLatexLog('errors.log')
 
-    for (let i = 0; i < errors.length; i++) {
-      expect(errors[i].file).to.equal(
+    for (const error of errors) {
+      expect(error.file).to.equal(
         'compiles/dff0c37d892f346e58fc14975a16bf69/sections/appendices.tex'
       )
     }
 
-    latexParser = new LatexLogParser(this.badBoxesLog)
-    errors = latexParser.parse().all
-    for (let j = 0; j < errors.length; j++) {
-      expect(errors[j].file).to.equal(
+    const { all: badBoxesErrors } = parseLatexLog('bad-boxes.log')
+    for (const error of badBoxesErrors) {
+      expect(error.file).to.equal(
         'compiles/b6cf470376785e64ad84c57e3296c912/logs/bad-boxes.tex'
       )
     }
   })
 
   it('should parse a typical biber .blg file', function () {
-    const bibParser = new BibLogParser(this.biberBlg, {})
+    const log = readLog('biber.blg')
+    const bibParser = new BibLogParser(log, {})
     const result = bibParser.parse()
     expect(typeof result).to.equal('object')
     expect(result.all.length).to.equal(14)
@@ -503,38 +296,24 @@ describe('logParser', function (done) {
     )
   })
 
-  it('should throw an error when non-biblog passed to BibLogParser', function (done) {
-    const bibParser = new BibLogParser(this.captionWarningsLog, {})
-    try {
-      bibParser.parse()
-    } catch (e) {
-      expect(e).to.exist
-      done()
-    }
+  it('should throw an error when non-biblog passed to BibLogParser', function () {
+    const log = readLog('caption-warnings.log')
+    const bibParser = new BibLogParser(log, {})
+    expect(() => bibParser.parse()).to.throw()
   })
 
-  it('should throw an error when empty string passed to BibLogParser', function (done) {
+  it('should throw an error when empty string passed to BibLogParser', function () {
     const bibParser = new BibLogParser('', {})
-    try {
-      bibParser.parse()
-    } catch (e) {
-      expect(e).to.exist
-      done()
-    }
+    expect(() => bibParser.parse()).to.throw()
   })
 
-  it('should throw an error when non-string passed to BibLogParser', function (done) {
-    try {
-      const bibParser = new BibLogParser({ a: 1 }, {})
-      bibParser.parse()
-    } catch (e) {
-      expect(e).to.exist
-      done()
-    }
+  it('should throw an error when non-string passed to BibLogParser', function () {
+    expect(() => new BibLogParser({ a: 1 }, {})).to.throw()
   })
 
   it('should parse a typical bibtex .blg file', function () {
-    const bibParser = new BibLogParser(this.bibtexBlg, {})
+    const log = readLog('bibtex.blg')
+    const bibParser = new BibLogParser(log, {})
     const result = bibParser.parse()
 
     expect(typeof result).to.equal('object')
@@ -579,8 +358,7 @@ describe('logParser', function (done) {
 
   // https://github.com/overleaf/overleaf/issues/1023
   it('should parse logs from issue 1023', function () {
-    const latexParser = new LatexLogParser(this.issue1023Log)
-    const { errors, warnings } = latexParser.parse()
+    const { errors, warnings } = parseLatexLog('open-source-issue-1023.log')
     expect(errors.map(x => [x.line, x.message, x.file])).to.deep.equal([
       [38, 'Package PACKAGE Error: TEXT PackageError.', './main.tex'],
       [45, 'Class PACKAGE Error: TEXT ClassError.', './main.tex'],
@@ -623,3 +401,16 @@ describe('logParser', function (done) {
     ])
   })
 })
+
+function readLog(filename) {
+  return fs.readFileSync(path.resolve(__dirname, fixturePath + filename), {
+    encoding: 'utf8',
+    flag: 'r',
+  })
+}
+
+function parseLatexLog(filename, opts = {}) {
+  const log = readLog(filename)
+  const parser = new LatexLogParser(log, opts)
+  return parser.parse()
+}