@expo/xcpretty
Advanced tools
Comparing version 4.0.0 to 4.1.0
@@ -15,5 +15,2 @@ "use strict"; | ||
const symbols_1 = require("./utils/symbols"); | ||
function highlightLastPathComponent(filePath) { | ||
return chalk_1.default.dim(path_1.default.dirname(filePath) + '/') + path_1.default.basename(filePath); | ||
} | ||
/** | ||
@@ -87,6 +84,6 @@ * A superset of `Formatter` which adds support for Metro build errors and cleaner formatting for Node projects. | ||
const appFileRoot = Formatter_1.Formatter.getAppRoot(from); | ||
relativeFile = highlightLastPathComponent(Formatter_1.Formatter.relativePath(appFileRoot, from)); | ||
relativeFile = Formatter_1.Formatter.highlightLastPathComponent(Formatter_1.Formatter.relativePath(appFileRoot, from)); | ||
} | ||
const appFileRoot = Formatter_1.Formatter.getAppRoot(to); | ||
const relativeAppFile = highlightLastPathComponent(Formatter_1.Formatter.relativePath(appFileRoot, to)); | ||
const relativeAppFile = Formatter_1.Formatter.highlightLastPathComponent(Formatter_1.Formatter.relativePath(appFileRoot, to)); | ||
const moduleNameTag = this.getNodeModuleName('', target); | ||
@@ -93,0 +90,0 @@ return Formatter_1.Formatter.format('Copying ', [moduleNameTag, [relativeFile, relativeAppFile].join(' ➜ ')].filter(Boolean).join(' ')); |
import { Failure, Parser } from './Parser'; | ||
declare function highlightLastPathComponent(filePath: string): string; | ||
declare function format(command: string, argumentText?: string, success?: boolean): string; | ||
@@ -31,2 +32,4 @@ declare function relativePath(projectRoot: string, filePath: string): string; | ||
projectRoot: string; | ||
/** Sets the max character length for a warning before cropping the preview. Useful for minified files that can be upwards of a thousand characters long. */ | ||
maxWarningLineLength?: number; | ||
}; | ||
@@ -36,2 +39,3 @@ static format: typeof format; | ||
static getAppRoot: typeof getAppRoot; | ||
static highlightLastPathComponent: typeof highlightLastPathComponent; | ||
static relativePath: typeof relativePath; | ||
@@ -44,2 +48,4 @@ _parser: Parser | undefined; | ||
projectRoot: string; | ||
/** Sets the max character length for a warning before cropping the preview. Useful for minified files that can be upwards of a thousand characters long. */ | ||
maxWarningLineLength?: number; | ||
}); | ||
@@ -98,2 +104,15 @@ pipe(data: string): string[]; | ||
/** | ||
* In: `warning: [CP] Vendored binary '/Users/evanbacon/Library/Developer/Xcode/DerivedData/yolo67-hcjsxsdqyxnsgdednlbpylgeffja/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/hermes-engine.build/DerivedSources/hermes.framework.dSYM/Contents/Resources/DWARF/hermes' contains architectures (armv7 armv7s arm64) none of which match the current build architectures (x86_64).` | ||
* Out: `⚠️ Vendored binary '[app]/hermes-engine.build/DerivedSources/hermes.framework.dSYM/Contents/Resources/DWARF/hermes' does not support current build architecture (x86_64). Supported architectures: armv7, armv7s, arm64.` | ||
* | ||
* @param os iOS | ||
* @param deploymentTarget IPHONEOS_DEPLOYMENT_TARGET | ||
* @param version 8.0 | ||
* @param minVersion 9.0 | ||
* @param maxVersion 14.3.99 | ||
* @param target boost-for-react-native | ||
* @param project Pods | ||
*/ | ||
formatMissingArchitectureWarning(binaryPath: string, architectures: string[], currentArchitectures: string[]): string; | ||
/** | ||
* In: `Skipping duplicate build file in Compile Sources build phase: /Users/evanbacon/Documents/GitHub/expo/ios/Exponent/Kernel/ReactAppManager/EXReactAppManager.mm (in target 'Exponent' from project 'Exponent')` | ||
@@ -100,0 +119,0 @@ * Out: |
@@ -44,2 +44,5 @@ "use strict"; | ||
})(Status || (Status = {})); | ||
function highlightLastPathComponent(filePath) { | ||
return chalk_1.default.dim(path.dirname(filePath) + '/') + path.basename(filePath); | ||
} | ||
function format(command, argumentText = '', success = true) { | ||
@@ -97,6 +100,7 @@ const symbol = statusSymbol(success ? Status.Completion : Status.Fail); | ||
let appRoot = filePath; | ||
while (!/((Debug|Release)-[^/\s\d]*$)|(.app$)/.test(appRoot) && appRoot.length > 1) { | ||
const isBuildFolder = (path) => /((Debug|Release)-[^/\s\d]*$)|(.app$)/.test(path); | ||
while (!isBuildFolder(appRoot) && appRoot.length > 1) { | ||
appRoot = path.dirname(appRoot); | ||
} | ||
return appRoot; | ||
return isBuildFolder(appRoot) ? appRoot : ''; | ||
} | ||
@@ -271,2 +275,3 @@ class Formatter { | ||
projectRoot: this.props.projectRoot, | ||
maxWarningLineLength: this.props.maxWarningLineLength, | ||
}); | ||
@@ -360,2 +365,23 @@ this.errors.push(results); | ||
/** | ||
* In: `warning: [CP] Vendored binary '/Users/evanbacon/Library/Developer/Xcode/DerivedData/yolo67-hcjsxsdqyxnsgdednlbpylgeffja/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/hermes-engine.build/DerivedSources/hermes.framework.dSYM/Contents/Resources/DWARF/hermes' contains architectures (armv7 armv7s arm64) none of which match the current build architectures (x86_64).` | ||
* Out: `⚠️ Vendored binary '[app]/hermes-engine.build/DerivedSources/hermes.framework.dSYM/Contents/Resources/DWARF/hermes' does not support current build architecture (x86_64). Supported architectures: armv7, armv7s, arm64.` | ||
* | ||
* @param os iOS | ||
* @param deploymentTarget IPHONEOS_DEPLOYMENT_TARGET | ||
* @param version 8.0 | ||
* @param minVersion 9.0 | ||
* @param maxVersion 14.3.99 | ||
* @param target boost-for-react-native | ||
* @param project Pods | ||
*/ | ||
formatMissingArchitectureWarning(binaryPath, architectures, currentArchitectures) { | ||
const appFileRoot = getAppRoot(binaryPath); | ||
const relativeAppFile = appFileRoot | ||
? chalk_1.default.gray('[app]/') + relativePath(appFileRoot, binaryPath) | ||
: binaryPath; | ||
const architectureString = currentArchitectures.length === 1 ? 'architecture' : 'architectures'; | ||
const supportedString = chalk_1.default.dim(`Supported architectures: ${architectures.join(', ')}.`); | ||
return (chalk_1.default.yellow(`${symbols_1.WARNING} Vendored binary '${relativeAppFile}' does not support current build ${architectureString} (${chalk_1.default.bold(currentArchitectures.join(', '))}). `) + supportedString); | ||
} | ||
/** | ||
* In: `Skipping duplicate build file in Compile Sources build phase: /Users/evanbacon/Documents/GitHub/expo/ios/Exponent/Kernel/ReactAppManager/EXReactAppManager.mm (in target 'Exponent' from project 'Exponent')` | ||
@@ -405,2 +431,8 @@ * Out: | ||
[ | ||
Matchers_1.Matchers.Warnings.MISSING_ARCHITECTURE, | ||
([, $1, $2, $3]) => { | ||
return this.formatMissingArchitectureWarning($1, $2 === null || $2 === void 0 ? void 0 : $2.split(' ').map(value => value.trim()), $3 === null || $3 === void 0 ? void 0 : $3.split(' ').map(value => value.trim())); | ||
}, | ||
], | ||
[ | ||
Matchers_1.Matchers.Warnings.VERSION_MISMATCH, | ||
@@ -448,2 +480,3 @@ ([, $1, $2, $3, $4, $5, $6, $7]) => { | ||
projectRoot: this.props.projectRoot, | ||
maxWarningLineLength: this.props.maxWarningLineLength, | ||
}); | ||
@@ -511,2 +544,3 @@ this.warnings.push(results); | ||
projectRoot: this.props.projectRoot, | ||
maxWarningLineLength: this.props.maxWarningLineLength, | ||
}); | ||
@@ -531,2 +565,3 @@ } | ||
Formatter.getAppRoot = getAppRoot; | ||
Formatter.highlightLastPathComponent = highlightLastPathComponent; | ||
Formatter.relativePath = relativePath; | ||
@@ -562,4 +597,4 @@ function formatPaths(config) { | ||
} | ||
function formatWarningOrError({ filePath, reason, cursor, lineText, lineNumber, columnNumber, projectRoot, isError, }) { | ||
// TODO: Use testName for errors | ||
function formatWarningOrError({ projectRoot, filePath, reason, cursor, lineText, lineNumber, columnNumber, isError, maxWarningLineLength = 200, }) { | ||
var _a; | ||
const line = parseOptionalInt(lineNumber) || 0; | ||
@@ -569,5 +604,12 @@ const column = parseOptionalInt(columnNumber); | ||
const icon = color(isError ? symbols_1.ERROR : symbols_1.WARNING); | ||
const relativeFilePath = filePath ? slash(path.relative(projectRoot, filePath)) : null; | ||
const displayFilePath = !filePath | ||
? // If no file path, use null | ||
null | ||
: // If the file path is inside of the build folder (Hermes), then use absolute path. | ||
getAppRoot(filePath) | ||
? filePath | ||
: // Otherwise, use relative path | ||
slash(path.relative(projectRoot, filePath)); | ||
const formattedPath = formatPaths({ | ||
filePath: relativeFilePath, | ||
filePath: displayFilePath, | ||
col: column, | ||
@@ -578,2 +620,36 @@ line, | ||
const formattedReason = color(grayOutMatch(reason, /(\[-.*?\])/).replace(/(\(.*?\)\s?)/, '')); | ||
// Add special case for .jsbundle files that are parsed with Hermes. | ||
const isHermes = filePath.endsWith('.jsbundle'); | ||
const isPreviewTooLong = isHermes || (lineText && lineText.length > maxWarningLineLength); | ||
// When the preview is too long, we skip reading the file and attempting to apply | ||
// code coloring, this is because it can get very slow. | ||
if (isPreviewTooLong) { | ||
let previewLine = ''; | ||
let cursorLine = formattedReason; | ||
// Create a curtailed preview line like: | ||
// `...transition:'fade'},k._updatePropsStack=function(){clearImmediate(k._updateImmediate),k._updateImmediate...` | ||
// If there is no text preview or column number, we can't do anything. | ||
if (lineText && column != null) { | ||
const rangeWindow = Math.round(Math.max((_a = displayFilePath === null || displayFilePath === void 0 ? void 0 : displayFilePath.length) !== null && _a !== void 0 ? _a : 0, 80) / 2); | ||
let minBounds = Math.max(0, column - rangeWindow); | ||
const maxBounds = Math.min(minBounds + rangeWindow * 2, lineText.length); | ||
previewLine = lineText.slice(minBounds, maxBounds); | ||
// If we splice content off the start, then we should append `...`. | ||
// This is unlikely to happen since we limit the activation size. | ||
if (minBounds > 0) { | ||
// Adjust the min bounds so the cursor is aligned after we add the "..." | ||
minBounds -= 3; | ||
previewLine = chalk_1.default.dim('...') + previewLine; | ||
} | ||
if (maxBounds < lineText.length) { | ||
previewLine += chalk_1.default.dim('...'); | ||
} | ||
// If the column property could be found, then use that to fix the cursor location which is often broken in regex. | ||
cursorLine = | ||
(column == null ? chalk_1.default.reset(cursor) : fill(column) + chalk_1.default.reset('^')).slice(minBounds) + | ||
' ' + | ||
formattedReason; | ||
} | ||
return ['', pathWithPrefix, '', previewLine, cursorLine, chalk_1.default.dim('(warning truncated)')].join('\n'); | ||
} | ||
try { | ||
@@ -580,0 +656,0 @@ const raw = fs.readFileSync(filePath, 'utf8'); |
@@ -258,2 +258,6 @@ export declare const Matchers: { | ||
* @regex Captured groups | ||
*/ | ||
MISSING_ARCHITECTURE: RegExp; | ||
/** | ||
* @regex Captured groups | ||
* `$1` buildPhase | ||
@@ -260,0 +264,0 @@ * `$2` filePath |
@@ -261,2 +261,6 @@ "use strict"; | ||
* @regex Captured groups | ||
*/ | ||
MISSING_ARCHITECTURE: /^\[CP\] Vendored binary\s'([^']*)'.*contains architectures \(([\w\d\s]+)\) none of which match the current build architectures \(([\w\d\s]+)\)/m, | ||
/** | ||
* @regex Captured groups | ||
* `$1` buildPhase | ||
@@ -267,3 +271,3 @@ * `$2` filePath | ||
*/ | ||
SKIPPING_DUPLICATE_FILE: /^Skipping duplicate build file in (Compile Sources) build phase: (.*) \(in\s.*target '([^']*)'.*project '([^']*)'/m, | ||
SKIPPING_DUPLICATE_FILE: /^Skipping duplicate build file in ([A-Za-z\s]+) build phase: (.*) \(in\s.*target '([^']*)'.*project '([^']*)'/m, | ||
/** | ||
@@ -270,0 +274,0 @@ * @regex Captured groups |
@@ -21,11 +21,13 @@ "use strict"; | ||
parse(text) { | ||
this.updateTestState(text); | ||
this.updateErrorState(text); | ||
this.updateLinkerFailureState(text); | ||
const matchedErrorResults = this.updateErrorState(text); | ||
if (this.shouldFormatWarning()) { | ||
return this.formatCompileWarning(); | ||
} | ||
if (this.shouldFormatError()) { | ||
return this.formatCompileError(); | ||
} | ||
if (this.shouldFormatWarning()) { | ||
return this.formatCompileWarning(); | ||
if (matchedErrorResults) { | ||
return ''; | ||
} | ||
const matchedLinkerResults = this.updateLinkerFailureState(text); | ||
if (this.shouldFormatUndefinedSymbols()) { | ||
@@ -37,2 +39,6 @@ return this.formatUndefinedSymbols(); | ||
} | ||
if (matchedLinkerResults) { | ||
return ''; | ||
} | ||
this.updateTestState(text); | ||
const { formatter } = this; | ||
@@ -357,3 +363,3 @@ return switchRegex_1.switchRegex(text, [ | ||
}; | ||
return switchRegex_1.switchRegex(text, [ | ||
const results = switchRegex_1.switchRegex(text, [ | ||
[ | ||
@@ -386,5 +392,7 @@ Matchers_1.Matchers.Errors.COMPILE_ERROR_MATCHER, | ||
} | ||
return 'unmatched'; | ||
}, | ||
], | ||
]); | ||
return results !== 'unmatched'; | ||
} | ||
@@ -408,5 +416,5 @@ updateLinkerFailureState(text) { | ||
if (!this.formattingLinkerFailure) { | ||
return; | ||
return false; | ||
} | ||
return switchRegex_1.switchRegex(text, [ | ||
const results = switchRegex_1.switchRegex(text, [ | ||
[ | ||
@@ -432,3 +440,10 @@ Matchers_1.Matchers.Errors.SYMBOL_REFERENCED_FROM_MATCHER, | ||
], | ||
[ | ||
null, | ||
() => { | ||
return 'unmatched'; | ||
}, | ||
], | ||
]); | ||
return results !== 'unmatched'; | ||
} | ||
@@ -435,0 +450,0 @@ // TODO: clean up the mess around all this |
@@ -15,2 +15,2 @@ /// <reference types="node" /> | ||
export declare function writeBuildLogs(projectRoot: string, buildOutput: string, errorOutput: string): string; | ||
export declare function getErrorLogFilePath(projectRoot: string): string[]; | ||
export declare function getErrorLogFilePath(projectRoot: string): [string, string]; |
@@ -9,2 +9,3 @@ "use strict"; | ||
const fs_1 = __importDefault(require("fs")); | ||
const os_1 = __importDefault(require("os")); | ||
const path_1 = __importDefault(require("path")); | ||
@@ -29,11 +30,26 @@ const ExpoRunFormatter_1 = require("./ExpoRunFormatter"); | ||
let errorOutput = ''; | ||
let currentBuffer = ''; | ||
// Data can be sent in chunks that would have no relevance to our regex | ||
// this can cause massive slowdowns, so we need to ensure the data is complete before attempting to parse it. | ||
function flushBuffer() { | ||
if (!currentBuffer) { | ||
return; | ||
} | ||
const data = currentBuffer; | ||
currentBuffer = ''; | ||
const lines = formatter.pipe(data); | ||
for (const line of lines) { | ||
console.log(line); | ||
} | ||
} | ||
const onData = (data) => { | ||
const stringData = data.toString(); | ||
buildOutput += stringData; | ||
const lines = formatter.pipe(stringData); | ||
for (const line of lines) { | ||
console.log(line); | ||
currentBuffer += stringData; | ||
if (currentBuffer.endsWith(os_1.default.EOL)) { | ||
flushBuffer(); | ||
} | ||
}; | ||
const onErr = (data) => { | ||
flushBuffer(); | ||
const stringData = data instanceof Buffer ? data.toString() : data; | ||
@@ -43,2 +59,3 @@ errorOutput += stringData; | ||
const onEnd = (code) => { | ||
flushBuffer(); | ||
console.log(formatter.getBuildSummary()); | ||
@@ -72,18 +89,12 @@ const logFilePath = writeBuildLogs(projectRoot, buildOutput, errorOutput); | ||
function writeBuildLogs(projectRoot, buildOutput, errorOutput) { | ||
const output = '# Build output\n\n```log\n' + | ||
buildOutput + | ||
'\n```\n\n# Error output\n\n```log\n' + | ||
errorOutput + | ||
'\n```\n'; | ||
const [mdFilePath, logFilePath] = getErrorLogFilePath(projectRoot); | ||
fs_1.default.writeFileSync(mdFilePath, output); | ||
const [logFilePath, errorFilePath] = getErrorLogFilePath(projectRoot); | ||
fs_1.default.writeFileSync(logFilePath, buildOutput); | ||
return mdFilePath; | ||
fs_1.default.writeFileSync(errorFilePath, errorOutput); | ||
return logFilePath; | ||
} | ||
exports.writeBuildLogs = writeBuildLogs; | ||
function getErrorLogFilePath(projectRoot) { | ||
const filename = 'xcodebuild.md'; | ||
const folder = path_1.default.join(projectRoot, '.expo'); | ||
fs_1.default.mkdirSync(folder, { recursive: true }); | ||
return [path_1.default.join(folder, filename), path_1.default.join(folder, 'xcodebuild-output.log')]; | ||
return [path_1.default.join(folder, 'xcodebuild.log'), path_1.default.join(folder, 'xcodebuild-error.log')]; | ||
} | ||
@@ -90,0 +101,0 @@ exports.getErrorLogFilePath = getErrorLogFilePath; |
{ | ||
"name": "@expo/xcpretty", | ||
"description": "Parse and format xcodebuild logs", | ||
"version": "4.0.0", | ||
"version": "4.1.0", | ||
"main": "build/index.js", | ||
@@ -6,0 +6,0 @@ "types": "build/index.d.ts", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
269045
3053