mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-28 22:52:00 +08:00
fix(go): a comment directive like //go:embed is not part of a declaration's doc (#2679)
go doc leaves comment directives out of a doc comment's text: a // comment with no space after the slashes that is //line, //extern or //export followed by text, or that opens with a lowercase word, a colon and a lowercase letter or digit, like //go:embed static or //nolint:errcheck (go/ast's isDirective). Both extractors kept them, so prometheus's testsFs had the docstring "go:embed testdata", etcd's store.restore "nolint:unparam", and a doc comment with a directive under it ended in that directive. Go now drops directives from the docstring's text through a Go-only extractor option (docstringSkipsDirectives in TS; the kernel's Go docstring helper becomes preceding_go_doc_comment, which applies all three Go rules). A directive still counts as a comment when deciding where the doc comment starts, as in go/parser, so a declaration whose only comment is a directive has no docstring. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
23f728fac2
commit
f43432c86a
@@ -261,4 +261,7 @@ export const goExtractor: LanguageExtractor = {
|
||||
// line ends it, as go doc reads it: a banner or a note above that blank line
|
||||
// documents nothing.
|
||||
docstringSkipsDetachedComments: true,
|
||||
// A directive Go tools read, like `//go:embed static` or
|
||||
// `//nolint:errcheck`, is not part of the doc comment go doc shows.
|
||||
docstringSkipsDirectives: true,
|
||||
};
|
||||
|
||||
@@ -145,13 +145,19 @@ function cleanCommentMarkers(comment: string): string {
|
||||
* a blank line ends the docstring, and a comment that ends on the
|
||||
* declaration's own line documents nothing. That is Go's doc comment, the one
|
||||
* go doc shows. Default: off.
|
||||
*
|
||||
* `skipDirectives` leaves the comment directives Go tools read, like
|
||||
* `//go:embed static` or `//nolint:errcheck`, out of the docstring's text, as
|
||||
* go doc does. They still count as comments when the other options decide
|
||||
* where the docstring starts. Default: off.
|
||||
*/
|
||||
export function getPrecedingDocstring(
|
||||
node: SyntaxNode,
|
||||
source: string,
|
||||
stepOver: readonly string[] = [],
|
||||
skipTrailing = false,
|
||||
skipDetached = false
|
||||
skipDetached = false,
|
||||
skipDirectives = false
|
||||
): string | undefined {
|
||||
// Climb out of any wrapper(s) so a comment preceding the WHOLE construct
|
||||
// (export-, decorator-, or const-arrow-wrapped) is reachable as a sibling.
|
||||
@@ -206,16 +212,31 @@ export function getPrecedingDocstring(
|
||||
}
|
||||
first = start;
|
||||
}
|
||||
if (first === comments.length) return undefined;
|
||||
const docComments = comments
|
||||
.slice(first)
|
||||
.filter((c) => !skipDirectives || !isDirective(getNodeText(c, source)));
|
||||
if (docComments.length === 0) return undefined;
|
||||
|
||||
// Strip each comment's syntax markers (language-aware), then join.
|
||||
return comments
|
||||
.slice(first)
|
||||
return docComments
|
||||
.map((c) => cleanCommentMarkers(getNodeText(c, source)))
|
||||
.join('\n')
|
||||
.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a comment is a directive Go tools read, which go doc leaves out of a
|
||||
* doc comment's text (go/ast's isDirective): a `//` comment with no space
|
||||
* after the slashes that is `//line `, `//extern ` or `//export ` followed by
|
||||
* text, or that opens with a lowercase word, a colon and a lowercase letter or
|
||||
* digit, like `//go:embed static` or `//nolint:errcheck`.
|
||||
*/
|
||||
function isDirective(comment: string): boolean {
|
||||
if (!comment.startsWith('//')) return false;
|
||||
const text = comment.slice(2);
|
||||
return /^(?:line|extern|export) /.test(text) || /^[a-z0-9]+:[a-z0-9]/.test(text);
|
||||
}
|
||||
|
||||
/** Whether code comes before `node` on the line it starts on. */
|
||||
function followsCodeOnItsLine(node: SyntaxNode, source: string): boolean {
|
||||
let i = node.startIndex;
|
||||
|
||||
@@ -198,6 +198,12 @@ export interface LanguageExtractor {
|
||||
* declaration documents nothing.
|
||||
*/
|
||||
docstringSkipsDetachedComments?: boolean;
|
||||
/**
|
||||
* Leave out of a docstring's text the comment directives Go tools read, like
|
||||
* `//go:embed static`, `//nolint:errcheck` or `//export F`, as go doc does:
|
||||
* a declaration whose only comment is a directive has no doc.
|
||||
*/
|
||||
docstringSkipsDirectives?: boolean;
|
||||
/**
|
||||
* Node types that may stand between a declaration and the decorators written
|
||||
* before it without ending the scan for them. Dart writes comments there
|
||||
|
||||
@@ -542,7 +542,8 @@ export class TreeSitterExtractor {
|
||||
this.source,
|
||||
this.extractor?.docstringStepOverTypes,
|
||||
this.extractor?.docstringSkipsTrailingComments,
|
||||
this.extractor?.docstringSkipsDetachedComments
|
||||
this.extractor?.docstringSkipsDetachedComments,
|
||||
this.extractor?.docstringSkipsDirectives
|
||||
);
|
||||
const body = this.extractor?.getBodyDocstring?.(node, this.source);
|
||||
if (preceding && body) return `${preceding}\n\n${body}`;
|
||||
|
||||
Reference in New Issue
Block a user