@@ -7,13 +7,13 @@ import { marked } from "marked";
7
7
import { filterProblems , problemAffectsEntrypoint , problemKindInfo } from "@arethetypeswrong/core/problems" ;
8
8
import type { Opts } from "../index.js" ;
9
9
import { moduleKinds , problemFlags , resolutionKinds } from "../problemUtils.js" ;
10
- import { tableFlipped } from "./tableFlipped .js" ;
10
+ import { asciiTable } from "./asciiTable .js" ;
11
11
import TerminalRenderer from "marked-terminal" ;
12
12
13
13
export async function typed ( analysis : core . Analysis , opts : Opts ) {
14
14
const problems = analysis . problems . filter ( ( problem ) => ! opts . ignoreRules || ! opts . ignoreRules . includes ( problem . kind ) ) ;
15
15
const grouped = groupProblemsByKind ( problems ) ;
16
- const subpaths = Object . keys ( analysis . entrypoints ) ;
16
+ const entrypoints = Object . keys ( analysis . entrypoints ) ;
17
17
marked . setOptions ( {
18
18
// @ts -expect-error the types are wrong (haha)
19
19
renderer : new TerminalRenderer ( ) ,
@@ -43,86 +43,90 @@ export async function typed(analysis: core.Analysis, opts: Opts) {
43
43
console . log ( summaryTexts . join ( "" ) || defaultSummary ) ;
44
44
}
45
45
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 ) => {
47
50
const hasProblems = problems . some ( ( p ) => problemAffectsEntrypoint ( p , s , analysis ) ) ;
48
51
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 ] ) ;
52
53
} ) ;
53
54
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
+ } ) ;
78
69
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 ] ) ) ] ,
82
74
} )
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
+ ] ) ;
86
82
} ) ;
87
- console . log ( table . toString ( ) ) ;
88
- return ;
89
83
}
90
84
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
+ }
122
96
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 ;
127
117
}
128
118
}
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