UNPKG

chrome-devtools-frontend

Version:
78 lines (70 loc) 2.94 kB
// Copyright 2025 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as CodeMirror from '../../../third_party/codemirror.next/codemirror.next.js'; const LINE_COMMENT_PATTERN = /^(?:\/\/|#)\s*/; const BLOCK_COMMENT_START_PATTERN = /^\/\*+\s*/; const BLOCK_COMMENT_END_PATTERN = /\s*\*+\/$/; const BLOCK_COMMENT_LINE_PREFIX_PATTERN = /^\s*\*\s?/; function findLastNonWhitespacePos(state: CodeMirror.EditorState, cursorPosition: number): number { const line = state.doc.lineAt(cursorPosition); const textBefore = line.text.substring(0, cursorPosition - line.from); const effectiveEnd = line.from + textBefore.trimEnd().length; return effectiveEnd; } function resolveCommentNode(state: CodeMirror.EditorState, cursorPosition: number): CodeMirror.SyntaxNode|undefined { const tree = CodeMirror.syntaxTree(state); const lookupPos = findLastNonWhitespacePos(state, cursorPosition); // Find the innermost syntax node at the last non-whitespace character position. // The bias of -1 makes it check the character to the left of the position. const node = tree.resolveInner(lookupPos, -1); const nodeType = node.type.name; // Check if the node type is a comment AND the cursor is within the node's range. if (nodeType.includes('Comment') && cursorPosition >= node.to) { if (!nodeType.includes('BlockComment')) { return node; } // An unclosed block comment can result in the parser inserting an error. let hasInternalError = false; tree.iterate({ from: node.from, to: node.to, enter: n => { if (n.type.isError) { hasInternalError = true; return false; } return true; }, }); return hasInternalError ? undefined : node; } return; } function extractBlockComment(rawText: string): string|undefined { // Remove /* and */, whitespace, and common leading asterisks on new lines let cleaned = rawText.replace(BLOCK_COMMENT_START_PATTERN, '').replace(BLOCK_COMMENT_END_PATTERN, ''); // Remove leading " * " from multi-line block comments cleaned = cleaned.split('\n').map(line => line.replace(BLOCK_COMMENT_LINE_PREFIX_PATTERN, '')).join('\n').trim(); return cleaned; } function extractLineComment(rawText: string): string { return rawText.replace(LINE_COMMENT_PATTERN, '').trim(); } export class AiCodeGenerationParser { static extractCommentText(state: CodeMirror.EditorState, cursorPosition: number): string|undefined { const node = resolveCommentNode(state, cursorPosition); if (!node) { return; } const nodeType = node.type.name; const rawText = state.doc.sliceString(node.from, node.to); if (nodeType.includes('LineComment')) { return extractLineComment(rawText); } if (nodeType.includes('BlockComment')) { return extractBlockComment(rawText); } return rawText; } }