auto-cr-cmd
Version:
Fast automated code review CLI powered by SWC-based static analysis
253 lines (252 loc) • 9.52 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createReporter = createReporter;
var auto_cr_rules_1 = require("auto-cr-rules");
var consola_1 = __importDefault(require("consola"));
var i18n_1 = require("../i18n");
var UNTAGGED_TAG = 'untagged';
var DEFAULT_FORMAT = 'text';
var severityLoggers = (_a = {},
_a[auto_cr_rules_1.RuleSeverity.Error] = consola_1.default.error,
_a[auto_cr_rules_1.RuleSeverity.Warning] = consola_1.default.warn,
_a[auto_cr_rules_1.RuleSeverity.Optimizing] = consola_1.default.info,
_a);
function createReporter(filePath, source, options) {
var _a;
if (options === void 0) { options = {}; }
var offsets = buildLineOffsets(source);
var t = (0, i18n_1.getTranslator)();
var language = (0, i18n_1.getLanguage)();
var records = [];
var format = (_a = options.format) !== null && _a !== void 0 ? _a : DEFAULT_FORMAT;
var totalViolations = 0;
var errorViolations = 0;
var severityCounts = {
error: 0,
warning: 0,
optimizing: 0,
};
var pushRecord = function (record) {
records.push(record);
totalViolations += 1;
if (record.severity === auto_cr_rules_1.RuleSeverity.Error) {
errorViolations += 1;
severityCounts.error += 1;
}
else if (record.severity === auto_cr_rules_1.RuleSeverity.Warning) {
severityCounts.warning += 1;
}
else if (record.severity === auto_cr_rules_1.RuleSeverity.Optimizing) {
severityCounts.optimizing += 1;
}
};
var error = function (message) {
pushRecord({
tag: UNTAGGED_TAG,
ruleName: 'general',
severity: auto_cr_rules_1.RuleSeverity.Error,
message: message,
});
};
var errorAtLine = function (line, message) {
pushRecord({
tag: UNTAGGED_TAG,
ruleName: 'general',
severity: auto_cr_rules_1.RuleSeverity.Error,
line: line,
message: message,
});
};
var errorAtSpan = function (spanLike, message) {
var span = extractSpan(spanLike);
if (!span) {
error(message);
return;
}
var line = offsetToLine(span.start, offsets);
errorAtLine(line, message);
};
var buildRuleReporter = function (rule) {
var _a, _b;
var tag = (_a = rule.tag) !== null && _a !== void 0 ? _a : UNTAGGED_TAG;
var severity = (_b = rule.severity) !== null && _b !== void 0 ? _b : auto_cr_rules_1.RuleSeverity.Error;
var store = function (payload) {
pushRecord({
tag: tag,
ruleName: rule.name,
severity: severity,
message: payload.message,
line: payload.line,
code: payload.code,
suggestions: payload.suggestions,
});
};
var scopedError = function (message) {
store({ message: message });
};
var scopedErrorAtLine = function (line, message) {
store({ message: message, line: line });
};
var scopedErrorAtSpan = function (spanLike, message) {
var span = extractSpan(spanLike);
if (!span) {
scopedError(message);
return;
}
var line = offsetToLine(span.start, offsets);
scopedErrorAtLine(line, message);
};
var record = function (payload) {
var line = resolveLine(payload, offsets);
store({
message: payload.description,
line: line,
code: payload.code,
suggestions: payload.suggestions,
});
};
var reporterWithRecord = {
error: scopedError,
errorAtLine: scopedErrorAtLine,
errorAtSpan: scopedErrorAtSpan,
record: record,
};
return reporterWithRecord;
};
var flush = function () {
var violationSnapshot = records.map(function (record) { return (__assign(__assign({}, record), { suggestions: record.suggestions ? __spreadArray([], record.suggestions, true) : undefined })); });
var summary = {
totalViolations: totalViolations,
errorViolations: errorViolations,
severityCounts: {
error: severityCounts.error,
warning: severityCounts.warning,
optimizing: severityCounts.optimizing,
},
violations: violationSnapshot,
};
if (violationSnapshot.length > 0 && format === 'text') {
var locale = language === 'zh' ? 'zh-CN' : 'en-US';
var formatter_1 = new Intl.DateTimeFormat(locale, {
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
});
var indent_1 = ' ';
var colon_1 = language === 'zh' ? ':' : ':';
var headerGap_1 = language === 'zh' ? '' : ' ';
violationSnapshot.forEach(function (violation) {
var timestamp = formatter_1.format(new Date());
var tagLabel = t.ruleTagLabel({ tag: violation.tag });
var severityIcon = t.reporterSeverityIcon({ severity: violation.severity });
var logger = getLoggerForSeverity(violation.severity);
var header = "[".concat(timestamp, "] ").concat(severityIcon, " [").concat(tagLabel, "]").concat(colon_1).concat(headerGap_1).concat(violation.ruleName);
logger(header);
var location = typeof violation.line === 'number' ? "".concat(filePath, ":").concat(violation.line) : filePath;
consola_1.default.log("".concat(indent_1).concat(t.reporterFileLabel(), ": ").concat(location));
consola_1.default.log("".concat(indent_1).concat(t.reporterDescriptionLabel(), ": ").concat(violation.message));
if (violation.code) {
consola_1.default.log("".concat(indent_1).concat(t.reporterCodeLabel(), ": ").concat(violation.code));
}
if (violation.suggestions && violation.suggestions.length > 0) {
var suggestionSeparator = language === 'zh' ? '; ' : ' | ';
var suggestionLine = violation.suggestions
.map(function (suggestion) { return t.reporterFormatSuggestion(suggestion); })
.join(suggestionSeparator);
consola_1.default.log("".concat(indent_1).concat(t.reporterSuggestionLabel(), ": ").concat(suggestionLine));
}
});
}
records.length = 0;
resetCounters();
return summary;
};
var resetCounters = function () {
totalViolations = 0;
errorViolations = 0;
severityCounts.error = 0;
severityCounts.warning = 0;
severityCounts.optimizing = 0;
};
return Object.assign({ error: error, errorAtLine: errorAtLine, errorAtSpan: errorAtSpan }, {
forRule: buildRuleReporter,
flush: flush,
});
}
function getLoggerForSeverity(severity) {
var _a;
return (_a = severityLoggers[severity]) !== null && _a !== void 0 ? _a : consola_1.default.error;
}
function resolveLine(record, offsets) {
if (typeof record.line === 'number') {
return record.line;
}
if (record.span) {
return offsetToLine(record.span.start, offsets);
}
return undefined;
}
function extractSpan(spanLike) {
if (!spanLike) {
return undefined;
}
if (hasSpan(spanLike)) {
return spanLike.span;
}
return spanLike;
}
function hasSpan(value) {
return typeof value === 'object' && value !== null && 'span' in value;
}
function buildLineOffsets(source) {
var offsets = [0];
for (var index = 0; index < source.length; index += 1) {
if (source[index] === '\n') {
offsets.push(index + 1);
}
}
return offsets;
}
function offsetToLine(offset, offsets) {
var low = 0;
var high = offsets.length - 1;
while (low <= high) {
var mid = Math.floor((low + high) / 2);
var current = offsets[mid];
if (current === offset) {
return mid + 1;
}
if (current < offset) {
low = mid + 1;
}
else {
high = mid - 1;
}
}
return high + 1;
}