google / flatbuffers

FlatBuffers: Memory Efficient Serialization Library

Home Page:https://flatbuffers.dev/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[TS] --ts-flat-file generates self-imports

jkuszmaul opened this issue · comments

Since as far as I know I'm the only user currently and it doesn't block me yet, just creating this ticket for documentation purposes.

If you pass --ts-flat-file to flatc when generating typescript code, you will get some self-imports in certain cases. E.g., the below code gets generated for typescript_keywords.fbs. This happens because we generate imports for any types used as fields of other types in the file, whether or not they are in the same file, because I couldn't be bothered to add the complexity to #7161.

import * as flatbuffers from 'flatbuffers';
import {Schema as reflectionSchema, SchemaT as reflectionSchemaT} from  './../reflection/reflection_generated';
import {class_ as foobarclass_} from  './test_dir/typescript_include_generated';
import {Abc as foobarAbc} from  './test_dir/typescript_transitive_include_generated';
import {Object_ as typescriptObject, ObjectT as typescriptObjectT, class_ as typescriptclass_} from  './typescript_keywords_generated';


export enum class_{
  new_ = 0,
  instanceof_ = 1
}

export class Object_ {
  bb: flatbuffers.ByteBuffer|null = null;
  bb_pos = 0;
__init(i:number, bb:flatbuffers.ByteBuffer):Object_ {
  this.bb_pos = i;
  this.bb = bb;
  return this;
}

static getRootAsObject(bb:flatbuffers.ByteBuffer, obj?:Object_):Object_ {
  return (obj || new Object_()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
}

static getSizePrefixedRootAsObject(bb:flatbuffers.ByteBuffer, obj?:Object_):Object_ {
  bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
  return (obj || new Object_()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
}

return():number {
  const offset = this.bb!.__offset(this.bb_pos, 4);
  return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
}

mutate_return(value:number):boolean {
  const offset = this.bb!.__offset(this.bb_pos, 4);

  if (offset === 0) {
    return false;
  }

  this.bb!.writeInt32(this.bb_pos + offset, value);
  return true;
}

if():number {
  const offset = this.bb!.__offset(this.bb_pos, 6);
  return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
}

mutate_if(value:number):boolean {
  const offset = this.bb!.__offset(this.bb_pos, 6);

  if (offset === 0) {
    return false;
  }

  this.bb!.writeInt32(this.bb_pos + offset, value);
  return true;
}

switch():number {
  const offset = this.bb!.__offset(this.bb_pos, 8);
  return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
}

mutate_switch(value:number):boolean {
  const offset = this.bb!.__offset(this.bb_pos, 8);

  if (offset === 0) {
    return false;
  }

  this.bb!.writeInt32(this.bb_pos + offset, value);
  return true;
}

enum():typescriptclass_ {
  const offset = this.bb!.__offset(this.bb_pos, 10);
  return offset ? this.bb!.readInt32(this.bb_pos + offset) : typescriptclass_.new_;
}

mutate_enum(value:typescriptclass_):boolean {
  const offset = this.bb!.__offset(this.bb_pos, 10);

  if (offset === 0) {
    return false;
  }

  this.bb!.writeInt32(this.bb_pos + offset, value);
  return true;
}

enum2():foobarclass_ {
  const offset = this.bb!.__offset(this.bb_pos, 12);
  return offset ? this.bb!.readInt32(this.bb_pos + offset) : foobarclass_.arguments;
}

mutate_enum2(value:foobarclass_):boolean {
  const offset = this.bb!.__offset(this.bb_pos, 12);

  if (offset === 0) {
    return false;
  }

  this.bb!.writeInt32(this.bb_pos + offset, value);
  return true;
}

enum3():foobarAbc {
  const offset = this.bb!.__offset(this.bb_pos, 14);
  return offset ? this.bb!.readInt32(this.bb_pos + offset) : foobarAbc.a;
}

mutate_enum3(value:foobarAbc):boolean {
  const offset = this.bb!.__offset(this.bb_pos, 14);

  if (offset === 0) {
    return false;
  }

  this.bb!.writeInt32(this.bb_pos + offset, value);
  return true;
}

reflect(obj?:reflectionSchema):reflectionSchema|null {
  const offset = this.bb!.__offset(this.bb_pos, 16);
  return offset ? (obj || new reflectionSchema()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
}

static getFullyQualifiedName():string {
  return 'typescript.Object';
}

static startObject(builder:flatbuffers.Builder) {
  builder.startObject(7);
}

static addReturn(builder:flatbuffers.Builder, return_:number) {
  builder.addFieldInt32(0, return_, 0);
}

static addIf(builder:flatbuffers.Builder, if_:number) {
  builder.addFieldInt32(1, if_, 0);
}

static addSwitch(builder:flatbuffers.Builder, switch_:number) {
  builder.addFieldInt32(2, switch_, 0);
}

static addEnum(builder:flatbuffers.Builder, enum_:typescriptclass_) {
  builder.addFieldInt32(3, enum_, typescriptclass_.new_);
}

static addEnum2(builder:flatbuffers.Builder, enum2:foobarclass_) {
  builder.addFieldInt32(4, enum2, foobarclass_.arguments);
}

static addEnum3(builder:flatbuffers.Builder, enum3:foobarAbc) {
  builder.addFieldInt32(5, enum3, foobarAbc.a);
}

static addReflect(builder:flatbuffers.Builder, reflectOffset:flatbuffers.Offset) {
  builder.addFieldOffset(6, reflectOffset, 0);
}

static endObject(builder:flatbuffers.Builder):flatbuffers.Offset {
  const offset = builder.endObject();
  return offset;
}


unpack(): ObjectT {
  return new ObjectT(
    this.return(),
    this.if(),
    this.switch(),
    this.enum(),
    this.enum2(),
    this.enum3(),
    (this.reflect() !== null ? this.reflect()!.unpack() : null)
  );
}


unpackTo(_o: ObjectT): void {
  _o.return_ = this.return();
  _o.if_ = this.if();
  _o.switch_ = this.switch();
  _o.enum_ = this.enum();
  _o.enum2 = this.enum2();
  _o.enum3 = this.enum3();
  _o.reflect = (this.reflect() !== null ? this.reflect()!.unpack() : null);
}
}

export class ObjectT {
constructor(
  public return_: number = 0,
  public if_: number = 0,
  public switch_: number = 0,
  public enum_: typescriptclass_ = typescriptclass_.new_,
  public enum2: foobarclass_ = foobarclass_.arguments,
  public enum3: foobarAbc = foobarAbc.a,
  public reflect: reflectionSchemaT|null = null
){}


pack(builder:flatbuffers.Builder): flatbuffers.Offset {
  const reflect = (this.reflect !== null ? this.reflect!.pack(builder) : 0);

  typescriptObject.startObject(builder);
  typescriptObject.addReturn(builder, this.return_);
  typescriptObject.addIf(builder, this.if_);
  typescriptObject.addSwitch(builder, this.switch_);
  typescriptObject.addEnum(builder, this.enum_);
  typescriptObject.addEnum2(builder, this.enum2);
  typescriptObject.addEnum3(builder, this.enum3);
  typescriptObject.addReflect(builder, reflect);

  return typescriptObject.endObject(builder);
}
}

The self referencing might be related to #7190.

No, this is a distinct issue. I was lazy in writing the code and basically made the flat file be generated approximately by concatenating the original files. Which also meant doing all the same imports, but now rather than imports of other files they are imports of the same file. #7190 actually doesn't apply to flat-file generation at all, because for the flat files we don't need the summary file.

Will --ts-flat-file give us an easy way to create an index.d.ts for the entire resulting TS API via tsc?

In other words, something we can put in the types property of a package.json:

"types": "./dist/index.d.ts",

It depends on what you mean by "the entire resulting TS API". --ts-flat-fileis specifically meant for allowing there to be a 1-1 correspondence between schema (.fbs) files and generated typescript files. If you have multiple schema files, it's not going to give you just one file.

If you do have multiple schema files and want to generate everything in the same folder structure at once, you may be interested in the --gen-all flag without --ts-flat-file (I haven't made the two work together). I am not familiar enough with tsc to know what may options exist for making declaration files from multiple files.