private buildSheet()

in frontend/libs/parser/src/lib/SheetReader.ts [140:310]


  private buildSheet(ctx: SheetContext) {
    const tables: ParsedTable[] = [];
    const pythonBlocks: PythonBlock[] = [];

    for (const pythonBlock of ctx.python_definition_list()) {
      const dslPlacement = getFullDSLPlacement(pythonBlock, true);

      if (!dslPlacement) continue;

      pythonBlocks.push(new PythonBlock(dslPlacement));
    }

    for (const tableCtx of ctx.table_definition_list()) {
      const fields: ParsedField[] = [];
      const tableNameCtx = tableCtx.table_name();

      if (!tableNameCtx) continue;

      const tableName = tableNameCtx.getText();
      const tableRange = getFullDSLPlacement(tableCtx);

      const tableNameRange = {
        start: tableNameCtx.start.start,
        end: tableNameCtx.start.start + tableName.length,
      };

      for (const fieldCtx of tableCtx.field_definition_list()) {
        const fieldNameCtx = fieldCtx.field_name();

        if (!fieldNameCtx) continue;

        const fieldName: string = fieldNameCtx.getText();
        let fieldExpression: ExpressionContext | undefined;
        let expressionMetadata: ExpressionMetadata | undefined;

        try {
          fieldExpression = fieldCtx.expression();

          if (fieldExpression) {
            const startIndex = fieldExpression.start.start;
            const end =
              fieldExpression.stop?.stop ||
              startIndex + fieldExpression.getText().length;

            const expressionText = SheetReader.sourceText.substring(
              startIndex,
              end + 1
            );

            expressionMetadata = {
              text: expressionText || fieldExpression.getText(),
              start: Math.min(startIndex, end),
              end: Math.max(startIndex, end),
            };
          }
        } catch (err) {
          // eslint-disable-next-line no-console
          console.error(err);
        }

        const dslFieldNamePlacement = getFieldNameDslPlacement(
          fieldNameCtx,
          fieldName
        );
        const dslFieldPlacement = getShortDSLPlacement(fieldCtx);
        const dimensionKeyword = fieldCtx.DIMENSION_KEYWORD();
        const keyKeyword = fieldCtx.KEY_KEYWORD();
        const dslDimensionPlacement = dimensionKeyword && {
          start: dimensionKeyword.symbol.start,
          end: dimensionKeyword.symbol.stop,
        };
        const dslKeyPlacement = keyKeyword && {
          start: keyKeyword.symbol.start,
          end: keyKeyword.symbol.stop,
        };

        const fieldNote: DSLNote = {
          text: '',
          start: 0,
          end: 0,
        };

        const docComment = fieldCtx.doc_comment_list();

        if (docComment.length > 0) {
          const firstDocComment = docComment[0];
          const lastDocComment = docComment.at(-1);

          fieldNote.start = firstDocComment.start.start;
          fieldNote.end = lastDocComment?.stop?.stop || fieldNote.start;

          docComment.forEach((i) => {
            fieldNote.text += i.getText();
          });
        }

        try {
          const field = new ParsedField(
            fieldCtx.KEY_KEYWORD() != null,
            fieldCtx.DIMENSION_KEYWORD() != null,
            false,
            new FieldKey(
              tableName,
              fieldName,
              SheetReader.stripQuotes(fieldName)
            ),
            fieldExpression && this.buildExpression(fieldExpression),
            expressionMetadata,
            dslFieldPlacement,
            dslFieldNamePlacement,
            dslDimensionPlacement,
            dslKeyPlacement,
            SheetReader.parseDecorators(fieldCtx.decorator_definition_list()),
            fieldNote.text ? fieldNote : undefined
          );

          fields.push(field);
        } catch (e) {
          // eslint-disable-next-line no-console
          console.error(e);
        }
      }

      const decorators = SheetReader.parseDecorators(
        tableCtx.decorator_definition_list()
      );
      const isManual = !!decorators.find(
        (decorator) => decorator.decoratorName === 'manual'
      );

      const overrideDefinition = tableCtx.override_definition();
      const keyFields = fields
        .filter((f) => f.isKey)
        .map((f) => f.key.fieldName);
      const overrides = this.parseOverrides(
        keyFields,
        isManual,
        overrideDefinition
      );
      const dslOverridePlacement = getFullDSLPlacement(
        overrideDefinition,
        true
      );
      const parsedApply: ParsedApply | undefined = this.parseApply(tableCtx);
      const parsedTotals: ParsedTotal | undefined = this.parseTotals(
        tableCtx,
        tableName
      );

      tables.push(
        new ParsedTable(
          tableName,
          fields,
          tableCtx.getText(),
          tableRange,
          tableNameRange,
          decorators,
          overrides,
          dslOverridePlacement,
          parsedApply,
          parsedTotals
        )
      );
    }

    return new ParsedSheet(
      tables,
      this.errorListener.getErrors(),
      pythonBlocks
    );
  }