pavlitsky/vscode-yard

View on GitHub
src/renderers/snippet_string/spacer_helper.ts

Summary

Maintainability
B
5 hrs
Test Coverage
"use strict";
import { SnippetString, workspace, WorkspaceConfiguration } from "vscode";
import { Tag } from "../../entities/tag";
import { IEntity } from "../../types";

// Helper class to manage empty lines of a snippet
export class SpacerHelper {
  private lastTag = undefined;
  private isFirstTag: boolean = false;
  private isFirstTagInGroup: boolean = false;
  private isTag: boolean = false;
  private isText: boolean = false;
  private tagsCount: number = 0;
  private isSingleEntity: boolean = false;
  private isLastEntity: boolean = false;
  private isSingleTag: boolean = false;

  private config: WorkspaceConfiguration;

  constructor(private snippet: SnippetString, private eol: string) {
    this.config = workspace.getConfiguration("yard.spacers");
  }

  // Prepend empty line to an entity if needed
  public beforeEntity(entity: IEntity, entities: IEntity[], index: number) {
    this.updateContext(entity, entities, index);

    const beforeDescription = this.isText;
    const beforeTags = this.isFirstTag && !this.isSingleTag;
    const separateTags = !this.isFirstTag && this.isFirstTagInGroup && !this.isSingleEntity;
    const beforeSingleTag = this.isSingleTag;

    if (
      (beforeDescription && this.config.get("beforeDescription")) ||
      (beforeTags && this.config.get("beforeTags")) ||
      (separateTags && this.config.get("separateTags")) ||
      (beforeSingleTag && this.config.get("beforeSingleTag"))
    ) {
      this.endOfLine();
    }
  }

  // Append empty line to an entity if needed
  public afterEntity() {
    const afterDescription = this.isText;
    const afterTags = this.isTag && (!this.isSingleEntity && this.isLastEntity);
    const afterSingleTag = this.isSingleTag;

    if (
      (afterDescription && this.config.get("afterDescription")) ||
      (afterTags && this.config.get("afterTags")) ||
      (afterSingleTag && this.config.get("afterSingleTag"))
    ) {
      this.endOfLine();
    }
  }

  // Append spaced string
  public spacedText(text: string) {
    if (text) { this.snippet.appendText(" " + text); }
  }

  // Append empty line to a snippet
  public endOfLine() {
    this.snippet.appendText(this.eol);
  }

  // Update context parameters for a current entity
  private updateContext(entity: IEntity, entities: IEntity[], index: number) {
    this.isTag = entity instanceof Tag;
    this.isText = entity.type === "Text";
    this.isLastEntity = entities.length - 1 === index;
    this.isSingleEntity = entities.length === 1;

    if (this.isTag) {
      const tag: Tag = entity;
      if (this.lastTag) {
        this.isFirstTagInGroup = tag.tagName !== this.lastTag.tagName;
      } else {
        this.isFirstTagInGroup = true;
      }
      this.isFirstTag = this.tagsCount === 0;
      this.isSingleTag = this.isSingleEntity;
      this.tagsCount += 1;
      this.lastTag = entity;
    } else {
      this.isFirstTag = false;
      this.isFirstTagInGroup = false;
      this.isSingleTag = false;
      this.lastTag = undefined;
    }
  }
}