Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions src/utils/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,29 @@ export function findExample(name: string): FileInfo | null {
return match || null;
}

/**
* Get numeric priority for a search result (lower = higher priority).
* SDK sources rank above example apps.
*/
export function getResultPriority(result: SearchResult): number {
const { repo, file } = result;

if (repo === "aztec-packages") {
if (/\baztec-nr\b/.test(file) || /\byarn-project\b/.test(file)) return 1;
if (/\bnoir-contracts\b/.test(file)) return 2;
// Other aztec-packages paths (boxes, playground, etc.)
return 4;
}

if (repo === "noir") {
if (/\bnoir_stdlib\b/.test(file)) return 3;
return 4;
}

// Example apps / community repos
return 5;
}

// --- Helper functions ---

/**
Expand All @@ -197,8 +220,6 @@ function parseRgOutput(output: string, maxResults: number): SearchResult[] {
const lines = output.split("\n").filter(Boolean);

for (const line of lines) {
if (results.length >= maxResults) break;

// Format: /path/to/file:linenum:content
const match = line.match(/^(.+?):(\d+):(.*)$/);
if (match) {
Expand All @@ -215,7 +236,8 @@ function parseRgOutput(output: string, maxResults: number): SearchResult[] {
}
}

return results;
results.sort((a, b) => getResultPriority(a) - getResultPriority(b));
return results.slice(0, maxResults);
}

function manualSearch(
Expand Down Expand Up @@ -243,15 +265,11 @@ function manualSearch(
}

for (const file of files) {
if (results.length >= maxResults) break;

try {
const content = readFileSync(file, "utf-8");
const lines = content.split("\n");

for (let i = 0; i < lines.length; i++) {
if (results.length >= maxResults) break;

if (searchRegex.test(lines[i])) {
const relativePath = relative(REPOS_DIR, file);
const repoPart = relativePath.split("/")[0];
Expand All @@ -275,7 +293,8 @@ function manualSearch(
// Globby error, return empty
}

return results;
results.sort((a, b) => getResultPriority(a) - getResultPriority(b));
return results.slice(0, maxResults);
}

function findContracts(basePath: string, repoName: string): FileInfo[] {
Expand Down
81 changes: 81 additions & 0 deletions tests/utils/search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
readFile,
findExample,
getFileType,
getResultPriority,
} from "../../src/utils/search.js";

const mockExecSync = vi.mocked(execSync);
Expand Down Expand Up @@ -365,3 +366,83 @@ describe("findExample", () => {
expect(result).toBeNull();
});
});

describe("getResultPriority", () => {
it("ranks aztec-nr / yarn-project as highest priority (1)", () => {
expect(getResultPriority({ repo: "aztec-packages", file: "aztec-packages/yarn-project/aztec.js/src/main.ts", content: "", line: 1 })).toBe(1);
expect(getResultPriority({ repo: "aztec-packages", file: "aztec-packages/aztec-nr/aztec/src/lib.nr", content: "", line: 1 })).toBe(1);
});

it("ranks noir-contracts as priority 2", () => {
expect(getResultPriority({ repo: "aztec-packages", file: "aztec-packages/noir-projects/noir-contracts/token/src/main.nr", content: "", line: 1 })).toBe(2);
});

it("ranks noir_stdlib as priority 3", () => {
expect(getResultPriority({ repo: "noir", file: "noir/noir_stdlib/src/hash.nr", content: "", line: 1 })).toBe(3);
});

it("ranks other aztec-packages and noir paths as priority 4", () => {
expect(getResultPriority({ repo: "aztec-packages", file: "aztec-packages/boxes/token/src/main.nr", content: "", line: 1 })).toBe(4);
expect(getResultPriority({ repo: "noir", file: "noir/tooling/nargo/src/lib.rs", content: "", line: 1 })).toBe(4);
});

it("ranks example repos as lowest priority (5)", () => {
expect(getResultPriority({ repo: "aztec-examples", file: "aztec-examples/token/src/main.nr", content: "", line: 1 })).toBe(5);
expect(getResultPriority({ repo: "aztec-starter", file: "aztec-starter/src/main.nr", content: "", line: 1 })).toBe(5);
expect(getResultPriority({ repo: "gregoswap", file: "gregoswap/src/main.nr", content: "", line: 1 })).toBe(5);
});
});

describe("search result sorting", () => {
it("sorts ripgrep results by source priority", () => {
mockExistsSync.mockReturnValue(true);
mockExecSync.mockReturnValue(
"/fake/repos/gregoswap/src/main.nr:1:fn transfer() {\n" +
"/fake/repos/aztec-packages/yarn-project/aztec.js/src/main.ts:5:fn transfer() {\n" +
"/fake/repos/aztec-examples/token/src/main.nr:3:fn transfer() {\n" +
"/fake/repos/aztec-packages/noir-projects/noir-contracts/token/src/main.nr:10:fn transfer() {\n" +
"/fake/repos/noir/noir_stdlib/src/hash.nr:7:fn transfer() {\n"
);

const results = searchCode("transfer");
expect(results[0].repo).toBe("aztec-packages");
expect(results[0].file).toContain("yarn-project");
expect(results[1].repo).toBe("aztec-packages");
expect(results[1].file).toContain("noir-contracts");
expect(results[2].repo).toBe("noir");
expect(results[2].file).toContain("noir_stdlib");
expect(results[3].repo).toBe("gregoswap");
expect(results[4].repo).toBe("aztec-examples");
});

it("sorts manual search results by source priority", () => {
mockExistsSync.mockReturnValue(true);
mockExecSync.mockImplementation(() => { throw new Error("rg not found"); });
mockGlobbySync.mockReturnValue([
"/fake/repos/aztec-starter/src/main.nr",
"/fake/repos/aztec-packages/yarn-project/aztec.js/src/lib.nr",
]);
mockReadFileSync
.mockReturnValueOnce("fn transfer() {" as any)
.mockReturnValueOnce("fn transfer() {" as any);

const results = searchCode("transfer");
expect(results).toHaveLength(2);
expect(results[0].repo).toBe("aztec-packages");
expect(results[1].repo).toBe("aztec-starter");
});

it("applies sorting before maxResults limit", () => {
mockExistsSync.mockReturnValue(true);
mockExecSync.mockReturnValue(
"/fake/repos/gregoswap/src/a.nr:1:match\n" +
"/fake/repos/aztec-examples/src/b.nr:2:match\n" +
"/fake/repos/aztec-packages/yarn-project/c.nr:3:match\n"
);

const results = searchCode("match", { maxResults: 2 });
expect(results).toHaveLength(2);
// SDK result should be kept even though it appeared last in raw output
expect(results[0].repo).toBe("aztec-packages");
});
});