2020-05-15 09:52:23 -04:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . default = void 0 ;
var _buffer = _interopRequireDefault ( require ( "./buffer" ) ) ;
var n = _interopRequireWildcard ( require ( "./node" ) ) ;
2020-09-08 13:25:36 -04:00
var t = _interopRequireWildcard ( require ( "@babel/types" ) ) ;
2020-05-15 09:52:23 -04:00
var generatorFunctions = _interopRequireWildcard ( require ( "./generators" ) ) ;
2020-09-08 13:25:36 -04:00
function _getRequireWildcardCache ( ) { if ( typeof WeakMap !== "function" ) return null ; var cache = new WeakMap ( ) ; _getRequireWildcardCache = function ( ) { return cache ; } ; return cache ; }
function _interopRequireWildcard ( obj ) { if ( obj && obj . _ _esModule ) { return obj ; } if ( obj === null || typeof obj !== "object" && typeof obj !== "function" ) { return { default : obj } ; } var cache = _getRequireWildcardCache ( ) ; if ( cache && cache . has ( obj ) ) { return cache . get ( obj ) ; } var newObj = { } ; var hasPropertyDescriptor = Object . defineProperty && Object . getOwnPropertyDescriptor ; for ( var key in obj ) { if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) { var desc = hasPropertyDescriptor ? Object . getOwnPropertyDescriptor ( obj , key ) : null ; if ( desc && ( desc . get || desc . set ) ) { Object . defineProperty ( newObj , key , desc ) ; } else { newObj [ key ] = obj [ key ] ; } } } newObj . default = obj ; if ( cache ) { cache . set ( obj , newObj ) ; } return newObj ; }
2020-05-15 09:52:23 -04:00
function _interopRequireDefault ( obj ) { return obj && obj . _ _esModule ? obj : { default : obj } ; }
const SCIENTIFIC _NOTATION = /e/i ;
const ZERO _DECIMAL _INTEGER = /\.0+$/ ;
const NON _DECIMAL _LITERAL = /^0[box]/ ;
2020-09-08 13:25:36 -04:00
const PURE _ANNOTATION _RE = /^\s*[@#]__PURE__\s*$/ ;
2020-05-15 09:52:23 -04:00
class Printer {
constructor ( format , map ) {
this . inForStatementInitCounter = 0 ;
this . _printStack = [ ] ;
this . _indent = 0 ;
this . _insideAux = false ;
this . _printedCommentStarts = { } ;
this . _parenPushNewlineState = null ;
this . _noLineTerminator = false ;
this . _printAuxAfterOnNextUserNode = false ;
this . _printedComments = new WeakSet ( ) ;
this . _endsWithInteger = false ;
this . _endsWithWord = false ;
this . format = format || { } ;
this . _buf = new _buffer . default ( map ) ;
}
generate ( ast ) {
this . print ( ast ) ;
this . _maybeAddAuxComment ( ) ;
return this . _buf . get ( ) ;
}
indent ( ) {
if ( this . format . compact || this . format . concise ) return ;
this . _indent ++ ;
}
dedent ( ) {
if ( this . format . compact || this . format . concise ) return ;
this . _indent -- ;
}
semicolon ( force = false ) {
this . _maybeAddAuxComment ( ) ;
this . _append ( ";" , ! force ) ;
}
rightBrace ( ) {
if ( this . format . minified ) {
this . _buf . removeLastSemicolon ( ) ;
}
this . token ( "}" ) ;
}
space ( force = false ) {
if ( this . format . compact ) return ;
if ( this . _buf . hasContent ( ) && ! this . endsWith ( " " ) && ! this . endsWith ( "\n" ) || force ) {
this . _space ( ) ;
}
}
word ( str ) {
if ( this . _endsWithWord || this . endsWith ( "/" ) && str . indexOf ( "/" ) === 0 ) {
this . _space ( ) ;
}
this . _maybeAddAuxComment ( ) ;
this . _append ( str ) ;
this . _endsWithWord = true ;
}
number ( str ) {
this . word ( str ) ;
2020-09-08 13:25:36 -04:00
this . _endsWithInteger = Number . isInteger ( + str ) && ! NON _DECIMAL _LITERAL . test ( str ) && ! SCIENTIFIC _NOTATION . test ( str ) && ! ZERO _DECIMAL _INTEGER . test ( str ) && str [ str . length - 1 ] !== "." ;
2020-05-15 09:52:23 -04:00
}
token ( str ) {
if ( str === "--" && this . endsWith ( "!" ) || str [ 0 ] === "+" && this . endsWith ( "+" ) || str [ 0 ] === "-" && this . endsWith ( "-" ) || str [ 0 ] === "." && this . _endsWithInteger ) {
this . _space ( ) ;
}
this . _maybeAddAuxComment ( ) ;
this . _append ( str ) ;
}
newline ( i ) {
if ( this . format . retainLines || this . format . compact ) return ;
if ( this . format . concise ) {
this . space ( ) ;
return ;
}
if ( this . endsWith ( "\n\n" ) ) return ;
if ( typeof i !== "number" ) i = 1 ;
i = Math . min ( 2 , i ) ;
if ( this . endsWith ( "{\n" ) || this . endsWith ( ":\n" ) ) i -- ;
if ( i <= 0 ) return ;
for ( let j = 0 ; j < i ; j ++ ) {
this . _newline ( ) ;
}
}
endsWith ( str ) {
return this . _buf . endsWith ( str ) ;
}
removeTrailingNewline ( ) {
this . _buf . removeTrailingNewline ( ) ;
}
exactSource ( loc , cb ) {
this . _catchUp ( "start" , loc ) ;
this . _buf . exactSource ( loc , cb ) ;
}
source ( prop , loc ) {
this . _catchUp ( prop , loc ) ;
this . _buf . source ( prop , loc ) ;
}
withSource ( prop , loc , cb ) {
this . _catchUp ( prop , loc ) ;
this . _buf . withSource ( prop , loc , cb ) ;
}
_space ( ) {
this . _append ( " " , true ) ;
}
_newline ( ) {
this . _append ( "\n" , true ) ;
}
_append ( str , queue = false ) {
this . _maybeAddParen ( str ) ;
this . _maybeIndent ( str ) ;
if ( queue ) this . _buf . queue ( str ) ; else this . _buf . append ( str ) ;
this . _endsWithWord = false ;
this . _endsWithInteger = false ;
}
_maybeIndent ( str ) {
if ( this . _indent && this . endsWith ( "\n" ) && str [ 0 ] !== "\n" ) {
this . _buf . queue ( this . _getIndent ( ) ) ;
}
}
_maybeAddParen ( str ) {
const parenPushNewlineState = this . _parenPushNewlineState ;
if ( ! parenPushNewlineState ) return ;
let i ;
for ( i = 0 ; i < str . length && str [ i ] === " " ; i ++ ) continue ;
2020-09-08 13:25:36 -04:00
if ( i === str . length ) {
return ;
}
2020-05-15 09:52:23 -04:00
const cha = str [ i ] ;
if ( cha !== "\n" ) {
2020-09-08 13:25:36 -04:00
if ( cha !== "/" || i + 1 === str . length ) {
this . _parenPushNewlineState = null ;
return ;
}
2020-05-15 09:52:23 -04:00
const chaPost = str [ i + 1 ] ;
2020-09-08 13:25:36 -04:00
if ( chaPost === "*" ) {
if ( PURE _ANNOTATION _RE . test ( str . slice ( i + 2 , str . length - 2 ) ) ) {
return ;
}
} else if ( chaPost !== "/" ) {
this . _parenPushNewlineState = null ;
return ;
}
2020-05-15 09:52:23 -04:00
}
this . token ( "(" ) ;
this . indent ( ) ;
parenPushNewlineState . printed = true ;
}
_catchUp ( prop , loc ) {
if ( ! this . format . retainLines ) return ;
const pos = loc ? loc [ prop ] : null ;
2020-09-08 13:25:36 -04:00
if ( ( pos == null ? void 0 : pos . line ) != null ) {
2020-05-15 09:52:23 -04:00
const count = pos . line - this . _buf . getCurrentLine ( ) ;
for ( let i = 0 ; i < count ; i ++ ) {
this . _newline ( ) ;
}
}
}
_getIndent ( ) {
2020-09-08 13:25:36 -04:00
return this . format . indent . style . repeat ( this . _indent ) ;
2020-05-15 09:52:23 -04:00
}
startTerminatorless ( isLabel = false ) {
if ( isLabel ) {
this . _noLineTerminator = true ;
return null ;
} else {
return this . _parenPushNewlineState = {
printed : false
} ;
}
}
endTerminatorless ( state ) {
this . _noLineTerminator = false ;
2020-09-08 13:25:36 -04:00
if ( state == null ? void 0 : state . printed ) {
2020-05-15 09:52:23 -04:00
this . dedent ( ) ;
this . newline ( ) ;
this . token ( ")" ) ;
}
}
print ( node , parent ) {
if ( ! node ) return ;
const oldConcise = this . format . concise ;
if ( node . _compact ) {
this . format . concise = true ;
}
const printMethod = this [ node . type ] ;
if ( ! printMethod ) {
2020-09-08 13:25:36 -04:00
throw new ReferenceError ( ` unknown node of type ${ JSON . stringify ( node . type ) } with constructor ${ JSON . stringify ( node == null ? void 0 : node . constructor . name ) } ` ) ;
2020-05-15 09:52:23 -04:00
}
this . _printStack . push ( node ) ;
const oldInAux = this . _insideAux ;
this . _insideAux = ! node . loc ;
this . _maybeAddAuxComment ( this . _insideAux && ! oldInAux ) ;
let needsParens = n . needsParens ( node , parent , this . _printStack ) ;
if ( this . format . retainFunctionParens && node . type === "FunctionExpression" && node . extra && node . extra . parenthesized ) {
needsParens = true ;
}
if ( needsParens ) this . token ( "(" ) ;
this . _printLeadingComments ( node ) ;
2020-09-08 13:25:36 -04:00
const loc = t . isProgram ( node ) || t . isFile ( node ) ? null : node . loc ;
2020-05-15 09:52:23 -04:00
this . withSource ( "start" , loc , ( ) => {
printMethod . call ( this , node , parent ) ;
} ) ;
this . _printTrailingComments ( node ) ;
if ( needsParens ) this . token ( ")" ) ;
this . _printStack . pop ( ) ;
this . format . concise = oldConcise ;
this . _insideAux = oldInAux ;
}
_maybeAddAuxComment ( enteredPositionlessNode ) {
if ( enteredPositionlessNode ) this . _printAuxBeforeComment ( ) ;
if ( ! this . _insideAux ) this . _printAuxAfterComment ( ) ;
}
_printAuxBeforeComment ( ) {
if ( this . _printAuxAfterOnNextUserNode ) return ;
this . _printAuxAfterOnNextUserNode = true ;
const comment = this . format . auxiliaryCommentBefore ;
if ( comment ) {
this . _printComment ( {
type : "CommentBlock" ,
value : comment
} ) ;
}
}
_printAuxAfterComment ( ) {
if ( ! this . _printAuxAfterOnNextUserNode ) return ;
this . _printAuxAfterOnNextUserNode = false ;
const comment = this . format . auxiliaryCommentAfter ;
if ( comment ) {
this . _printComment ( {
type : "CommentBlock" ,
value : comment
} ) ;
}
}
getPossibleRaw ( node ) {
const extra = node . extra ;
if ( extra && extra . raw != null && extra . rawValue != null && node . value === extra . rawValue ) {
return extra . raw ;
}
}
printJoin ( nodes , parent , opts = { } ) {
2020-09-08 13:25:36 -04:00
if ( ! ( nodes == null ? void 0 : nodes . length ) ) return ;
2020-05-15 09:52:23 -04:00
if ( opts . indent ) this . indent ( ) ;
const newlineOpts = {
addNewlines : opts . addNewlines
} ;
for ( let i = 0 ; i < nodes . length ; i ++ ) {
const node = nodes [ i ] ;
if ( ! node ) continue ;
if ( opts . statement ) this . _printNewline ( true , node , parent , newlineOpts ) ;
this . print ( node , parent ) ;
if ( opts . iterator ) {
opts . iterator ( node , i ) ;
}
if ( opts . separator && i < nodes . length - 1 ) {
opts . separator . call ( this ) ;
}
if ( opts . statement ) this . _printNewline ( false , node , parent , newlineOpts ) ;
}
if ( opts . indent ) this . dedent ( ) ;
}
printAndIndentOnComments ( node , parent ) {
const indent = node . leadingComments && node . leadingComments . length > 0 ;
if ( indent ) this . indent ( ) ;
this . print ( node , parent ) ;
if ( indent ) this . dedent ( ) ;
}
printBlock ( parent ) {
const node = parent . body ;
2020-09-08 13:25:36 -04:00
if ( ! t . isEmptyStatement ( node ) ) {
2020-05-15 09:52:23 -04:00
this . space ( ) ;
}
this . print ( node , parent ) ;
}
_printTrailingComments ( node ) {
this . _printComments ( this . _getComments ( false , node ) ) ;
}
_printLeadingComments ( node ) {
2020-09-08 13:25:36 -04:00
this . _printComments ( this . _getComments ( true , node ) , true ) ;
2020-05-15 09:52:23 -04:00
}
printInnerComments ( node , indent = true ) {
2020-09-08 13:25:36 -04:00
var _node$innerComments ;
if ( ! ( ( _node$innerComments = node . innerComments ) == null ? void 0 : _node$innerComments . length ) ) return ;
2020-05-15 09:52:23 -04:00
if ( indent ) this . indent ( ) ;
this . _printComments ( node . innerComments ) ;
if ( indent ) this . dedent ( ) ;
}
printSequence ( nodes , parent , opts = { } ) {
opts . statement = true ;
return this . printJoin ( nodes , parent , opts ) ;
}
printList ( items , parent , opts = { } ) {
if ( opts . separator == null ) {
opts . separator = commaSeparator ;
}
return this . printJoin ( items , parent , opts ) ;
}
_printNewline ( leading , node , parent , opts ) {
if ( this . format . retainLines || this . format . compact ) return ;
if ( this . format . concise ) {
this . space ( ) ;
return ;
}
let lines = 0 ;
if ( this . _buf . hasContent ( ) ) {
if ( ! leading ) lines ++ ;
if ( opts . addNewlines ) lines += opts . addNewlines ( leading , node ) || 0 ;
const needs = leading ? n . needsWhitespaceBefore : n . needsWhitespaceAfter ;
if ( needs ( node , parent ) ) lines ++ ;
}
this . newline ( lines ) ;
}
_getComments ( leading , node ) {
return node && ( leading ? node . leadingComments : node . trailingComments ) || [ ] ;
}
2020-09-08 13:25:36 -04:00
_printComment ( comment , skipNewLines ) {
2020-05-15 09:52:23 -04:00
if ( ! this . format . shouldPrintComment ( comment . value ) ) return ;
if ( comment . ignore ) return ;
if ( this . _printedComments . has ( comment ) ) return ;
this . _printedComments . add ( comment ) ;
if ( comment . start != null ) {
if ( this . _printedCommentStarts [ comment . start ] ) return ;
this . _printedCommentStarts [ comment . start ] = true ;
}
const isBlockComment = comment . type === "CommentBlock" ;
2020-09-08 13:25:36 -04:00
const printNewLines = isBlockComment && ! skipNewLines && ! this . _noLineTerminator ;
if ( printNewLines && this . _buf . hasContent ( ) ) this . newline ( 1 ) ;
2020-05-15 09:52:23 -04:00
if ( ! this . endsWith ( "[" ) && ! this . endsWith ( "{" ) ) this . space ( ) ;
let val = ! isBlockComment && ! this . _noLineTerminator ? ` // ${ comment . value } \n ` : ` /* ${ comment . value } */ ` ;
if ( isBlockComment && this . format . indent . adjustMultilineComment ) {
2020-09-08 13:25:36 -04:00
var _comment$loc ;
const offset = ( _comment$loc = comment . loc ) == null ? void 0 : _comment$loc . start . column ;
2020-05-15 09:52:23 -04:00
if ( offset ) {
const newlineRegex = new RegExp ( "\\n\\s{1," + offset + "}" , "g" ) ;
val = val . replace ( newlineRegex , "\n" ) ;
}
const indentSize = Math . max ( this . _getIndent ( ) . length , this . _buf . getCurrentColumn ( ) ) ;
2020-09-08 13:25:36 -04:00
val = val . replace ( /\n(?!$)/g , ` \n ${ " " . repeat ( indentSize ) } ` ) ;
2020-05-15 09:52:23 -04:00
}
if ( this . endsWith ( "/" ) ) this . _space ( ) ;
this . withSource ( "start" , comment . loc , ( ) => {
this . _append ( val ) ;
} ) ;
2020-09-08 13:25:36 -04:00
if ( printNewLines ) this . newline ( 1 ) ;
2020-05-15 09:52:23 -04:00
}
2020-09-08 13:25:36 -04:00
_printComments ( comments , inlinePureAnnotation ) {
if ( ! ( comments == null ? void 0 : comments . length ) ) return ;
2020-05-15 09:52:23 -04:00
2020-09-08 13:25:36 -04:00
if ( inlinePureAnnotation && comments . length === 1 && PURE _ANNOTATION _RE . test ( comments [ 0 ] . value ) ) {
this . _printComment ( comments [ 0 ] , this . _buf . hasContent ( ) && ! this . endsWith ( "\n" ) ) ;
} else {
for ( const comment of comments ) {
this . _printComment ( comment ) ;
}
2020-05-15 09:52:23 -04:00
}
}
}
exports . default = Printer ;
Object . assign ( Printer . prototype , generatorFunctions ) ;
function commaSeparator ( ) {
this . token ( "," ) ;
this . space ( ) ;
}