IanVS / prettier-plugin-sort-imports

An opinionated but flexible prettier plugin to sort import statements
Apache License 2.0
1.02k stars 25 forks source link

TypeError: Cannot read properties of undefined (reading 'buildError') #139

Closed vincerubinetti closed 11 months ago

vincerubinetti commented 11 months ago

Your Environment

Describe the bug

See error log below.

To Reproduce

This is the file I'm trying to format. Still trying to narrow down what is tripping up the plugin.

import { FaFilter, FaSort, FaSortDown, FaSortUp } from "react-icons/fa6";
import {
  Column,
  ColumnDef,
  createColumnHelper,
  flexRender,
  getCoreRowModel,
  getFacetedMinMaxValues,
  getFacetedRowModel,
  getFacetedUniqueValues,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  RowData,
  Table,
  useReactTable,
} from "@tanstack/react-table";
import Popover from "@/components/Popover";
import Slider from "@/components/Slider";
import TextBox from "@/components/TextBox";
import classes from "./Table.module.css";

type Props<Datum extends object> = {
  cols: {
    /** key of row object to access as value */
    key: keyof Datum;
    /** label for header */
    name: string;
    /** is sortable (default true) */
    sortable?: boolean;
    /** is filterable (default true) */
    filterable?: boolean;
    /** type used for sorting/filtering (default string) */
    type?: "string" | "number";
  }[];
  rows: Datum[];
};

/** https://tanstack.com/table/v8/docs/api/core/column-def#meta */
declare module "@tanstack/table-core" {
  interface ColumnMeta<TData extends RowData, TValue> {
    type: NonNullable<Props<object>["cols"][number]["type"]>;
  }
}

/**
 * reference:
 * https://codesandbox.io/p/devbox/tanstack-table-example-kitchen-sink-vv4871
 */
const Table = <Datum extends object>({ cols, rows }: Props<Datum>) => {
  const columnHelper = createColumnHelper<Datum>();

  /** column definitions */
  const columns = cols.map((col) =>
    columnHelper.accessor((row: Datum) => row[col.key], {
      header: col.name,
      enableSorting: col.sortable ?? true,
      enableColumnFilter: col.filterable ?? true,
      meta: { type: col.type ?? "string" },
    }),
  );

  /** tanstack table api */
  const table = useReactTable({
    data: rows,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFacetedRowModel: getFacetedRowModel(),
    getFacetedUniqueValues: getFacetedUniqueValues(),
    getFacetedMinMaxValues: getFacetedMinMaxValues(),
    // onColumnFiltersChange: setColumnFilters,
    // onGlobalFilterChange: setGlobalFilter,
    // globalFilterFn: fuzzyFilter,
    autoResetPageIndex: true,
    // enableColumnResizing: true,
    columnResizeMode: "onChange",
    // onColumnVisibilityChange: setColumnVisibility,
    // Provide our updateData function to our table meta
    state: {
      // columnFilters,
      // globalFilter,
      // columnVisibility,
    },
    // debugTable: true,
    // debugHeaders: true,
    // debugColumns: true,
  });

  console.log(table.getHeaderGroups());

  return (
    <table>
      <thead>
        {table.getHeaderGroups().map((headerGroup) => (
          <tr key={headerGroup.id}>
            {headerGroup.headers.map((header) => (
              <th key={header.id} style={{ width: header.getSize() }}>
                {header.isPlaceholder ? null : (
                  <div className={classes.th}>
                    {flexRender(
                      header.column.columnDef.header,
                      header.getContext(),
                    )}
                    <button
                      className={classes.button}
                      data-active={header.column.getIsSorted() ? "" : undefined}
                      onClick={header.column.getToggleSortingHandler()}
                    >
                      {header.column.getIsSorted() ? (
                        header.column.getIsSorted() === "asc" ? (
                          <FaSortUp />
                        ) : (
                          <FaSortDown />
                        )
                      ) : (
                        <FaSort />
                      )}
                    </button>
                    {header.column.getCanFilter() ? (
                      <Popover
                        label={`Filter "${header.column.columnDef.header}"`}
                        content={
                          <Filter table={table} column={header.column} />
                        }
                      >
                        <button>
                          <FaFilter />
                        </button>
                      </Popover>
                    ) : null}
                  </div>
                )}
              </th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody>
        {table.getRowModel().rows.map((row) => (
          <tr key={row.id}>
            {row.getVisibleCells().map((cell) => (
              <td key={cell.id} style={{ width: cell.column.getSize() }}>
                {flexRender(cell.column.columnDef.cell, cell.getContext())}
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
};

export default Table;

type FilterProps<Datum extends object> = {
  column: Column<Datum, unknown>;
  table: Table<Datum>;
};

/** content of filter popup for column */
const Filter = <Datum extends object>({
  column,
  table,
}: FilterProps<Datum>) => {
  if (column.columnDef.meta?.type === "number") {
    const [min = 0, max = 100] = column.getFacetedMinMaxValues() || [];

    return <Slider min={min} max={max} multi={true} value={[min, max]} />;
  }

  return <TextBox placeholder="Search" />;
};

Configuration File (cat .prettierrc, prettier.config.js, .prettier.js)

I have tried removing the other plugins, and there is no effect. If I remove just this plugin, prettier is able to format the document.

{
  "plugins": [
    "@ianvs/prettier-plugin-sort-imports",
    "./node_modules/prettier-plugin-jsdoc/dist/index.js",
    "prettier-plugin-css-order"
  ],
  "importOrder": [
    "^react",
    "^[a-zA-Z]",
    "^@[a-zA-Z]",
    "^@/",
    "^/",
    "^./",
    "^../"
  ],
  "cssDeclarationSorterOrder": "smacss",
  "jsdocCapitalizeDescription": false,
  "htmlWhitespaceSensitivity": "strict"
}

Error log

["INFO" - 1:44:05 PM] Formatting file:///Users/vincerubinetti/Desktop/gene-plexus/app/src/components/Table.tsx
["INFO" - 1:44:05 PM] Using config file at '/Users/vincerubinetti/Desktop/gene-plexus/app/.prettierrc'
["INFO" - 1:44:05 PM] PrettierInstance:
{
  "modulePath": "/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/prettier/index.cjs",
  "importResolver": {},
  "callMethodResolvers": {},
  "currentCallMethodId": 6,
  "version": "3.1.0"
}
["INFO" - 1:44:05 PM] Using ignore file (if present) at /Users/vincerubinetti/Desktop/gene-plexus/.prettierignore
["INFO" - 1:44:05 PM] File Info:
{
  "ignored": false,
  "inferredParser": "typescript"
}
["INFO" - 1:44:05 PM] Detected local configuration (i.e. .prettierrc or .editorconfig), VS Code configuration will not be used
["INFO" - 1:44:05 PM] Prettier Options:
{
  "filepath": "/Users/vincerubinetti/Desktop/gene-plexus/app/src/components/Table.tsx",
  "parser": "typescript",
  "plugins": [
    "/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@ianvs/prettier-plugin-sort-imports/lib/src/index.js",
    "/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/prettier-plugin-jsdoc/dist/index.js",
    "/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/prettier-plugin-css-order/src/main.mjs"
  ],
  "importOrder": [
    "^react",
    "^[a-zA-Z]",
    "^@[a-zA-Z]",
    "^@/",
    "^/",
    "^./",
    "^../"
  ],
  "cssDeclarationSorterOrder": "smacss",
  "jsdocCapitalizeDescription": false,
  "htmlWhitespaceSensitivity": "strict"
}
["ERROR" - 1:44:05 PM] Error formatting document.
["ERROR" - 1:44:05 PM] Cannot read properties of undefined (reading 'buildError')
TypeError: Cannot read properties of undefined (reading 'buildError')
    at Scope.checkBlockScopedCollisions (/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@babel/traverse/lib/scope/index.js:399:22)
    at Scope.registerBinding (/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@babel/traverse/lib/scope/index.js:535:16)
    at Scope.registerDeclaration (/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@babel/traverse/lib/scope/index.js:487:14)
    at Object.BlockScoped (/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@babel/traverse/lib/scope/index.js:254:12)
    at Object.newFn (/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@babel/traverse/lib/visitors.js:195:17)
    at NodePath._call (/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@babel/traverse/lib/path/context.js:46:20)
    at NodePath.call (/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@babel/traverse/lib/path/context.js:32:14)
    at NodePath.visit (/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@babel/traverse/lib/path/context.js:82:31)
    at TraversalContext.visitQueue (/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@babel/traverse/lib/context.js:86:16)
    at TraversalContext.visitMultiple (/Users/vincerubinetti/Desktop/gene-plexus/app/node_modules/@babel/traverse/lib/context.js:61:17)
["INFO" - 1:44:05 PM] Formatting completed in 11ms.

Contribute to @ianvs/prettier-plugin-sort-imports

vincerubinetti commented 11 months ago

Hmm, it looks like it 's because of the lack of type before the import { Table }, interesting! It's probably getting confused since Table already exists as a value (as opposed to a type) in the scope. Not sure this is a really a bug, it's definitely my mistake. But perhaps it'd be good to guard against this somehow?

a-somani commented 11 months ago

i've been using it no problem for a week till today where i got the same error ["ERROR" - 5:55:13 PM] Cannot read properties of undefined (reading 'buildError') TypeError: Cannot read properties of undefined (reading 'buildError')

I also get the error with trivago's package. https://github.com/trivago/prettier-plugin-sort-imports/issues/228

IanVS commented 11 months ago

@a-somani there is probably a syntax error in your file.

@vincerubinetti I'd be happy to review a PR if you'd like to try adding a nicer error message!

a-somani commented 11 months ago

this is my .prettierrc.json

{
  "plugins": ["@ianvs/prettier-plugin-sort-imports"],
  "importOrder": [
    "<BUILTIN_MODULES>",
    "^react($|/)",
    "^react-dom($|/)",
    "^next($|/)",
    "<THIRD_PARTY_MODULES>",
    "",
    "^@(styles|interfaces|services|components|lib|utils|artifacts|contracts|pages|hooks|layout|middleware|schemas|shared|contexts)($|/).*",
    "^[./]"
  ],
  "importOrderSeparation": true,
  "importOrderSortSpecifiers": true
}

i have not changed it since i used it last week when it was working. perhaps there was a vscode update or just the prettier vscode extension?

IanVS commented 11 months ago

This is not a problem in the plugin or prettier, it's a problem somewhere in the file that you are trying to format.

a-somani commented 11 months ago

do you know if theres an easier way to debug prettier in my file? im not sure whats causing Cannot read properties of undefined (reading 'buildError')

IanVS commented 11 months ago

Is it a TypeScript file? If so, you can try compiling it with tsc and see if it gives you an error. Or, try deleting one import at a time until the error goes away, and then you'll know which one it was.

a-somani commented 11 months ago

I fixed it! I had named my react component the same as one of my imports. i resolved it by commenting out 1 line at a time till my prettier vscode plugin was no longer red. also found help with using yarn prettier */.tsx --check

vincerubinetti commented 11 months ago

Closing because it's unfortunately unlikely i'll have the time to be able to dive in and figure out what to change and how.