@@ -7,13 +7,13 @@ import { marked } from "marked";
77import { filterProblems , problemAffectsEntrypoint , problemKindInfo } from "@arethetypeswrong/core/problems" ;
88import type { Opts } from "../index.js" ;
99import { moduleKinds , problemFlags , resolutionKinds } from "../problemUtils.js" ;
10- import { tableFlipped } from "./tableFlipped .js" ;
10+ import { asciiTable } from "./asciiTable .js" ;
1111import TerminalRenderer from "marked-terminal" ;
1212
1313export async function typed ( analysis : core . Analysis , opts : Opts ) {
1414 const problems = analysis . problems . filter ( ( problem ) => ! opts . ignoreRules || ! opts . ignoreRules . includes ( problem . kind ) ) ;
1515 const grouped = groupProblemsByKind ( problems ) ;
16- const subpaths = Object . keys ( analysis . entrypoints ) ;
16+ const entrypoints = Object . keys ( analysis . entrypoints ) ;
1717 marked . setOptions ( {
1818 // @ts -expect-error the types are wrong (haha)
1919 renderer : new TerminalRenderer ( ) ,
@@ -43,86 +43,90 @@ export async function typed(analysis: core.Analysis, opts: Opts) {
4343 console . log ( summaryTexts . join ( "" ) || defaultSummary ) ;
4444 }
4545
46- const entrypoints = subpaths . map ( ( s ) => {
46+ const entrypointNames = entrypoints . map (
47+ ( s ) => `"${ s === "." ? analysis . packageName : `${ analysis . packageName } /${ s . substring ( 2 ) } ` } "`
48+ ) ;
49+ const entrypointHeaders = entrypoints . map ( ( s , i ) => {
4750 const hasProblems = problems . some ( ( p ) => problemAffectsEntrypoint ( p , s , analysis ) ) ;
4851 const color = hasProblems ? "redBright" : "greenBright" ;
49-
50- if ( s === "." ) return chalk . bold [ color ] ( `"${ analysis . packageName } "` ) ;
51- else return chalk . bold [ color ] ( `"${ analysis . packageName } /${ s . substring ( 2 ) } "` ) ;
52+ return chalk . bold [ color ] ( entrypointNames [ i ] ) ;
5253 } ) ;
5354
54- if ( opts . format === "table-flipped" ) {
55- const table = new Table ( {
56- head : [ "" , ...allResolutionKinds . map ( ( kind ) => chalk . reset ( resolutionKinds [ kind ] ) ) ] ,
57- colWidths : [ 20 , ...allResolutionKinds . map ( ( ) => 25 ) ] ,
58- } ) ;
59-
60- subpaths . forEach ( ( subpath , i ) => {
61- const point = entrypoints [ i ] ;
62- let row = [ point ] ;
63-
64- row = row . concat (
65- allResolutionKinds . map ( ( kind ) => {
66- const problemsForCell = groupProblemsByKind (
67- filterProblems ( problems , analysis , { entrypoint : subpath , resolutionKind : kind } )
68- ) ;
69- const resolution = analysis . entrypoints [ subpath ] . resolutions [ kind ] . resolution ;
70- const kinds = Object . keys ( problemsForCell ) as core . ProblemKind [ ] ;
71- if ( kinds . length ) {
72- return kinds
73- . map (
74- ( kind ) => ( opts . emoji ? `${ problemKindInfo [ kind ] . emoji } ` : "" ) + problemKindInfo [ kind ] . shortDescription
75- )
76- . join ( "\n" ) ;
77- }
55+ const getCellContents = memo ( ( entrypoint : string , resolutionKind : core . ResolutionKind ) => {
56+ const problemsForCell = groupProblemsByKind ( filterProblems ( problems , analysis , { entrypoint, resolutionKind } ) ) ;
57+ const resolution = analysis . entrypoints [ entrypoint ] . resolutions [ resolutionKind ] . resolution ;
58+ const kinds = Object . keys ( problemsForCell ) as core . ProblemKind [ ] ;
59+ if ( kinds . length ) {
60+ return kinds
61+ . map ( ( kind ) => ( opts . emoji ? `${ problemKindInfo [ kind ] . emoji } ` : "" ) + problemKindInfo [ kind ] . shortDescription )
62+ . join ( "\n" ) ;
63+ }
64+
65+ const jsonResult = ! opts . emoji ? "OK (JSON)" : "🟢 (JSON)" ;
66+ const moduleResult = ( ! opts . emoji ? "OK " : "🟢 " ) + moduleKinds [ resolution ?. moduleKind ?. detectedKind || "" ] ;
67+ return resolution ?. isJson ? jsonResult : moduleResult ;
68+ } ) ;
7869
79- const jsonResult = ! opts . emoji ? "OK (JSON)" : "🟢 (JSON)" ;
80- const moduleResult = ( ! opts . emoji ? "OK " : "🟢 " ) + moduleKinds [ resolution ?. moduleKind ?. detectedKind || "" ] ;
81- return resolution ?. isJson ? jsonResult : moduleResult ;
70+ const flippedTable =
71+ opts . format === "auto" || opts . format === "table-flipped"
72+ ? new Table ( {
73+ head : [ "" , ...allResolutionKinds . map ( ( kind ) => chalk . reset ( resolutionKinds [ kind ] ) ) ] ,
8274 } )
83- ) ;
84-
85- table . push ( row ) ;
75+ : undefined ;
76+ if ( flippedTable ) {
77+ entrypoints . forEach ( ( subpath , i ) => {
78+ flippedTable . push ( [
79+ entrypointHeaders [ i ] ,
80+ ...allResolutionKinds . map ( ( resolutionKind ) => getCellContents ( subpath , resolutionKind ) ) ,
81+ ] ) ;
8682 } ) ;
87- console . log ( table . toString ( ) ) ;
88- return ;
8983 }
9084
91- const table = new Table ( {
92- head : [ "" , ...entrypoints ] ,
93- colWidths : [ 20 , ...entrypoints . map ( ( ) => 35 ) ] ,
94- } ) as GenericTable < HorizontalTableRow > ;
95-
96- allResolutionKinds . forEach ( ( kind ) => {
97- let row = [ resolutionKinds [ kind ] ] ;
98-
99- row = row . concat (
100- subpaths . map ( ( subpath ) => {
101- const problemsForCell = groupProblemsByKind (
102- filterProblems ( problems , analysis , { entrypoint : subpath , resolutionKind : kind } )
103- ) ;
104- const resolution = analysis . entrypoints [ subpath ] . resolutions [ kind ] . resolution ;
105- const kinds = Object . keys ( problemsForCell ) as core . ProblemKind [ ] ;
106- if ( kinds . length ) {
107- return kinds
108- . map (
109- ( kind ) => ( opts . emoji ? `${ problemKindInfo [ kind ] . emoji } ` : "" ) + problemKindInfo [ kind ] . shortDescription
110- )
111- . join ( "\n" ) ;
112- }
113-
114- const jsonResult = ! opts . emoji ? "OK (JSON)" : "🟢 (JSON)" ;
115- const moduleResult = ( ! opts . emoji ? "OK " : "🟢 " ) + moduleKinds [ resolution ?. moduleKind ?. detectedKind || "" ] ;
116- return resolution ?. isJson ? jsonResult : moduleResult ;
117- } )
118- ) ;
119-
120- table . push ( row ) ;
121- } ) ;
85+ const table =
86+ opts . format === "auto" || ! flippedTable
87+ ? ( new Table ( {
88+ head : [ "" , ...entrypointHeaders ] ,
89+ } ) as GenericTable < HorizontalTableRow > )
90+ : undefined ;
91+ if ( table ) {
92+ allResolutionKinds . forEach ( ( kind ) => {
93+ table . push ( [ resolutionKinds [ kind ] , ...entrypoints . map ( ( entrypoint ) => getCellContents ( entrypoint , kind ) ) ] ) ;
94+ } ) ;
95+ }
12296
123- if ( opts . format === "ascii" ) {
124- console . log ( tableFlipped ( table ) ) ;
125- } else {
126- console . log ( table . toString ( ) ) ;
97+ switch ( opts . format ) {
98+ case "table" :
99+ console . log ( table ! . toString ( ) ) ;
100+ break ;
101+ case "table-flipped" :
102+ console . log ( flippedTable ! . toString ( ) ) ;
103+ break ;
104+ case "ascii" :
105+ console . log ( asciiTable ( table ! ) ) ;
106+ break ;
107+ case "auto" :
108+ const terminalWidth = process . stdout . columns || 133 ; // This looks like GitHub Actions' width
109+ if ( table ! . width <= terminalWidth ) {
110+ console . log ( table ! . toString ( ) ) ;
111+ } else if ( flippedTable ! . width <= terminalWidth ) {
112+ console . log ( flippedTable ! . toString ( ) ) ;
113+ } else {
114+ console . log ( asciiTable ( table ! ) ) ;
115+ }
116+ break ;
127117 }
128118}
119+
120+ function memo < Args extends ( string | number ) [ ] , Result > ( fn : ( ...args : Args ) => Result ) : ( ...args : Args ) => Result {
121+ const cache = new Map ( ) ;
122+ return ( ...args ) => {
123+ const key = "" + args ;
124+ if ( cache . has ( key ) ) {
125+ return cache . get ( key ) ;
126+ }
127+
128+ const result = fn ( ...args ) ;
129+ cache . set ( key , result ) ;
130+ return result ;
131+ } ;
132+ }
0 commit comments