Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate from Vega-lite Spec #21

Open
lan-lyu opened this issue Jul 11, 2023 · 4 comments
Open

Generate from Vega-lite Spec #21

lan-lyu opened this issue Jul 11, 2023 · 4 comments
Labels

Comments

@lan-lyu
Copy link
Collaborator

lan-lyu commented Jul 11, 2023

I used type checker and AST node to parse from vega-lite/src/spec/index.ts, and begin from this:

export type TopLevelSpec =
  | TopLevelUnitSpec<Field>
  | TopLevelFacetSpec
  | TopLevel<LayerSpec<Field>>
  | TopLevel<RepeatSpec>
  | TopLevel<GenericConcatSpec<NonNormalizedSpec>>
  | TopLevel<GenericVConcatSpec<NonNormalizedSpec>>
  | TopLevel<GenericHConcatSpec<NonNormalizedSpec>>;

Now it can parse the type inheritance like this (full text)

############### TopLevelUnitSpec<Field> ###############
####### TopLevelUnitSpec<Field> #######
- TopLevelUnitSpec<Field>
-- GenericUnitSpec<FacetedCompositeEncoding<Field>, AnyMark, TopLevelParameter>
-- ResolveMixins
-- GenericCompositionLayout
-- FrameMixins<any>
-- TopLevelProperties<any>
-- { $schema?: string; config?: Config<any>; datasets?: Datasets; usermeta?: Dict<unknown>; }
-- DataMixins
####### Field #######
- Field
-- string
-- RepeatRef

and get properties in these types (full text)

############### TopLevelUnitSpec<Field> ###############
####### TopLevelUnitSpec<Field> #######
### mark ###
### encoding ###
### projection ###
### params ###
### title ###
### name ###
### description ###
### data ###
### transform ###
### resolve ###
### align ###
### center ###
### spacing ###
### bounds ###
### view ###
### width ###
### height ###
### background ###
### padding ###
### autosize ###
### $schema ###
### config ###
### datasets ###
### usermeta ###
####### Field #######
### toString ###
### valueOf ###
### repeat ###

And types in each property such as mark (full text)

############### TopLevelUnitSpec<Field> ###############
####### TopLevelUnitSpec<Field> #######
### mark ###
AnyMark
"boxplot"
"errorbar"
"errorband"
BoxPlotDef
ErrorBarDef
ErrorBandDef
"arc"
"area"
"bar"
"image"
"line"
"point"
"rect"
"rule"
"text"
"tick"
"trail"
"circle"
"square"
"geoshape"
MarkDef<"arc" | "area" | "bar" | "image" | "line" | "point" | "rect" | "rule" | "text" | "tick" | "trail" | "circle" | "square" | "geoshape", any>

The code is in

if(statement.name.getText() === "TopLevelSpec") {

@lan-lyu lan-lyu added the update label Jul 11, 2023
@lan-lyu
Copy link
Collaborator Author

lan-lyu commented Jul 19, 2023

Recursively get the types and properties (code)

And generate a rough mark example directly from the types (text)

@lan-lyu
Copy link
Collaborator Author

lan-lyu commented Jul 26, 2023

Vega-lite-api is using FacetedEncoding for generating encoding channels. While FacetedEncoding is in json-schema, it's not in vega-lite src types.
Is it because this json-schema is not updated with the types? If not, how does json-schema-generator come up with FacetedEncoding? @domoritz

@domoritz
Copy link
Member

There is a rename step because the names from the generator were not what we wanted: https://github.com/vega/vega-lite/blob/main/scripts/rename-schema.sh

@lan-lyu
Copy link
Collaborator Author

lan-lyu commented Jul 26, 2023

This week's update:

Auto-generate files from typescript types

The generation logic is from vega-lite-api constants. When I meet a 'TopLevelUnitSpec', I generate mark and data.

  mark:     'TopLevelUnitSpec',
  layer:    'TopLevelLayerSpec',
  concat:   'TopLevelConcatSpec',
  hconcat:  'TopLevelHConcatSpec',
  vconcat:  'TopLevelVConcatSpec',
  _repeat:  'TopLevelRepeatSpec',
  _facet:   'TopLevelFacetSpec',
  spec:     'TopLevelSpec',
  data:     'TopLevelUnitSpec',

In this way, as long as we have a well-defined constant, all codes can be generated. But will that influence the maintainability of the code?

  • check if the generation logic is okay

Create Internal Representation (In Process)

Now when generating, the types still have inheritances, for example, boolean | RowCol<boolean> as shown below.

  center(value: boolean | RowCol<boolean>) {
    if (arguments.length) {
      const obj = copy(this);
      set(obj, "center", value);
      return obj;
    } else {
      return get(this, "center");
    }
  }

To solve this, I plan to have a class that stores the inheritance through children's classes so that we can get the oneLevelType from children's oneLevelType.

// internal representation of a type
class VegaLiteType {
    name: string;
    type: ts.Type;
    kind: TypeKind;
    children: VegaLiteType[];
    oneLevelType: string;
    properties?: ts.Type[];
    description?: string;   //TODO: get descirption and generate documentation

    constructor(name: string, type: ts.Type, kind: TypeKind, children: VegaLiteType[]) {
        this.name = name;
        this.type = type;
        this.kind = kind;
        this.children = children;
        // this.oneLevelType = this.updateOneLevelType();
        this.properties = (type as any).properties;
    }

    generateOneLevelType(): string {
        switch (this.kind) {
            case TypeKind.Union:
                return this.children.map(child => child.generateOneLevelType()).join(" | ");
            case TypeKind.Intersection:
                return this.children.map(child => child.generateOneLevelType()).join(" & ");
            case TypeKind.Literal:
                return this.name;
            case TypeKind.TypeParameter:
                return this.name;
            case TypeKind.Other:
                return this.name;
        }
    }

    updateOneLevelType(): void {
        this.oneLevelType = this.generateOneLevelType();
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants