简体   繁体   中英

Semantic checking of protobuf generated JS code in VS Code and JSDoc

I am writing a Node.js application that is using Google Protocol Buffers to communicate with a C# client.

I am using the official Google's JavaScript compiler with CommonJS style imports. I have recently added linting to my project with eslint and specifically the default "google" config. VS Code offers semantic checking (setting ID js/ts.implicitProjectConfig.checkJs ) which combined with JSDoc, that the google lint style enforces, works very well for introducing a little bit of type-safety into my application. Now the issue is that I can't get the VS Code semantic checking to work with Protocol Buffers generated JS code. The code runs fine so at least Node understands the protocol buffer code.

Here is a small example code, index.js , that's giving me trouble:

// Alteratively following works for JSDoc as well: /** @typedef { import('./bar').Bar } Bar */
const {Bar} = require('./bar');

// The typedef imports are not working:
// /** @typedef { import('./foo_pb').fooPackage } fooPackage */
// ^ Warns "Namespace ...foo_pb has no exported member fooPackage"
// /** @typedef { import('./foo_pb').Foo } Foo */
// ^ Warns "Namespace ...foo_pb has no exported member Foo"
const fooPackage = require('./foo_pb');

/**
 * @param {Bar} bar
 */
function useBar(bar) {
  bar.printHi();
}

// VS Code warns "Namespace <abspath>/foo_pb has no exported member 'Foo'."
/**
 * @param {fooPackage.Foo} foo
 */
function useFoo(foo) {
  console.log(foo);
}

useBar(new Bar());
// VS Code warns "Property 'Foo' does not exist on type 'typeof import("<abspath>/foo_pb")'."
useFoo(fooPackage.Foo.FOO_OK);

Here is the foo.proto file and it generated output foo_pb.js :

// foo.proto
syntax = "proto3";

package fooPackage;

enum Foo {
  FOO_UNSPECIFIED = 0;
  FOO_OK = 1;
}

// foo_pb.js
var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();

goog.exportSymbol('proto.fooPackage.Foo', null, global);
/**
 * @enum {number}
 */
proto.fooPackage.Foo = {
  FOO_UNSPECIFIED: 0,
  FOO_OK: 1
};

goog.object.extend(exports, proto.fooPackage);

Here is bar.js used in the index.js that works as I would expect with the semantic checking:

/** A Bar class */
class Bar {
  /** Prints hi */
  printHi() {
    console.log('Hi');
  }
}

module.exports = {
  Bar,
};

Here is my, abridged, package.json :

{
  "main": "index.js",
  "scripts": {
    "build": "protoc --proto_path=./ --js_out=import_style=commonjs,binary:./ foo.proto",
    "lint": "node_modules/.bin/eslint ./"
  },
  "dependencies": {
    "google-protobuf": "^3.14.0"
  },
  "devDependencies": {
    "eslint": "^7.18.0",
    "eslint-config-google": "^0.14.0"
  }
}

It's not clear to me whether this is issue with VS Code, the Google's protocol buffer code or JSDoc and how does TypeScript and Closure play into this.

A reasonable solution for me to use following require syntax: const Foo = require('./foo_pb').Foo; .

VS Code semantic checking does NOT complain about it, but it does have following downsides:

  • Each symbol must be imported separately while const fooPackage = require('./foo_pb'); imports all symbols into fooPackage "namespace". This could be argued is actually a benefit since the whole "Include what you use" principle.
  • VS Code is not able to inspect those symbols so auto-complete won't be working for them
  • Linting might complain about no-unused-vars on those imports if they are, for example, just function parameters. A simple solution for me is to wrap those imports /* eslint-disable no-unused-vars */ blocks.

Just for reference, here is working index.js :

const {Bar} = require('./bar');

const Foo = require('./foo_pb').Foo;

/**
 * @param {Bar} bar
 */
function useBar(bar) {
  bar.printHi();
}

/**
 * @param {Foo} foo
 */
function useFoo(foo) {
  console.log(foo);
}

useBar(new Bar());
useFoo(Foo.FOO_OK);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM