From 98eacf4a9defb27ad386aef9e3a7d6d74ae3cacf Mon Sep 17 00:00:00 2001 From: Martin Heidegger Date: Wed, 23 Mar 2022 12:20:10 +0900 Subject: [PATCH 1/4] chore: moving to github actions --- .github/workflows/test.yml | 15 +++++++++++++++ .travis.yml | 7 ------- README.md | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/test.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..d1b71d4 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,15 @@ +name: Tests + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: lts/* + - run: npm -v + - run: npm i + - run: npm test diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f95469d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: node_js -node_js: - - '0.10' - - '0.12' - - '4' - - '5' - - 'node' diff --git a/README.md b/README.md index 4312eb4..e04cb78 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ No nonsense [protocol buffers](https://developers.google.com/protocol-buffers) s npm install protocol-buffers-schema ``` -[![build status](http://img.shields.io/travis/mafintosh/protocol-buffers-schema.svg?style=flat)](http://travis-ci.org/mafintosh/protocol-buffers-schema) +[![build status](https://github.com/mafintosh/protocol-buffers-schema/actions/workflows/test.yml/badge.svg)](https://github.com/mafintosh/protocol-buffers-schema/workflows/test.yml) ## Usage From aedf28f4c53e8dde0e45266b037f0bcc658c2e54 Mon Sep 17 00:00:00 2001 From: Martin Heidegger Date: Tue, 22 Mar 2022 01:27:30 +0900 Subject: [PATCH 2/4] chore: updating test --- package.json | 2 +- test/fixtures/reserved.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 904d6c5..d56fd1b 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "devDependencies": { "standard": "^10.0.3", - "tape": "^4.8.0" + "tape": "^5.5.2" }, "scripts": { "test": "standard && tape test/*.js" diff --git a/test/fixtures/reserved.json b/test/fixtures/reserved.json index 6b1e9b3..28a589c 100644 --- a/test/fixtures/reserved.json +++ b/test/fixtures/reserved.json @@ -8,11 +8,11 @@ "values": { "x": { "value": 1, - "options": [] + "options": {} }, "y": { "value": 10, - "options": [] + "options": {} } }, "options": {} From 8ecb592e09fc65dbc85fe79f55519d24b9334f41 Mon Sep 17 00:00:00 2001 From: Martin Heidegger Date: Tue, 22 Mar 2022 01:34:56 +0900 Subject: [PATCH 3/4] chore: update linting --- example.js | 6 +- index.js | 4 +- package.json | 2 +- parse.js | 203 ++++++++++++++++++++++++++------------------------ stringify.js | 54 +++++++------- test/index.js | 20 ++--- tokenize.js | 22 +++--- 7 files changed, 159 insertions(+), 152 deletions(-) diff --git a/example.js b/example.js index a8a14da..a8f4bf2 100644 --- a/example.js +++ b/example.js @@ -1,7 +1,7 @@ -var schema = require('./') -var fs = require('fs') +const schema = require('./') +const fs = require('fs') -var sch = schema.parse(fs.readFileSync('example.proto')) +const sch = schema.parse(fs.readFileSync('example.proto')) console.log('Parsed schema:') console.log(JSON.stringify(sch, null, 2)) diff --git a/index.js b/index.js index 1292497..199c019 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ -var parse = require('./parse') -var stringify = require('./stringify') +const parse = require('./parse') +const stringify = require('./stringify') module.exports = parse module.exports.parse = parse diff --git a/package.json b/package.json index d56fd1b..19cdcf2 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "No nonsense protocol buffers schema parser written in Javascript", "main": "index.js", "devDependencies": { - "standard": "^10.0.3", + "standard": "^16.0.4", "tape": "^5.5.2" }, "scripts": { diff --git a/parse.js b/parse.js index a0d2fc2..2889818 100644 --- a/parse.js +++ b/parse.js @@ -1,9 +1,9 @@ -var tokenize = require('./tokenize') -var MAX_RANGE = 0x1FFFFFFF +const tokenize = require('./tokenize') +const MAX_RANGE = 0x1FFFFFFF // "Only repeated fields of primitive numeric types (types which use the varint, 32-bit, or 64-bit wire types) can be declared "packed"." // https://developers.google.com/protocol-buffers/docs/encoding#optional -var PACKABLE_TYPES = [ +const PACKABLE_TYPES = [ // varint wire types 'int32', 'int64', 'uint32', 'uint64', 'sint32', 'sint64', 'bool', // + ENUMS @@ -13,13 +13,13 @@ var PACKABLE_TYPES = [ 'fixed32', 'sfixed32', 'float' ] -var onfieldoptionvalue = function (tokens) { - var value = tokens.shift() +function onfieldoptionvalue (tokens) { + let value = tokens.shift() if (value !== '{') { return value } value = {} - var field = '' + let field = '' while (tokens.length) { switch (tokens[0]) { case '}': @@ -35,20 +35,20 @@ var onfieldoptionvalue = function (tokens) { } } -var onfieldoptions = function (tokens) { - var opts = {} +function onfieldoptions (tokens) { + const opts = {} while (tokens.length) { switch (tokens[0]) { case '[': case ',': { tokens.shift() - var name = tokens.shift() + let name = tokens.shift() if (name === '(') { // handling [(A) = B] name = tokens.shift() tokens.shift() // remove the end of bracket } - var field = [] + let field = [] if (tokens[0][0] === '.') { field = tokens[0].substr(1).split('.') tokens.shift() @@ -59,11 +59,11 @@ var onfieldoptions = function (tokens) { // for option (A).b.c // path will be ['A', 'b'] and lastFieldName 'c' - var path = [name].concat(field) - var lastFieldName = path.pop() + const path = [name].concat(field) + const lastFieldName = path.pop() // opt references opts.A.b - var opt = path.reduce(function (opt, n, index) { + const opt = path.reduce(function (opt, n, index) { if (opt[n] == null) { opt[n] = {} } @@ -86,8 +86,8 @@ var onfieldoptions = function (tokens) { throw new Error('No closing tag for field options') } -var onfield = function (tokens) { - var field = { +function onfield (tokens) { + const field = { name: null, type: null, tag: -1, @@ -123,11 +123,13 @@ var onfield = function (tokens) { case 'repeated': case 'required': case 'optional': - var t = tokens.shift() - field.required = t === 'required' - field.repeated = t === 'repeated' - field.type = tokens.shift() - field.name = tokens.shift() + { + const t = tokens.shift() + field.required = t === 'required' + field.repeated = t === 'repeated' + field.type = tokens.shift() + field.name = tokens.shift() + } break case '[': @@ -149,8 +151,8 @@ var onfield = function (tokens) { throw new Error('No ; found for message field') } -var onmessagebody = function (tokens) { - var body = { +function onmessagebody (tokens) { + const body = { enums: [], options: {}, messages: [], @@ -182,14 +184,16 @@ var onmessagebody = function (tokens) { case 'oneof': tokens.shift() - var name = tokens.shift() - if (tokens[0] !== '{') throw new Error('Unexpected token in oneof: ' + tokens[0]) - tokens.shift() - while (tokens[0] !== '}') { - tokens.unshift('optional') - var field = onfield(tokens) - field.oneof = name - body.fields.push(field) + { + const name = tokens.shift() + if (tokens[0] !== '{') throw new Error('Unexpected token in oneof: ' + tokens[0]) + tokens.shift() + while (tokens[0] !== '}') { + tokens.unshift('optional') + const field = onfield(tokens) + field.oneof = name + body.fields.push(field) + } } tokens.shift() break @@ -210,9 +214,11 @@ var onmessagebody = function (tokens) { break case 'option': - var opt = onoption(tokens) - if (body.options[opt.name] !== undefined) throw new Error('Duplicate option ' + opt.name) - body.options[opt.name] = opt.value + { + const opt = onoption(tokens) + if (body.options[opt.name] !== undefined) throw new Error('Duplicate option ' + opt.name) + body.options[opt.name] = opt.value + } break default: @@ -227,32 +233,32 @@ var onmessagebody = function (tokens) { return body } -var onextend = function (tokens) { - var out = { +function onextend (tokens) { + const out = { name: tokens[1], message: onmessage(tokens) } return out } -var onextensions = function (tokens) { +function onextensions (tokens) { tokens.shift() - var from = Number(tokens.shift()) + const from = Number(tokens.shift()) if (isNaN(from)) throw new Error('Invalid from in extensions definition') if (tokens.shift() !== 'to') throw new Error("Expected keyword 'to' in extensions definition") - var to = tokens.shift() + let to = tokens.shift() if (to === 'max') to = MAX_RANGE to = Number(to) if (isNaN(to)) throw new Error('Invalid to in extensions definition') if (tokens.shift() !== ';') throw new Error('Missing ; in extensions definition') return { from: from, to: to } } -var onmessage = function (tokens) { +function onmessage (tokens) { tokens.shift() - var lvl = 1 - var body = [] - var msg = { + let lvl = 1 + let body = [] + const msg = { name: tokens.shift(), options: {}, enums: [], @@ -286,21 +292,21 @@ var onmessage = function (tokens) { if (lvl) throw new Error('No closing tag for message') } -var onpackagename = function (tokens) { +function onpackagename (tokens) { tokens.shift() - var name = tokens.shift() + const name = tokens.shift() if (tokens[0] !== ';') throw new Error('Expected ; but found ' + tokens[0]) tokens.shift() return name } -var onsyntaxversion = function (tokens) { +function onsyntaxversion (tokens) { tokens.shift() if (tokens[0] !== '=') throw new Error('Expected = but found ' + tokens[0]) tokens.shift() - var version = tokens.shift() + let version = tokens.shift() switch (version) { case '"proto2"': version = 2 @@ -320,7 +326,7 @@ var onsyntaxversion = function (tokens) { return version } -var onenumvalue = function (tokens) { +function onenumvalue (tokens) { if (tokens.length < 4) throw new Error('Invalid enum value: ' + tokens.slice(0, 3).join(' ')) if (tokens[0] === 'reserved') { tokens.shift() @@ -333,9 +339,9 @@ var onenumvalue = function (tokens) { if (tokens[1] !== '=') throw new Error('Expected = but found ' + tokens[1]) if (tokens[3] !== ';' && tokens[3] !== '[') throw new Error('Expected ; or [ but found ' + tokens[1]) - var name = tokens.shift() + const name = tokens.shift() tokens.shift() - var val = { + const val = { value: null, options: {} } @@ -351,10 +357,10 @@ var onenumvalue = function (tokens) { } } -var onenum = function (tokens) { +function onenum (tokens) { tokens.shift() - var options = {} - var e = { + let options = {} + const e = { name: tokens.shift(), values: {}, options: {} @@ -375,7 +381,7 @@ var onenum = function (tokens) { e.options[options.name] = options.value continue } - var val = onenumvalue(tokens) + const val = onenumvalue(tokens) if (val !== null) { e.values[val.name] = val.val } @@ -384,11 +390,11 @@ var onenum = function (tokens) { throw new Error('No closing tag for enum') } -var onoption = function (tokens) { - var name = null - var value = null +function onoption (tokens) { + let name = null + let value = null - var parse = function (value) { + function parse (value) { if (value === 'true') return true if (value === 'false') return false return value.replace(/^"+|"+$/gm, '') @@ -402,15 +408,16 @@ var onoption = function (tokens) { switch (tokens[0]) { case 'option': tokens.shift() + { + const hasBracket = tokens[0] === '(' + if (hasBracket) tokens.shift() - var hasBracket = tokens[0] === '(' - if (hasBracket) tokens.shift() - - name = tokens.shift() + name = tokens.shift() - if (hasBracket) { - if (tokens[0] !== ')') throw new Error('Expected ) but found ' + tokens[0]) - tokens.shift() + if (hasBracket) { + if (tokens[0] !== ')') throw new Error('Expected ) but found ' + tokens[0]) + tokens.shift() + } } if (tokens[0][0] === '.') { @@ -438,14 +445,14 @@ var onoption = function (tokens) { } } -var onoptionMap = function (tokens) { - var parse = function (value) { +function onoptionMap (tokens) { + function parse (value) { if (value === 'true') return true if (value === 'false') return false return value.replace(/^"+|"+$/gm, '') } - var map = {} + const map = {} while (tokens.length) { if (tokens[0] === '}') { @@ -453,16 +460,16 @@ var onoptionMap = function (tokens) { return map } - var hasBracket = tokens[0] === '(' + const hasBracket = tokens[0] === '(' if (hasBracket) tokens.shift() - var key = tokens.shift() + const key = tokens.shift() if (hasBracket) { if (tokens[0] !== ')') throw new Error('Expected ) but found ' + tokens[0]) tokens.shift() } - var value = null + let value = null switch (tokens[0]) { case ':': @@ -502,9 +509,9 @@ var onoptionMap = function (tokens) { throw new Error('No closing tag for option map') } -var onimport = function (tokens) { +function onimport (tokens) { tokens.shift() - var file = tokens.shift().replace(/^"+|"+$/gm, '') + const file = tokens.shift().replace(/^"+|"+$/gm, '') if (tokens[0] !== ';') throw new Error('Unexpected token: ' + tokens[0] + '. Expected ";"') @@ -512,10 +519,10 @@ var onimport = function (tokens) { return file } -var onservice = function (tokens) { +function onservice (tokens) { tokens.shift() - var service = { + const service = { name: tokens.shift(), methods: [], options: {} @@ -534,9 +541,11 @@ var onservice = function (tokens) { switch (tokens[0]) { case 'option': - var opt = onoption(tokens) - if (service.options[opt.name] !== undefined) throw new Error('Duplicate option ' + opt.name) - service.options[opt.name] = opt.value + { + const opt = onoption(tokens) + if (service.options[opt.name] !== undefined) throw new Error('Duplicate option ' + opt.name) + service.options[opt.name] = opt.value + } break case 'rpc': service.methods.push(onrpc(tokens)) @@ -549,10 +558,10 @@ var onservice = function (tokens) { throw new Error('No closing tag for service') } -var onrpc = function (tokens) { +function onrpc (tokens) { tokens.shift() - var rpc = { + const rpc = { name: tokens.shift(), input_type: null, output_type: null, @@ -607,7 +616,7 @@ var onrpc = function (tokens) { } if (tokens[0] === 'option') { - var opt = onoption(tokens) + const opt = onoption(tokens) if (rpc.options[opt.name] !== undefined) throw new Error('Duplicate option ' + opt.name) rpc.options[opt.name] = opt.value } else { @@ -618,17 +627,12 @@ var onrpc = function (tokens) { throw new Error('No closing tag for rpc') } -var parse = function (buf) { - var tokens = tokenize(buf.toString()) +function parse (buf) { + let tokens = tokenize(buf.toString()) // check for isolated strings in tokens by looking for opening quote - for (var i = 0; i < tokens.length; i++) { + for (let i = 0; i < tokens.length; i++) { if (/^("|')([^'"]*)$/.test(tokens[i])) { - var j - if (tokens[i].length === 1) { - j = i + 1 - } else { - j = i - } + let j = (tokens[i].length === 1) ? i + 1 : i // look ahead for the closing quote and collapse all // in-between tokens into a single token for (j; j < tokens.length; j++) { @@ -639,7 +643,7 @@ var parse = function (buf) { } } } - var schema = { + const schema = { syntax: 3, package: null, imports: [], @@ -649,7 +653,7 @@ var parse = function (buf) { extends: [] } - var firstline = true + let firstline = true while (tokens.length) { switch (tokens[0]) { @@ -671,9 +675,11 @@ var parse = function (buf) { break case 'option': - var opt = onoption(tokens) - if (schema.options[opt.name]) throw new Error('Duplicate option ' + opt.name) - schema.options[opt.name] = opt.value + { + const opt = onoption(tokens) + if (schema.options[opt.name]) throw new Error('Duplicate option ' + opt.name) + schema.options[opt.name] = opt.value + } break case 'import': @@ -711,10 +717,10 @@ var parse = function (buf) { schema.messages.forEach(function (msg) { msg.fields.forEach(function (field) { - var fieldSplit - var messageName - var nestedEnumName - var message + let fieldSplit + let messageName + let nestedEnumName + let message function enumNameIsFieldType (en) { return en.name === field.type @@ -745,6 +751,7 @@ var parse = function (buf) { message = msg return msg } + return false }) if (message && message.enums && message.enums.some(enumNameIsNestedEnumName)) { diff --git a/stringify.js b/stringify.js index 19c9435..8a00f5f 100644 --- a/stringify.js +++ b/stringify.js @@ -1,14 +1,14 @@ -var onimport = function (i, result) { +function onimport (i, result) { result.push('import "' + i + '";', '') return result } -var onfield = function (f, result) { - var prefix = f.repeated ? 'repeated' : f.required ? 'required' : 'optional' +function onfield (f, result) { + let prefix = f.repeated ? 'repeated' : f.required ? 'required' : 'optional' if (f.type === 'map') prefix = 'map<' + f.map.from + ',' + f.map.to + '>' if (f.oneof) prefix = '' - var opts = Object.keys(f.options || {}).map(function (key) { + let opts = Object.keys(f.options || {}).map(function (key) { return key + ' = ' + f.options[key] }).join(',') @@ -18,7 +18,7 @@ var onfield = function (f, result) { return result } -var onmessage = function (m, result) { +function onmessage (m, result) { result.push('message ' + m.name + ' {') if (!m.options) m.options = {} @@ -34,7 +34,7 @@ var onmessage = function (m, result) { result.push(onmessage(m, [])) }) - var oneofs = {} + const oneofs = {} if (!m.fields) m.fields = [] m.fields.forEach(function (f) { @@ -56,38 +56,38 @@ var onmessage = function (m, result) { return result } -var onenum = function (e, result) { +function onenum (e, result) { result.push('enum ' + e.name + ' {') if (!e.options) e.options = {} - var options = onoption(e.options, []) + const options = onoption(e.options, []) if (options.length > 1) { result.push(options.slice(0, -1)) } - Object.keys(e.values).map(function (v) { - var val = onenumvalue(e.values[v]) + Object.keys(e.values).forEach(function (v) { + const val = onenumvalue(e.values[v]) result.push([v + ' = ' + val + ';']) }) result.push('}', '') return result } -var onenumvalue = function (v, result) { - var opts = Object.keys(v.options || {}).map(function (key) { +function onenumvalue (v, result) { + let opts = Object.keys(v.options || {}).map(function (key) { return key + ' = ' + v.options[key] }).join(',') if (opts) opts = ' [' + opts + ']' - var val = v.value + opts + const val = v.value + opts return val } -var onoption = function (o, result) { - var keys = Object.keys(o) +function onoption (o, result) { + const keys = Object.keys(o) keys.forEach(function (option) { - var v = o[option] + let v = o[option] if (~option.indexOf('.')) option = '(' + option + ')' - var type = typeof v + const type = typeof v if (type === 'object') { v = onoptionMap(v, []) @@ -104,12 +104,12 @@ var onoption = function (o, result) { return result } -var onoptionMap = function (o, result) { - var keys = Object.keys(o) +function onoptionMap (o, result) { + const keys = Object.keys(o) keys.forEach(function (k) { - var v = o[k] + let v = o[k] - var type = typeof v + const type = typeof v if (type === 'object') { if (Array.isArray(v)) { @@ -130,7 +130,7 @@ var onoptionMap = function (o, result) { return result } -var onservices = function (s, result) { +function onservices (s, result) { result.push('service ' + s.name + ' {') if (!s.options) s.options = {} @@ -144,8 +144,8 @@ var onservices = function (s, result) { return result } -var onrpc = function (rpc, result) { - var def = 'rpc ' + rpc.name + '(' +function onrpc (rpc, result) { + let def = 'rpc ' + rpc.name + '(' if (rpc.client_streaming) def += 'stream ' def += rpc.input_type + ') returns (' if (rpc.server_streaming) def += 'stream ' @@ -153,7 +153,7 @@ var onrpc = function (rpc, result) { if (!rpc.options) rpc.options = {} - var options = onoption(rpc.options, []) + const options = onoption(rpc.options, []) if (options.length > 1) { result.push(def + ' {', options.slice(0, -1), '}') } else { @@ -163,7 +163,7 @@ var onrpc = function (rpc, result) { return result } -var indent = function (lvl) { +function indent (lvl) { return function (line) { if (Array.isArray(line)) return line.map(indent(lvl + ' ')).join('\n') return lvl + line @@ -171,7 +171,7 @@ var indent = function (lvl) { } module.exports = function (schema) { - var result = [] + const result = [] result.push('syntax = "proto' + schema.syntax + '";', '') diff --git a/test/index.js b/test/index.js index 925a5b2..0b2b056 100644 --- a/test/index.js +++ b/test/index.js @@ -1,9 +1,9 @@ -var tape = require('tape') -var path = require('path') -var fs = require('fs') -var schema = require('../') +const tape = require('tape') +const path = require('path') +const fs = require('fs') +const schema = require('../') -var fixture = function (name) { +const fixture = function (name) { return fs.readFileSync(path.join(__dirname, 'fixtures', name), 'utf-8') } @@ -13,7 +13,7 @@ tape('basic parse', function (t) { }) tape('basic parse + stringify', function (t) { - var syntax = 'syntax = "proto3";\n\n' + const syntax = 'syntax = "proto3";\n\n' t.same(schema.stringify(schema.parse(fixture('basic.proto'))), syntax + fixture('basic.proto')) t.end() }) @@ -24,7 +24,7 @@ tape('complex parse', function (t) { }) tape('complex parse + stringify', function (t) { - var syntax = 'syntax = "proto3";\n\n' + const syntax = 'syntax = "proto3";\n\n' t.same(schema.stringify(schema.parse(fixture('complex.proto'))), syntax + fixture('complex.proto')) t.end() }) @@ -64,7 +64,7 @@ tape('schema with extends', function (t) { }) tape('comparing extended and not extended schema', function (t) { - var sch = schema.parse(fixture('extend.proto')) + const sch = schema.parse(fixture('extend.proto')) t.same(sch.messages.MsgNormal, sch.messages.MsgExtend) t.end() }) @@ -104,13 +104,13 @@ tape('service parse', function (t) { }) tape('service parse + stringify', function (t) { - var syntax = 'syntax = "proto3";\n\n' + const syntax = 'syntax = "proto3";\n\n' t.same(schema.stringify(schema.parse(fixture('service.proto'))), syntax + fixture('service.proto')) t.end() }) tape('import parse + stringify', function (t) { - var syntax = 'syntax = "proto3";\n\n' + const syntax = 'syntax = "proto3";\n\n' t.same(schema.stringify(schema.parse(fixture('search.proto'))), syntax + fixture('search.proto')) t.end() }) diff --git a/tokenize.js b/tokenize.js index 425d436..66fbbae 100644 --- a/tokenize.js +++ b/tokenize.js @@ -1,11 +1,11 @@ module.exports = function (sch) { - var noComments = function (line) { - var i = line.indexOf('//') + const noComments = function (line) { + const i = line.indexOf('//') return i > -1 ? line.slice(0, i) : line } - var noMultilineComments = function () { - var inside = false + const noMultilineComments = function () { + let inside = false return function (token) { if (token === '/*') { inside = true @@ -19,27 +19,27 @@ module.exports = function (sch) { } } - var trim = function (line) { + const trim = function (line) { return line.trim() } - var removeQuotedLines = function (list) { + const removeQuotedLines = function (list) { return function (str) { - var s = '$' + list.length + '$' + const s = '$' + list.length + '$' list.push(str) return s } } - var restoreQuotedLines = function (list) { - var re = /^\$(\d+)\$$/ + const restoreQuotedLines = function (list) { + const re = /^\$(\d+)\$$/ return function (line) { - var m = line.match(re) + const m = line.match(re) return m ? list[+m[1]] : line } } - var replacements = [] + const replacements = [] return sch .replace(/"(\\"|[^"\n])*?"|'(\\'|[^'\n])*?'/gm, removeQuotedLines(replacements)) .replace(/([;,{}()=:[\]<>]|\/\*|\*\/)/g, ' $1 ') From bcba0463c4d2166812364afda6baa5720ecb24e1 Mon Sep 17 00:00:00 2001 From: Martin Heidegger Date: Tue, 22 Mar 2022 02:00:07 +0900 Subject: [PATCH 4/4] feat: fully supporting import flags --- parse.js | 22 ++++++++++++++++++---- stringify.js | 2 +- test/fixtures/import.json | 7 ++++++- test/fixtures/import.proto | 2 ++ test/fixtures/option.json | 5 ++++- test/fixtures/search.json | 2 +- test/index.js | 7 +++++++ 7 files changed, 39 insertions(+), 8 deletions(-) diff --git a/parse.js b/parse.js index 2889818..c449603 100644 --- a/parse.js +++ b/parse.js @@ -511,12 +511,26 @@ function onoptionMap (tokens) { function onimport (tokens) { tokens.shift() - const file = tokens.shift().replace(/^"+|"+$/gm, '') + let token = tokens.shift() - if (tokens[0] !== ';') throw new Error('Unexpected token: ' + tokens[0] + '. Expected ";"') + let flag = null + if (token === 'public' || token === 'weak') { + flag = token + token = tokens.shift() + } + if (!/^".*"$/.test(token)) { + throw new Error('Unexpected import <' + token + '>. Expecting a string literal.') + } + const file = token.replace(/^"+|"+$/gm, '') - tokens.shift() - return file + token = tokens.shift() + + if (token !== ';') throw new Error('Unexpected token: ' + token + '. Expected ";"') + + return { + file: file, + flag: flag + } } function onservice (tokens) { diff --git a/stringify.js b/stringify.js index 8a00f5f..e00e89f 100644 --- a/stringify.js +++ b/stringify.js @@ -1,5 +1,5 @@ function onimport (i, result) { - result.push('import "' + i + '";', '') + result.push('import ' + (i.flag ? i.flag + ' "' : '"') + i.file + '";', '') return result } diff --git a/test/fixtures/import.json b/test/fixtures/import.json index bb53a72..a2af6fe 100644 --- a/test/fixtures/import.json +++ b/test/fixtures/import.json @@ -1,7 +1,12 @@ { "syntax": 3, "package": null, - "imports": ["./result.proto", "./other_result.proto"], + "imports": [ + { "file": "./result.proto", "flag": null }, + { "file": "./other_result.proto", "flag": null }, + { "file": "./public.proto", "flag": "public" }, + { "file": "./weak.proto", "flag": "weak" } + ], "enums": [], "extends": [], "messages": [ diff --git a/test/fixtures/import.proto b/test/fixtures/import.proto index 692ca71..434d355 100644 --- a/test/fixtures/import.proto +++ b/test/fixtures/import.proto @@ -1,5 +1,7 @@ import "./result.proto"; import "./other_result.proto"; +import public "./public.proto"; +import weak "./weak.proto"; message SearchResponse { repeated Result result = 1; diff --git a/test/fixtures/option.json b/test/fixtures/option.json index e80ca35..c5e6f9b 100644 --- a/test/fixtures/option.json +++ b/test/fixtures/option.json @@ -2,7 +2,10 @@ "syntax": 3, "package": null, "imports": [ - "google/protobuf/descriptor.proto" + { + "file": "google/protobuf/descriptor.proto", + "flag": null + } ], "enums": [ { diff --git a/test/fixtures/search.json b/test/fixtures/search.json index d1a37c5..a74dc44 100644 --- a/test/fixtures/search.json +++ b/test/fixtures/search.json @@ -1,7 +1,7 @@ { "syntax": 3, "package": null, - "imports": ["./result.proto"], + "imports": [{ "file": "./result.proto", "flag": null }], "enums": [], "extends": [], "messages": [ diff --git a/test/index.js b/test/index.js index 0b2b056..e8c1305 100644 --- a/test/index.js +++ b/test/index.js @@ -53,6 +53,13 @@ tape('schema with imports', function (t) { t.end() }) +tape('schema without quotes', function (t) { + t.throws(function () { + schema.parse('import foo;') + }, /Unexpected import . Expecting a string literal./) + t.end() +}) + tape('schema with imports loaded by path', function (t) { t.same(schema.parse(fixture('search.proto')), require('./fixtures/search.json')) t.end()