Skip to content
Merged
9 changes: 5 additions & 4 deletions tools/apiview/parsers/rust-api-parser/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# 1.1.0

Enhanced rendering of `use` items to more closely match the rustdoc (docs.rs) HTML view:
- Improved handling of `use` items and module re-exports with better tracking to prevent duplication
- Refactored module processing with enhanced sorting and organization of child items
- Fixed bugs and improved utility functions for better code maintainability
- Enhanced rendering of `use` items to more closely match the rustdoc (docs.rs) HTML view:
- Improved handling of `use` items and module re-exports with better tracking to prevent duplication
- Refactored module processing with enhanced sorting and organization of child items
- Fixed bugs and improved utility functions for better code maintainability
- Updated `ReviewLine#LineId`s to stable, meaningful identifiers rather than relying on the dynamic rustdoc ids.

# 1.0.1

Expand Down
7 changes: 5 additions & 2 deletions tools/apiview/parsers/rust-api-parser/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CodeFile, TokenKind } from "./models/apiview-models";
import { Crate, FORMAT_VERSION, Id } from "../rustdoc-types/output/rustdoc-types";
import { externalReferencesLines } from "./process-items/utils/externalReexports";
import { sortExternalItems } from "./process-items/utils/sorting";
import { updateReviewLinesWithStableLineIds } from "./utils/lineIdUtils";

