Как уменьшить когнитивную сложность этого кода на основе цикломатической сложности Томаса Дж. Маккейба

Я знаю, что есть если, то еще и свитч.

Но приведенный ниже код представляет собой смесь if, then else, else if, else.

@HostListener('document:keydown', ['$event'])
onKeydown(event: KeyboardEvent) {
  let index = 0;
  if (this.selectedItemIndex === null || this.selectedItemIndex < 0) {
    this.changeAria.emit('showall');
  } else {
    if ((event.key === 'ArrowDown' || event.key === 'Down') && this.isFocused) {
      index = this.selectedItemIndex;
      this.inputRef.nativeElement.getAttribute('aria-activedescendant');

      if (index >= 0 && index <= this.filteredItems.length - 1) {
        this.inputRef.nativeElement.value = this.filteredItems[index];
      }
    } else if ((event.key === 'ArrowUp' || event.key === 'Up') && this.isFocused) {
      index = this.selectedItemIndex - 2;
      this.inputRef.nativeElement.getAttribute('aria-activedescendant');
      if (index >= 0 && index <= this.filteredItems.length - 1) {
        this.inputRef.nativeElement.value = this.filteredItems[index];
      }
    } else if (index !== null && index >= 0) {
      this.changeAria.emit(this.filteredItems[index]);
    }
  }
  if (event.key === 'Enter' && this.isFocused && this.selectedItemIndex > 0) {
    if (this.selectedItemIndex === 0) {
      event.preventDefault();
      const item = (this.filter !== undefined && this.filter !== null && this.filter !== '') ? this.filter : '';
      this.onItemSelect(null, item);
    } else if (this.selectedItemIndex > 0) {
      event.preventDefault();
      this.onItemSelect(null, this.filteredItems[this.selectedItemIndex - 1]);
    }
  } else if ((event.key === 'ArrowUp' || event.key === 'Up') && this.isFocused) {
    event.preventDefault();
    if (this.selectedItemIndex === null || this.selectedItemIndex === 0) {
      this.selectedItemIndex = this.filteredItems.length;
    } else {
      if (this.selectedItemIndex > 0) {
        this.selectedItemIndex--;
      }
    }
  } else if ((event.key === 'ArrowDown' || event.key === 'Down') && this.isFocused) {
    event.preventDefault();
    if (this.selectedItemIndex === null) {
      this.selectedItemIndex = 0;
    } else {
      if (this.selectedItemIndex >= 0 && this.selectedItemIndex < this.filteredItems.length) {
        this.selectedItemIndex++;
      } else {
        this.selectedItemIndex = 0;
      }
    }
  } else if ((event.keyCode == 27) && this.isFocused) {
    this.clearFocus();
    this.inputRef.nativeElement.focus();
  }
}

Я знаю, что это можно уменьшить.

Я хочу сократить это число до наименьшего общего знаменателя, чтобы этот блок кода было намного легче читать и лучше оптимизировать.

