VS Code 和 JSDoc 中 protobuf 生成的 JS 代码的语义检查
Semantic checking of protobuf generated JS code in VS Code and JSDoc
我正在编写一个 Node.js 应用程序,它使用 Google 协议缓冲区与 C# 客户端通信。
我正在使用带有 CommonJS 样式导入的官方 Google 的 JavaScript 编译器。我最近使用 eslint 将 linting 添加到我的项目中,特别是默认的“google”配置。 VS Code 提供语义检查(设置 ID js/ts.implicitProjectConfig.checkJs
),它与 JSDoc 结合,google lint 风格强制执行,非常适合在我的应用程序中引入一点类型安全。现在的问题是我无法让 VS Code 语义检查与 Protocol Buffers 生成的 JS 代码一起使用。代码运行良好,所以至少 Node 理解协议缓冲区代码。
这是一个小示例代码,index.js,这给我带来了麻烦:
// 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);
这是 foo.proto 文件,它生成输出 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);
这是 bar.js 中使用的 index.js ,它的工作方式与我预期的语义检查一样:
/** A Bar class */
class Bar {
/** Prints hi */
printHi() {
console.log('Hi');
}
}
module.exports = {
Bar,
};
这是我的,删节的,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"
}
}
我不清楚这是否是 VS Code、Google 的协议缓冲区代码或 JSDoc 的问题,以及 TypeScript 和 Closure 如何发挥作用。
我使用以下 require 语法的合理解决方案:const Foo = require('./foo_pb').Foo;
.
VS Code 语义检查不会抱怨它,但它确实有以下缺点:
- 每个符号都必须单独导入,而
const fooPackage = require('./foo_pb');
将所有符号导入 fooPackage
“命名空间”。可以说这实际上是一个好处,因为整个“包括您使用的内容”原则。
- VS Code 无法检查这些符号,因此自动完成对它们不起作用
- Linting 可能会抱怨
no-unused-vars
这些导入,例如,如果它们只是函数参数。对我来说一个简单的解决方案是包装这些导入 /* eslint-disable no-unused-vars */
块。
仅供参考,这里正在工作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);
我正在编写一个 Node.js 应用程序,它使用 Google 协议缓冲区与 C# 客户端通信。
我正在使用带有 CommonJS 样式导入的官方 Google 的 JavaScript 编译器。我最近使用 eslint 将 linting 添加到我的项目中,特别是默认的“google”配置。 VS Code 提供语义检查(设置 ID js/ts.implicitProjectConfig.checkJs
),它与 JSDoc 结合,google lint 风格强制执行,非常适合在我的应用程序中引入一点类型安全。现在的问题是我无法让 VS Code 语义检查与 Protocol Buffers 生成的 JS 代码一起使用。代码运行良好,所以至少 Node 理解协议缓冲区代码。
这是一个小示例代码,index.js,这给我带来了麻烦:
// 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);
这是 foo.proto 文件,它生成输出 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);
这是 bar.js 中使用的 index.js ,它的工作方式与我预期的语义检查一样:
/** A Bar class */
class Bar {
/** Prints hi */
printHi() {
console.log('Hi');
}
}
module.exports = {
Bar,
};
这是我的,删节的,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"
}
}
我不清楚这是否是 VS Code、Google 的协议缓冲区代码或 JSDoc 的问题,以及 TypeScript 和 Closure 如何发挥作用。
我使用以下 require 语法的合理解决方案:const Foo = require('./foo_pb').Foo;
.
VS Code 语义检查不会抱怨它,但它确实有以下缺点:
- 每个符号都必须单独导入,而
const fooPackage = require('./foo_pb');
将所有符号导入fooPackage
“命名空间”。可以说这实际上是一个好处,因为整个“包括您使用的内容”原则。 - VS Code 无法检查这些符号,因此自动完成对它们不起作用
- Linting 可能会抱怨
no-unused-vars
这些导入,例如,如果它们只是函数参数。对我来说一个简单的解决方案是包装这些导入/* eslint-disable no-unused-vars */
块。
仅供参考,这里正在工作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);