let apiJson: Crate;
export const processedItems = new Set<number>();
Expand Down Expand Up @@ -67,8 +68,8 @@ function processExternalReferences(codeFile: CodeFile): void {
*/
function buildCodeFile(): CodeFile {
const codeFile: CodeFile = {
PackageName: apiJson.index[apiJson.root].name || "unknown",
PackageVersion: apiJson["crate_version"] || "unknown",
PackageName: apiJson.index[apiJson.root].name || "unknown_root_package_name",
PackageVersion: apiJson["crate_version"] || "unknown_crate_version",
ParserVersion: "1.1.0",
Language: "Rust",
ReviewLines: [],
Expand All @@ -77,6 +78,8 @@ function buildCodeFile(): CodeFile {

processRootItem(codeFile);
processExternalReferences(codeFile);

updateReviewLinesWithStableLineIds(codeFile.ReviewLines);
return codeFile;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Item } from "../../rustdoc-types/output/rustdoc-types";
import { createDocsReviewLines } from "./utils/generateDocReviewLine";
import { typeToReviewTokens } from "./utils/typeToReviewTokens";
import { isAssocConstItem } from "./utils/typeGuards";
import { lineIdMap } from "../utils/lineIdUtils";

/**
* Processes an associated constant item and returns ReviewLine objects.
Expand Down Expand Up @@ -30,7 +31,7 @@ export function processAssocConst(item: Item): ReviewLine[] | null {
// Add name
reviewLine.Tokens.push({
Kind: TokenKind.MemberName,
Value: item.name || "unknown",
Value: item.name || "unknown_assoc_const",
HasSuffixSpace: false,
RenderClasses: ["interface"],
});
Expand Down Expand Up @@ -62,5 +63,6 @@ export function processAssocConst(item: Item): ReviewLine[] | null {
});

reviewLines.push(reviewLine);
lineIdMap.set(item.id.toString(), `const_${item.name}`);
return reviewLines;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { createDocsReviewLines } from "./utils/generateDocReviewLine";
import { typeToReviewTokens } from "./utils/typeToReviewTokens";
import { isAssocTypeItem } from "./utils/typeGuards";
import { createGenericBoundTokens, processGenerics } from "./utils/processGenerics";
import { lineIdMap } from "../utils/lineIdUtils";

/**
* Processes an associated type item and returns ReviewLine objects.
Expand Down Expand Up @@ -32,7 +33,7 @@ export function processAssocType(item: Item): ReviewLine[] | null {
// Add name
reviewLine.Tokens.push({
Kind: TokenKind.MemberName,
Value: item.name || "unknown",
Value: item.name || "unknown_assoc_type",
HasSuffixSpace: false,
RenderClasses: ["interface"],
});
Expand Down Expand Up @@ -65,5 +66,6 @@ export function processAssocType(item: Item): ReviewLine[] | null {
});

reviewLines.push(reviewLine);
lineIdMap.set(item.id.toString(), `type_${item.name}`);
return reviewLines;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Item } from "../../rustdoc-types/output/rustdoc-types";
import { createDocsReviewLines } from "./utils/generateDocReviewLine";
import { isConstantItem } from "./utils/typeGuards";
import { typeToReviewTokens } from "./utils/typeToReviewTokens";
import { lineIdMap } from "../utils/lineIdUtils";

export function processConstant(item: Item) {
if (!isConstantItem(item)) return;
Expand All @@ -21,7 +22,7 @@ export function processConstant(item: Item) {
});
reviewLine.Tokens.push({
Kind: TokenKind.MemberName,
Value: item.name || "null",
Value: item.name || "unknown_const",
HasSuffixSpace: false,
NavigateToId: item.id.toString(),
NavigationDisplayName: item.name,
Expand All @@ -38,7 +39,7 @@ export function processConstant(item: Item) {
});
reviewLine.Tokens.push({
Kind: TokenKind.Text,
Value: item.inner.constant.const.expr || "null",
Value: item.inner.constant.const.expr || "unknown_const_expr",
HasSuffixSpace: false,
});
reviewLine.Tokens.push({
Expand All @@ -56,5 +57,6 @@ export function processConstant(item: Item) {
});
}
reviewLines.push(reviewLine);
lineIdMap.set(item.id.toString(), `const_${item.name}`);
return reviewLines;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import { createDocsReviewLines } from "./utils/generateDocReviewLine";
import { processGenerics } from "./utils/processGenerics";
import { isEnumItem } from "./utils/typeGuards";
import { getAPIJson } from "../main";
import { lineIdMap } from "../utils/lineIdUtils";

export function processEnum(item: Item): ReviewLine[] {
if (!isEnumItem(item)) return [];
const apiJson = getAPIJson();
const reviewLines: ReviewLine[] = item.docs ? createDocsReviewLines(item) : [];

lineIdMap.set(item.id.toString(), `enum_${item.name}`);
// Process derives and impls
let implResult: ImplProcessResult;
if (item.inner.enum.impls) {
Expand All @@ -25,7 +27,6 @@ export function processEnum(item: Item): ReviewLine[] {

if (implResult.deriveTokens.length > 0) {
const deriveTokensLine: ReviewLine = {
LineId: item.id.toString() + "_derive",
Tokens: implResult.deriveTokens,
RelatedToLine: item.id.toString(),
};
Expand All @@ -39,7 +40,7 @@ export function processEnum(item: Item): ReviewLine[] {

enumLine.Tokens.push({
Kind: TokenKind.MemberName,
Value: item.name || "null",
Value: item.name || "unknown_enum",
NavigateToId: item.id.toString(),
NavigationDisplayName: item.name || undefined,
RenderClasses: ["enum"],
Expand Down Expand Up @@ -67,12 +68,13 @@ export function processEnum(item: Item): ReviewLine[] {
if (item.inner.enum.variants) {
enumLine.Children = item.inner.enum.variants.map((variant: number) => {
const variantItem = apiJson.index[variant];
lineIdMap.set(variantItem.id.toString(), `variant_${variantItem.name}`);
return {
LineId: variantItem.id.toString(),
Tokens: [
{
Kind: TokenKind.Text,
Value: variantItem.name || "null",
Value: variantItem.name || "unknown_variant",
HasSuffixSpace: false,
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ReviewLine, TokenKind } from "../models/apiview-models";
import { Item } from "../../rustdoc-types/output/rustdoc-types";
import { createDocsReviewLines } from "./utils/generateDocReviewLine";
import { isExternTypeItem } from "./utils/typeGuards";
import { lineIdMap } from "../utils/lineIdUtils";

/**
* Processes an extern type item and returns ReviewLine objects.
Expand Down Expand Up @@ -30,7 +31,7 @@ export function processExternType(item: Item): ReviewLine[] | null {
// Add name
reviewLine.Tokens.push({
Kind: TokenKind.MemberName,
Value: item.name || "unknown",
Value: item.name || "unknown_extern_type",
});

// Add semicolon
Expand All @@ -40,5 +41,6 @@ export function processExternType(item: Item): ReviewLine[] | null {
});

reviewLines.push(reviewLine);
lineIdMap.set(item.id.toString(), `extern_type_${item.name}`);
return reviewLines;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { createDocsReviewLines } from "./utils/generateDocReviewLine";
import { processGenerics } from "./utils/processGenerics";
import { isFunctionItem } from "./utils/typeGuards";
import { typeToReviewTokens } from "./utils/typeToReviewTokens";
import { lineIdMap } from "../utils/lineIdUtils";

/**
* Processes the function header and adds modifiers and ABI information to the tokens
Expand Down Expand Up @@ -83,7 +84,7 @@ export function processFunction(item: Item): ReviewLine[] {

reviewLine.Tokens.push({
Kind: TokenKind.MemberName,
Value: item.name || "null",
Value: item.name || "unknown_fn",
HasSuffixSpace: false,
RenderClasses: ["method"],
NavigateToId: item.id.toString(),
Expand Down Expand Up @@ -175,5 +176,6 @@ export function processFunction(item: Item): ReviewLine[] {
});
}
reviewLines.push(reviewLine);
lineIdMap.set(item.id.toString(), `function_${item.name}`);
return reviewLines;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { typeToReviewTokens } from "./utils/typeToReviewTokens";
import { processGenericArgs, processGenerics } from "./utils/processGenerics";
import { getAPIJson } from "../main";
import { lineIdMap } from "../utils/lineIdUtils";

// Interface for the result of processing implementations
export interface ImplProcessResult {
Expand Down Expand Up @@ -60,7 +61,7 @@ export function processAutoTraitImpls(impls: number[]): ReviewToken[] {
}

// Process manually implemented trait implementations
function processOtherTraitImpls(impls: number[]): ReviewLine[] {
function processOtherTraitImpls(impls: number[], prefixId: string): ReviewLine[] {
const apiJson = getAPIJson();
const traitImpls = getFilteredImpls(impls, isManualTraitImpl);
return traitImpls.flatMap((implItem) => {
Expand All @@ -69,33 +70,35 @@ function processOtherTraitImpls(impls: number[]): ReviewLine[] {
// Get the type that the trait is implemented for
const parentName = typeToReviewTokens(implItem.inner.impl.for);

const implId = implItem.id.toString();
const lineId = implItem.id.toString() + "_" + prefixId;
// Process provided trait methods that are mentioned but not explicitly implemented
const providedTraitMethods: ReviewLine[] = implItem.inner.impl.provided_trait_methods.map(
(method) => ({
LineId: implId + "_impl_" + method,
Tokens: [
{ Kind: TokenKind.Keyword, Value: "pub" },
{ Kind: TokenKind.Keyword, Value: "fn" },
{
Kind: TokenKind.MemberName,
Value: method,
RenderClasses: ["method"],
HasSuffixSpace: false,
},
{ Kind: TokenKind.Punctuation, Value: ";" },
{
Kind: TokenKind.Comment,
Value: "// provided trait method",
HasSuffixSpace: false,
},
],
}),
(method) => {
return {
Tokens: [
{ Kind: TokenKind.Keyword, Value: "pub" },
{ Kind: TokenKind.Keyword, Value: "fn" },
{
Kind: TokenKind.MemberName,
Value: method,
RenderClasses: ["method"],
HasSuffixSpace: false,
},
{ Kind: TokenKind.Punctuation, Value: ";" },
{
Kind: TokenKind.Comment,
Value: "// provided trait method",
HasSuffixSpace: false,
},
],
RelatedToLine: lineId,
};
},
);
const implGenerics = processGenerics(implItem.inner.impl.generics);
// Create the main impl line with trait name and type
const reviewLineForImpl: ReviewLine = {
LineId: implId + "_impl",
LineId: lineId,
Tokens: [
{
Kind: TokenKind.Keyword,
Expand All @@ -108,7 +111,7 @@ function processOtherTraitImpls(impls: number[]): ReviewLine[] {
Value: (implItem.inner.impl.is_negative ? "!" : "") + implItem.inner.impl.trait.name,
HasPrefixSpace: true,
HasSuffixSpace: false,
NavigateToId: implId + "_impl",
NavigateToId: lineId,
// Create navigation display name by combining trait and type names
NavigationDisplayName:
implItem.inner.impl.trait.name + "_" + parentName.map((token) => token.Value).join(""),
Expand All @@ -132,8 +135,16 @@ function processOtherTraitImpls(impls: number[]): ReviewLine[] {
],
};

lineIdMap.set(
lineId,
prefixId +
reviewLineForImpl.Tokens.map((token) => token.Value)
.join("_")
.replace(/[^a-zA-Z0-9]+/g, ""),
);

const closingLine: ReviewLine = {
RelatedToLine: implItem.id.toString() + "_impl",
RelatedToLine: lineId,
Tokens: [{ Kind: TokenKind.Punctuation, Value: "}" }],
};

Expand Down Expand Up @@ -166,6 +177,8 @@ export function processImpl(
| (Item & { inner: { enum: Enum } })
| (Item & { inner: { union: Union } }),
): ImplProcessResult {
const linedId = item.id.toString() + "_impl";
lineIdMap.set(linedId, lineIdMap.get(item.id.toString()) + "_impl");
Comment thread
HarshaNalluru marked this conversation as resolved.
// Get all implementations associated with this item
const impls = getImplsFromItem(item);

Expand All @@ -176,35 +189,35 @@ export function processImpl(
// Process children first to check if they're empty
const children = processImpls(impls).filter((item) => item != null);

// Only create an implBlock if there are children
const implBlock: ReviewLine[] =
children.length === 0
? [] // Empty implBlock if no children
: [
// Create the main implementation line with type name
{
LineId: item.id.toString() + "_impl",
Tokens: [
{ Kind: TokenKind.Keyword, Value: "impl" },
{
Kind: TokenKind.MemberName,
Value: item.name || "null",
RenderClasses: ["interface"],
NavigateToId: item.id.toString() + "_impl",
NavigationDisplayName: item.name || undefined,
},
{ Kind: TokenKind.Punctuation, Value: "{" },
],
Children: children,
},
let implBlock: ReviewLine[] = [];
if (children.length > 0) {
// Only create an implBlock if there are children
implBlock = [
// Create the main implementation line with type name
{
LineId: linedId,
Tokens: [
{ Kind: TokenKind.Keyword, Value: "impl" },
{
RelatedToLine: item.id.toString() + "_impl",
Tokens: [{ Kind: TokenKind.Punctuation, Value: "}" }],
Kind: TokenKind.MemberName,
Value: item.name || "unknown_impl",
RenderClasses: ["interface"],
NavigateToId: linedId,
NavigationDisplayName: item.name || undefined,
},
];
{ Kind: TokenKind.Punctuation, Value: "{" },
],
Children: children,
},
{
RelatedToLine: linedId,
Tokens: [{ Kind: TokenKind.Punctuation, Value: "}" }],
},
];
}

// Process manual trait implementations (like impl Trait for Type { ... })
const traitImpls = processOtherTraitImpls(impls);
const traitImpls = processOtherTraitImpls(impls, item.name);

return { deriveTokens, implBlock, traitImpls };
}
Loading