ОБНОВЛЕНИЕ: вот мое сокращение кода

  /**
   * @name: checkForSelected
   * @description: Checks for Selected Index
   * @argument: NONE
   * @returns: boolean - meaning: there's no selected index found
   */
  checkForSelected(): boolean {
    if (this.selectedItemIndex === null || this.selectedItemIndex < 0) {
      this.hasNothingSelected = false;
    }
    return this.hasNothingSelected;
  }

  /**
   * @name: checkForArrowDnUp
   * @description: Checks for Arrow is up or down and has focused
   * @param event as ANY
   * @returns: boolean - meaning, whether the arrow is up or down 'and' focused
   */
  checkForArrowDnUp(event: KeyboardEvent): boolean {
    if ((event.key === 'ArrowDown' || event.key === 'Down') && this.isFocused) {
      this.arrowDnKeyDn = true;
    } else if ((event.key === 'ArrowUp' || event.key === 'Up') && this.isFocused) {
      this.arrowDnKeyDn = false;
    }
    return this.arrowDnKeyDn;
  }

  /**
   * @name: checkForNullOrZero
   * @description: Checks for index being NULL or ZERO
   * @param index
   * @returns: boolean - Meaning, yes index is null OR Zero or greater than ZERO
   */
  checkForNullOrZero(index: number): boolean {

    this.isNdxNullOrZero = false;

    if (index !== null && index >= 0) {
      this.isNdxNullOrZero = true;
    }

    return this.isNdxNullOrZero;
  }

  /**
   * @name: checkForEnterKeyUpDn
   * @description: Checks for keyboard event if the user PRESSES the ENTER KEY
   * @param event
   * @returns: boolean - Meaning, YES the user has indeed pressed the ENTER KEY
   * @default: variable DEFAULTS to FALSE
   */
  checkForEnterKeyUpDn(event: KeyboardEvent): boolean {

    this.isEnterKeyUpDn = false;

    if (event.key === 'Enter' && this.isFocused && this.selectedItemIndex > 0) {
      this.isEnterKeyUpDn = true;
    }
    return this.isEnterKeyUpDn;
  }

  /**
   * @name: checkForSelectedItemIndexFiltered
   * @description: Checks if the selected item has been filtered to a specific item index or not
   * @param: NONE
   * @returns: boolean - Meaning, YES the selected item has indeed been filter
   * @default: variable DEFAULTS to FALSE
   */
  checkForSelectedItemIndexFiltered(): boolean {

    this.isSelectedItemNdxFoundFiltered = false;

    if (this.selectedItemIndex >= 0 && this.selectedItemIndex < this.filteredItems.length) {
      this.selectedItemIndex++;
    } else {
      this.selectedItemIndex = 0;
    }
    return this.isSelectedItemNdxFoundFiltered;
  }


  checkForKeyEscape(event: KeyboardEvent): boolean {
    this.isKeyDnUpEscape = false;
    if ((event.key === 'Escape') && this.isFocused) {
      this.isKeyDnUpEscape = true;
    }
    return this.isKeyDnUpEscape;
  }

  onKeydown(event: KeyboardEvent) {

    const item = (this.filter !== undefined && this.filter !== null && this.filter !== '') ? this.filter : '';
    let index = 0;
    let nothingSelected = this.checkForSelected;
    let enterKeyUpDn = this.checkForEnterKeyUpDn(event);
    let arrowDnKeyUpDn = this.checkForArrowDnUp(event);
    let indexNullOrZero = this.checkForNullOrZero(index);
    let selectedItemNdxFiltered = this.checkForSelectedItemIndexFiltered();
    let keyIsEscape = this.checkForKeyEscape(event);

    if (nothingSelected) {
      this.changeAria.emit('showall');
    } else {
      if (arrowDnKeyUpDn) {
        index = this.selectedItemIndex;
        this.inputRef.nativeElement.getAttribute('aria-activedescendant');
        if (index >= 0 && index <= this.filteredItems.length - 1) {
          this.inputRef.nativeElement.value = this.filteredItems[index];
        }
      } else if (!arrowDnKeyUpDn) {
        index = this.selectedItemIndex - 2;
        this.inputRef.nativeElement.getAttribute('aria-activedescendant');
        if (index >= 0 && index <= this.filteredItems.length - 1) {
          this.inputRef.nativeElement.value = this.filteredItems[index];
        }
      } else if (indexNullOrZero) {
        this.changeAria.emit(this.filteredItems[index]);
      }
    }

    if (enterKeyUpDn) {
      event.preventDefault();

      this.enterKeyUpDown(item);

      // switch(true) {
      //   case this.selectedItemIndex === 0:
      //     this.onItemSelect(null, item);
      //     break;
      //   case this.selectedItemIndex > 0:
      //     this.onItemSelect(null, this.filteredItems[this.selectedItemIndex - 1]);
      //     break;
      //   default:
      //     false;
      //     break;
      // }

      // if (this.selectedItemIndex === 0) {
      //   this.onItemSelect(null, item);
      // } else if (this.selectedItemIndex > 0) {
      //   this.onItemSelect(null, this.filteredItems[this.selectedItemIndex - 1]);
      // }
    } else if (arrowDnKeyUpDn) {
      event.preventDefault();

      this.arrowDownKeyUpDown();

      // switch(true) {
      //   case this.selectedItemIndex === null || this.selectedItemIndex === 0:
      //     this.selectedItemIndex = this.filteredItems.length;
      //     break;
      //   default:
      //     if (this.selectedItemIndex > 0) {
      //       this.selectedItemIndex--;
      //     }
      //     false;
      //     break;
      // }

      // if (this.selectedItemIndex === null || this.selectedItemIndex === 0) {
      //   this.selectedItemIndex = this.filteredItems.length;
      // } else {
      //   if (this.selectedItemIndex > 0) {
      //     this.selectedItemIndex--;
      //   }
      // }
    } else if (!arrowDnKeyUpDn) {
      event.preventDefault();

      this.notArrowDownKeyUpDown(selectedItemNdxFiltered);

      // switch(true) {
      //   case this.selectedItemIndex === null:
      //     this.selectedItemIndex = 0;
      //     break;
      //   default:
      //     if (selectedItemNdxFiltered) {
      //       this.selectedItemIndex++;
      //     } else {
      //       this.selectedItemIndex = 0;
      //     }
      //     false;
      //     break;
      // }

      // if (this.selectedItemIndex === null) {
      //   this.selectedItemIndex = 0;
      // } else {
      //   if (selectedItemNdxFiltered) {
      //     this.selectedItemIndex++;
      //   } else {
      //     this.selectedItemIndex = 0;
      //   }
      // }
    } else if (keyIsEscape) {
      this.clearFocus();
      this.inputRef.nativeElement.focus();
    }
  }

  enterKeyUpDown(item: string): void {
    switch(true) {
      case this.selectedItemIndex === 0:
        this.onItemSelect(null, item);
        break;
      case this.selectedItemIndex > 0:
        this.onItemSelect(null, this.filteredItems[this.selectedItemIndex - 1]);
        break;
      default:
        false;
        break;
    }
  }

  arrowDownKeyUpDown() {
    switch(true) {
      case this.selectedItemIndex === null || this.selectedItemIndex === 0:
        this.selectedItemIndex = this.filteredItems.length;
        break;
      default:
        if (this.selectedItemIndex > 0) {
          this.selectedItemIndex--;
        }
        false;
        break;
    }
  }

  notArrowDownKeyUpDown(selectedItemNdxFiltered: boolean) {
    switch(true) {
      case this.selectedItemIndex === null:
        this.selectedItemIndex = 0;
        break;
      default:
        if (selectedItemNdxFiltered) {
          this.selectedItemIndex++;
        } else {
          this.selectedItemIndex = 0;
        }
        false;
        break;
    }
  }

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *