@nasl/cli 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -114,7 +114,10 @@ function validateNormalFile(file, nameFromPath, namespace, errors) {
114
114
  function composeToString(files) {
115
115
  files.sort((a, b) => sorter(a.path, b.path));
116
116
  const errors = [];
117
+ let currentLine = 1;
117
118
  const result = files.map((file) => {
119
+ // 记录这个文件的开始行号
120
+ file.startLine = currentLine;
118
121
  const arr = file.path.split('.');
119
122
  const ext = arr.pop();
120
123
  const nameFromPath = arr.pop();
@@ -140,7 +143,14 @@ function composeToString(files) {
140
143
  else if (isThemeCss) {
141
144
  content = ` $theme\`${content}\`;`;
142
145
  }
143
- return `namespace ${namespace} {\n${content}\n}\n`;
146
+ const fileContent = `namespace ${namespace} {\n${content}\n}\n`;
147
+ // 计算这个文件占用的行数(末尾 \n 导致 split 多一个空元素,减 1 得到实际行数)
148
+ const lineCount = fileContent.split('\n').length - 1;
149
+ // 记录这个文件的结束行号
150
+ file.endLine = currentLine + lineCount - 1;
151
+ // +1 是 join('\n') 在文件之间插入的换行符
152
+ currentLine = file.endLine + 2;
153
+ return fileContent;
144
154
  })
145
155
  .join('\n');
146
156
  if (errors.length > 0) {
@@ -34982,6 +34992,63 @@ async function tryCompile(entry, options) {
34982
34992
  }
34983
34993
  }
34984
34994
 
34995
+ /**
34996
+ * 将错误信息中的行号映射回原始文件
34997
+ * 直接替换错误头中的文件路径和行号,并调整代码片段中的行号
34998
+ */
34999
+ function mapErrorToSourceFile(options) {
35000
+ const { errorMessage, collectedFiles } = options;
35001
+ // 构建行号到文件的映射
35002
+ const lineToFileMap = new Map();
35003
+ collectedFiles.forEach((file) => {
35004
+ if (file.startLine !== undefined && file.endLine !== undefined) {
35005
+ for (let i = file.startLine; i <= file.endLine; i++) {
35006
+ const lineInFile = i - file.startLine;
35007
+ lineToFileMap.set(i, { file, lineInFile });
35008
+ }
35009
+ }
35010
+ });
35011
+ // 处理单个错误块:替换路径、行号,调整代码片段行号
35012
+ function processBlock(block) {
35013
+ // 匹配错误头: 可选的 "N. " 前缀 + "filepath: message (line:col)"
35014
+ const headerMatch = block.match(/^((?:\d+\.\s+)?)(.*?):\s+(.*?)\((\d+):(\d+)\)/);
35015
+ if (!headerMatch)
35016
+ return block;
35017
+ const [fullHeader, prefix, , message, lineStr, colStr] = headerMatch;
35018
+ const originalLine = parseInt(lineStr, 10);
35019
+ const fileInfo = lineToFileMap.get(originalLine);
35020
+ if (!fileInfo)
35021
+ return block;
35022
+ const { file, lineInFile } = fileInfo;
35023
+ const lineOffset = originalLine - lineInFile;
35024
+ // 替换错误头中的路径和行号
35025
+ let mapped = block.replace(fullHeader, `${prefix}${file.path}: ${message}(${lineInFile}:${colStr})`);
35026
+ // 收集代码片段中所有行号并计算映射后的值
35027
+ const snippetNumbers = [];
35028
+ const collectRegex = /^([> ]*?)(\d+)(\s*\|)/gm;
35029
+ let m;
35030
+ while ((m = collectRegex.exec(mapped)) !== null) {
35031
+ snippetNumbers.push(parseInt(m[2], 10) - lineOffset);
35032
+ }
35033
+ // 替换代码片段中的行号,保持对齐
35034
+ if (snippetNumbers.length > 0) {
35035
+ const maxWidth = Math.max(...snippetNumbers.map((n) => String(n).length));
35036
+ let idx = 0;
35037
+ mapped = mapped.replace(/^([> ]*?)(\d+)(\s*\|)/gm, (fullMatch, lead) => {
35038
+ const newNum = snippetNumbers[idx++];
35039
+ if (newNum <= 0)
35040
+ return fullMatch;
35041
+ const paddedNum = String(newNum).padStart(maxWidth);
35042
+ return lead.includes('>') ? `> ${paddedNum} |` : ` ${paddedNum} |`;
35043
+ });
35044
+ }
35045
+ return mapped;
35046
+ }
35047
+ // 按编号前缀分割为独立错误块,分别处理
35048
+ const parts = errorMessage.split(/(?=^\d+\.\s)/m);
35049
+ return parts.map(processBlock).join('');
35050
+ }
35051
+
34985
35052
  /**
34986
35053
  * 检查命令 - 检查 NASL 代码的语法和语义
34987
35054
  */
@@ -35003,6 +35070,13 @@ async function check(entry, options) {
35003
35070
  }
35004
35071
  if (!result && fullNaturalTS) {
35005
35072
  result = (await checkApi(fullNaturalTS, config)).trim();
35073
+ // 如果有错误,尝试映射回原始文件
35074
+ if (result) {
35075
+ result = mapErrorToSourceFile({
35076
+ errorMessage: result,
35077
+ collectedFiles,
35078
+ });
35079
+ }
35006
35080
  }
35007
35081
  const checkResult = {
35008
35082
  success: !result,