Skip to content
This repository was archived by the owner on Jan 19, 2025. It is now read-only.

Commit faa656f

Browse files
GideonKoenigGideonKoeniglars-reimann
authored
feat(gui): implements links to methods in element description (#949)
* feat: meth lab is done, walter sends his regard * style: apply automatic fixes of linters Co-authored-by: GideonKoenig <[email protected]> Co-authored-by: GideonKoenig <[email protected]> Co-authored-by: Lars Reimann <[email protected]>
1 parent 4c61bdb commit faa656f

File tree

1 file changed

+62
-4
lines changed

1 file changed

+62
-4
lines changed

api-editor/gui/src/features/packageData/selectionView/DocumentationText.tsx

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ import { selectExpandDocumentationByDefault } from '../../ui/uiSlice';
2828
import { Link as RouterLink } from 'react-router-dom';
2929
import { PythonDeclaration } from '../model/PythonDeclaration';
3030
import { PythonPackage } from '../model/PythonPackage';
31+
import { Optional } from '../../../common/util/types';
32+
import { PythonFunction } from '../model/PythonFunction';
33+
import { PythonClass } from '../model/PythonClass';
34+
import { PythonParameter } from '../model/PythonParameter';
35+
import { PythonModule } from '../model/PythonModule';
3136

3237
interface DocumentationTextProps {
3338
declaration: PythonDeclaration;
@@ -87,9 +92,16 @@ export const DocumentationText: React.FC<DocumentationTextProps> = function ({ d
8792
// replace double colons with single colon
8893
.replaceAll(/::/gu, ':')
8994
// replace relative links to classes
90-
.replaceAll(/:class:`(\w*)`/gu, (_match, name) => resolveRelativeLink(declaration, name))
95+
.replaceAll(/:class:`(\w*)`/gu, (_match, name) =>
96+
resolveRelativeLink(declaration, name, DeclarationLevel.CLASS),
97+
)
9198
// replace relative links to functions
92-
.replaceAll(/:func:`(\w*)`/gu, (_match, name) => resolveRelativeLink(declaration, name))
99+
.replaceAll(/:func:`(\w*)`/gu, (_match, name) =>
100+
resolveRelativeLink(declaration, name, DeclarationLevel.FUNCTION),
101+
)
102+
.replaceAll(/:meth:`(\w*)`/gu, (_match, name) =>
103+
resolveRelativeLink(declaration, name, DeclarationLevel.FUNCTION),
104+
)
93105
// replace absolute links to modules
94106
.replaceAll(/:mod:`([\w.]*)`/gu, (_match, qualifiedName) => resolveAbsoluteLink(declaration, qualifiedName, 1))
95107
// replace absolute links to classes
@@ -147,12 +159,33 @@ export const DocumentationText: React.FC<DocumentationTextProps> = function ({ d
147159
);
148160
};
149161

150-
const resolveRelativeLink = function (currentDeclaration: PythonDeclaration, linkedDeclarationName: string): string {
151-
const parent = currentDeclaration.parent();
162+
const resolveRelativeLink = function (
163+
currentDeclaration: PythonDeclaration,
164+
linkedDeclarationName: string,
165+
targetLevel: DeclarationLevel,
166+
): string {
167+
let parent: Optional<PythonDeclaration> = currentDeclaration;
168+
do {
169+
parent = parent.parent();
170+
} while (
171+
parent &&
172+
Object.keys(DeclarationLevel)[getDeclarationLevel(parent)] >= Object.keys(DeclarationLevel)[targetLevel]
173+
);
174+
152175
if (!parent) {
153176
return linkedDeclarationName;
154177
}
155178

179+
if (targetLevel === DeclarationLevel.FUNCTION) {
180+
const grandparent = parent.parent();
181+
if (grandparent) {
182+
const sibling = grandparent.children().find((it) => it.name === linkedDeclarationName);
183+
if (sibling) {
184+
return `[${sibling.preferredQualifiedName()}](${sibling.id})`;
185+
}
186+
}
187+
}
188+
156189
const sibling = parent.children().find((it) => it.name === linkedDeclarationName);
157190
if (!sibling) {
158191
return linkedDeclarationName;
@@ -192,3 +225,28 @@ const resolveAbsoluteLink = function (
192225

193226
return `[${current.preferredQualifiedName()}](${current.id})`;
194227
};
228+
229+
const getDeclarationLevel = function (element: PythonDeclaration): DeclarationLevel {
230+
if (element instanceof PythonPackage) {
231+
return DeclarationLevel.PACKAGE;
232+
} else if (element instanceof PythonModule) {
233+
return DeclarationLevel.MODULE;
234+
} else if (element instanceof PythonClass) {
235+
return DeclarationLevel.CLASS;
236+
} else if (element instanceof PythonFunction) {
237+
return DeclarationLevel.FUNCTION;
238+
} else if (element instanceof PythonParameter) {
239+
return DeclarationLevel.PARAMETER;
240+
} else {
241+
return DeclarationLevel.DEFAULT;
242+
}
243+
};
244+
245+
enum DeclarationLevel {
246+
DEFAULT,
247+
PACKAGE,
248+
MODULE,
249+
CLASS,
250+
FUNCTION,
251+
PARAMETER,
252+
}

0 commit comments

Comments
 (0)