Skip to content

Commit bfc441e

Browse files
committed
Add (direct) method references query
1 parent 2731cf5 commit bfc441e

6 files changed

Lines changed: 223 additions & 7 deletions

File tree

src/main/java/net/neoforged/waifu/web/api/PlatformCDNProxy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static void proxy(Context ctx) throws IOException {
2929
}
3030

3131
String host = uri.getHost();
32-
if (host == null || !(host.equals("edge.forgecdn.net") || host.equals("cdn.modrinth.net"))) {
32+
if (host == null || !(host.equals("edge.forgecdn.net") || host.equals("cdn.modrinth.com"))) {
3333
ctx.status(403).result("Domain not allowed");
3434
return;
3535
}

web-interface/app/pages/queries/index.vue

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
<v-container>
33
<h2>Classes</h2>
44
<v-card
5-
title="Mixins targetting Classes in Package"
6-
to="mixins-package" router>
5+
title="Annotated Classes"
6+
to="annotated-classes" router>
77
<template v-slot:text>
8-
Find mixins that target classes in a certain package (and its subpackages).
8+
Find the classes annotated with a given annotation.
99
</template>
1010
</v-card>
1111
<br>
@@ -18,10 +18,18 @@
1818
</v-card>
1919
<br>
2020
<v-card
21-
title="Annotated Classes"
22-
to="annotated-classes" router>
21+
title="Method References"
22+
to="method-references" router>
2323
<template v-slot:text>
24-
Find the classes annotated with a given annotation.
24+
Find direct references to a given method.
25+
</template>
26+
</v-card>
27+
<br>
28+
<v-card
29+
title="Mixins targetting Classes in Package"
30+
to="mixins-package" router>
31+
<template v-slot:text>
32+
Find mixins that target classes in a certain package (and its subpackages).
2533
</template>
2634
</v-card>
2735

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<template>
2+
<v-container>
3+
<query-component
4+
v-model:version="version"
5+
:on-load="load"
6+
:on-reset="() => loading = true"
7+
:additionalProperties="{'Class': clazz, 'Method': method}">
8+
<template v-slot:result-display>
9+
<v-card title="Results" flat>
10+
<template v-slot:text>
11+
<v-row>
12+
<v-col sm="8" cols="12">
13+
<v-text-field
14+
v-model="search"
15+
label="Search"
16+
prepend-inner-icon="mdi-magnify"
17+
variant="outlined"
18+
density="compact"
19+
hide-details
20+
single-line
21+
clearable
22+
></v-text-field>
23+
</v-col>
24+
25+
<v-col sm="4" cols="12">
26+
<v-select
27+
clearable
28+
v-model="groups.groupBy.value"
29+
label="Group by"
30+
density="compact"
31+
:items="groups.names"
32+
hide-details
33+
/>
34+
</v-col>
35+
</v-row>
36+
</template>
37+
38+
<v-data-table density="compact"
39+
:items="items"
40+
:loading="loading"
41+
:search="search"
42+
:group-by="groups.items.value"
43+
:headers="headers"
44+
items-per-page="25"
45+
>
46+
<template v-for="head in headers" v-slot:[`header.${head.key}`]="{ column }">
47+
<b>{{ column.title }}</b>
48+
</template>
49+
<template v-slot:item.mod.name="{ item, value }">
50+
<v-btn density="compact" color="primary" variant="text" border="false" @click="selectedMod = item.mod.id">{{ value }}</v-btn>
51+
</template>
52+
<template v-slot:item.cls="{ item, value }">
53+
<span @click="selectedFile = {mod: item.mod.id, file: getClassSourceFileName(item.cls)}">{{ value }}</span>
54+
</template>
55+
</v-data-table>
56+
</v-card>
57+
</template>
58+
59+
<template v-slot:form>
60+
<v-text-field
61+
v-model="clazz"
62+
label="Class"
63+
placeholder="com.example.ExampleClass"
64+
density="compact"
65+
variant="underlined"
66+
/>
67+
<v-text-field
68+
v-model="method"
69+
label="Method"
70+
placeholder="exampleMethod"
71+
density="compact"
72+
variant="underlined"
73+
/>
74+
<div class="text-left">
75+
<b>Direct</b> references to the method with the given name, from the given class will be returned.
76+
</div>
77+
</template>
78+
</query-component>
79+
<mod-information-dialog :version="version" v-model:modId="selectedMod" />
80+
<file-source-dialog :version="version" v-model:selected-file="selectedFile" />
81+
</v-container>
82+
</template>
83+
84+
<script setup lang="ts">
85+
import QueryComponent from "~/components/query-component.vue";
86+
import ModInformationDialog from "~/components/mod-information-dialog.vue";
87+
import {type FileSelection, getClassSourceFileName, grouper} from "~/utils/utils";
88+
import {METHOD_REFERENCES} from "~~/graphql-requests/methods";
89+
90+
definePageMeta({
91+
title: 'Method References Query'
92+
})
93+
94+
const queryClient = useQueryClient()
95+
96+
const version = queryClient.version
97+
const clazz = queryClient.queryParam('class')
98+
const method = queryClient.queryParam('method')
99+
100+
const selectedMod = ref<number>()
101+
const selectedFile = ref<{
102+
mod: number,
103+
file: FileSelection
104+
}>()
105+
106+
const items = ref([] as any[])
107+
const loading = ref(true)
108+
const search = ref(undefined)
109+
110+
const headers = [
111+
{title: 'Mod', key: 'mod.name'},
112+
{title: 'Class', key: 'cls'},
113+
{title: 'Referenced Method', key: 'mtd'}
114+
]
115+
116+
const groups = grouper(headers)
117+
118+
const load = () => {
119+
fetchWithVersion(queryClient.apollo, METHOD_REFERENCES, {
120+
class: clazz.value!!.replaceAll('.', '/'),
121+
methodFilter: {
122+
name: {
123+
equals: method.value!!
124+
}
125+
}
126+
}, version.value)
127+
.then((result) => {
128+
const newValues = [] as any[]
129+
result?.gameVersion?.class?.methods?.forEach(mtd => {
130+
mtd.references.forEach(ref => {
131+
newValues.push({
132+
mod: ref.owner.mod,
133+
cls: ref.owner.name,
134+
mtd: mtd.name + mtd.descriptor
135+
})
136+
})
137+
})
138+
items.value = newValues
139+
loading.value = false
140+
})
141+
}
142+
143+
</script>

web-interface/app/utils/utils.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import JSZip from "jszip";
22
import {decompile} from "@run-slicer/vf";
3+
import type {DataTableSortItem} from "vuetify/framework";
34

45
export function getCookieByName(key: string): string | undefined {
56
return document.cookie
@@ -57,3 +58,26 @@ export function getRecipeSourceFileName(recipeName: string): FileSelection {
5758
}
5859
}
5960
}
61+
62+
export function grouper(groups: {
63+
title: string,
64+
key: string
65+
}[]): {
66+
groupBy: Ref<string | undefined>,
67+
names: string[],
68+
items: Ref<DataTableSortItem[]>
69+
} {
70+
const groupBy = ref<string | undefined>(undefined)
71+
const groupByConfiguration = computed<DataTableSortItem[]>(() => {
72+
if (!groupBy.value || groupBy.value == 'None') {
73+
return []
74+
} else {
75+
return [{key: groups.filter(g => g.title == groupBy.value)[0]!!.key}]
76+
}
77+
})
78+
return {
79+
groupBy: groupBy,
80+
items: groupByConfiguration,
81+
names: groups.map(g => g.title)
82+
}
83+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import gql from "graphql-tag";
2+
import type {TypedDocumentNode} from "@apollo/client";
3+
import type {
4+
GetMethodReferencesQuery, GetMethodReferencesQueryVariables
5+
} from "./types/__generated__/graphql";
6+
7+
export const METHOD_REFERENCES: TypedDocumentNode<
8+
GetMethodReferencesQuery,
9+
GetMethodReferencesQueryVariables
10+
> = gql`
11+
query GetMethodReferences($version: String!, $loader: Loader!, $class: String!, $methodFilter: MethodPredicate!, $filter: ReferencePredicate) {
12+
gameVersion(loader: $loader, version: $version) {
13+
class(name: $class) {
14+
methods(where: $methodFilter) {
15+
name
16+
descriptor
17+
references(where: $filter) {
18+
owner {
19+
mod {
20+
id
21+
name
22+
}
23+
name
24+
}
25+
}
26+
}
27+
}
28+
}
29+
}
30+
`;

web-interface/graphql-requests/types/__generated__/graphql.ts

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)