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

feat: description annotation #536

Merged
merged 28 commits into from
Jun 13, 2022
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9ec9ed3
feat: process description annotations in backend
lars-reimann Jun 3, 2022
2d18515
feat: update validation in backend
lars-reimann Jun 3, 2022
e129011
feat(backend): actually trigger processing
lars-reimann Jun 3, 2022
2cfafbc
style: apply automatic fixes of linters
lars-reimann Jun 3, 2022
4fc0cc9
Merge branch 'main' into 517-description-annotation
lars-reimann Jun 4, 2022
497c8d7
Merge branch 'main' into 517-description-annotation
lars-reimann Jun 5, 2022
6c269b9
Merge branch 'main' into 517-description-annotation
lars-reimann Jun 5, 2022
69a658b
Merge branch 'main' into 517-description-annotation
lars-reimann Jun 11, 2022
fe6f8a4
Merge branch 'main' into 517-description-annotation
lars-reimann Jun 12, 2022
dee4cb8
Merge branch 'main' into 517-description-annotation
lars-reimann Jun 12, 2022
b8c7ed9
Merge branch 'main' into 517-description-annotation
lars-reimann Jun 13, 2022
3599178
feat: Adding description annotation (WIP)
Masara Jun 13, 2022
4d81cc2
Merge remote-tracking branch 'origin/517-description-annotation' into…
Masara Jun 13, 2022
3ab3f55
revert: changes to Kotlin files
lars-reimann Jun 13, 2022
0a21539
Merge branch 'main' into 517-description-annotation
lars-reimann Jun 13, 2022
c1726ca
feat: Added description annotation, a filter for it and adjusted the …
Masara Jun 13, 2022
55b6d3c
style: apply automatic fixes of linters
Masara Jun 13, 2022
6178c93
Merge branch 'main' into 517-description-annotation
lars-reimann Jun 13, 2022
9a3c77d
feat: don't show new description in annotation view (long)
lars-reimann Jun 13, 2022
a98d466
fix: build error
lars-reimann Jun 13, 2022
0357b36
feat: consistent label for new description text area
lars-reimann Jun 13, 2022
8303247
refactor: sort stuff
lars-reimann Jun 13, 2022
9fc7701
fix: description annotations not sent to server
lars-reimann Jun 13, 2022
ad0d06e
fix: remove log
lars-reimann Jun 13, 2022
b8d29b9
refactor: sort stuff
lars-reimann Jun 13, 2022
04a1037
refactor: sort stuff
lars-reimann Jun 13, 2022
5080c82
style: apply automatic fixes of linters
lars-reimann Jun 13, 2022
ac16cfe
fix: build error
lars-reimann Jun 13, 2022
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
Original file line number Diff line number Diff line change
@@ -60,6 +60,13 @@ data class ConstantAnnotation(val defaultValue: DefaultValue) : EditorAnnotation
override val validTargets = PARAMETERS
}

@Serializable
data class DescriptionAnnotation(val newDescription: String) : EditorAnnotation() {

@Transient
override val validTargets = ANY_DECLARATION
}

@Serializable
data class EnumAnnotation(val enumName: String, val pairs: List<EnumPair>) : EditorAnnotation() {

@@ -112,7 +119,7 @@ object RemoveAnnotation : EditorAnnotation() {
@Serializable
data class RenameAnnotation(val newName: String) : EditorAnnotation() {
@Transient
override val validTargets = CLASSES.union(FUNCTIONS).union(PARAMETERS)
override val validTargets = ANY_DECLARATION
}

@Serializable
@@ -164,6 +171,13 @@ enum class AnnotationTarget(private val target: String) {
}
}

val ANY_DECLARATION = setOf(
CLASS,
GLOBAL_FUNCTION,
METHOD,
CONSTRUCTOR_PARAMETER,
FUNCTION_PARAMETER
)
val GLOBAL_DECLARATIONS = setOf(CLASS, GLOBAL_FUNCTION)
val CLASSES = setOf(CLASS)
val FUNCTIONS = setOf(GLOBAL_FUNCTION, METHOD)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.larsreimann.api_editor.transformation

import com.larsreimann.api_editor.model.DescriptionAnnotation
import com.larsreimann.api_editor.mutable_model.PythonClass
import com.larsreimann.api_editor.mutable_model.PythonDeclaration
import com.larsreimann.api_editor.mutable_model.PythonFunction
import com.larsreimann.api_editor.mutable_model.PythonPackage
import com.larsreimann.api_editor.mutable_model.PythonParameter
import com.larsreimann.modeling.descendants

/**
* Processes and removes `@description` annotations.
*/
fun PythonPackage.processDescriptionAnnotations() {
this.descendants()
.filterIsInstance<PythonDeclaration>()
.forEach { it.processDescriptionAnnotations() }
}

private fun PythonDeclaration.processDescriptionAnnotations() {
this.annotations
.filterIsInstance<DescriptionAnnotation>()
.forEach {
when (this) {
is PythonClass -> this.description = it.newDescription
is PythonFunction -> this.description = it.newDescription
is PythonParameter -> this.description = it.newDescription
else -> {
// Do nothing
}
}
this.annotations.remove(it)
}
}
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@ private fun PythonPackage.preprocess(newPackageName: String) {
*/
private fun PythonPackage.processAnnotations() {
processRemoveAnnotations()
processDescriptionAnnotations()
processRenameAnnotations()
processMoveAnnotations()
processBoundaryAnnotations()
Original file line number Diff line number Diff line change
@@ -181,15 +181,28 @@ class AnnotationValidator(private val annotatedPythonPackage: SerializablePython

companion object {
private var possibleCombinations = buildMap<String, Set<String>> {
this["Attribute"] = mutableSetOf("Rename")
this["Boundary"] = mutableSetOf("Group", "Optional", "Rename", "Required")
this["CalledAfter"] = mutableSetOf("CalledAfter", "Group", "Move", "Pure", "Rename")
this["Attribute"] = mutableSetOf("Description", "Rename")
this["Boundary"] = mutableSetOf("Description", "Group", "Optional", "Rename", "Required")
this["CalledAfter"] = mutableSetOf("CalledAfter", "Description", "Group", "Move", "Pure", "Rename")
this["Constant"] = mutableSetOf()
this["Enum"] = mutableSetOf("Group", "Rename", "Required")
this["Description"] = mutableSetOf(
"Attribute",
"Boundary",
"CalledAfter",
"Enum",
"Group",
"Move",
"Optional",
"Pure",
"Rename",
"Required"
)
this["Enum"] = mutableSetOf("Description", "Group", "Rename", "Required")
this["Group"] =
mutableSetOf(
"Boundary",
"CalledAfter",
"Description",
"Enum",
"Group",
"Move",
@@ -198,22 +211,23 @@ class AnnotationValidator(private val annotatedPythonPackage: SerializablePython
"Rename",
"Required"
)
this["Move"] = mutableSetOf("CalledAfter", "Group", "Pure", "Rename")
this["Optional"] = mutableSetOf("Boundary", "Group", "Rename")
this["Pure"] = mutableSetOf("CalledAfter", "Group", "Move", "Rename")
this["Move"] = mutableSetOf("CalledAfter", "Description", "Group", "Pure", "Rename")
this["Optional"] = mutableSetOf("Boundary", "Description", "Group", "Rename")
this["Pure"] = mutableSetOf("CalledAfter", "Description", "Group", "Move", "Rename")
this["Remove"] = mutableSetOf()
this["Rename"] = mutableSetOf(
"Attribute",
"Boundary",
"CalledAfter",
"Description",
"Enum",
"Group",
"Move",
"Optional",
"Pure",
"Required"
)
this["Required"] = mutableSetOf("Boundary", "Enum", "Group", "Rename")
this["Required"] = mutableSetOf("Boundary", "Description", "Enum", "Group", "Rename")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package com.larsreimann.api_editor.transformation

import com.larsreimann.api_editor.model.DescriptionAnnotation
import com.larsreimann.api_editor.mutable_model.PythonClass
import com.larsreimann.api_editor.mutable_model.PythonFunction
import com.larsreimann.api_editor.mutable_model.PythonModule
import com.larsreimann.api_editor.mutable_model.PythonPackage
import com.larsreimann.api_editor.mutable_model.PythonParameter
import io.kotest.matchers.collections.shouldBeEmpty
import io.kotest.matchers.shouldBe
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

class DescriptionAnnotationProcessorTest {
private lateinit var testClass: PythonClass
private lateinit var testFunction: PythonFunction
private lateinit var testParameter: PythonParameter
private lateinit var testPackage: PythonPackage

@BeforeEach
fun reset() {
testClass = PythonClass(
name = "TestClass",
description = "Lorem ipsum",
annotations = mutableListOf(DescriptionAnnotation("Important class"))
)
testParameter = PythonParameter(
name = "testParameter",
description = "Lorem ipsum",
annotations = mutableListOf(DescriptionAnnotation("Important parameter"))
)
testFunction = PythonFunction(
name = "testFunction",
description = "Lorem ipsum",
annotations = mutableListOf(DescriptionAnnotation("Important function")),
parameters = mutableListOf(testParameter)
)
testPackage = PythonPackage(
distribution = "testPackage",
name = "testPackage",
version = "1.0.0",
modules = listOf(
PythonModule(
name = "testModule",
classes = listOf(testClass),
functions = listOf(testFunction)
)
)
)
}

@Test
fun `should process DescriptionAnnotation of classes`() {
testPackage.processDescriptionAnnotations()

testClass.description shouldBe "Important class"
}

@Test
fun `should remove DescriptionAnnotation of classes`() {
testPackage.processDescriptionAnnotations()

testClass.annotations
.filterIsInstance<DescriptionAnnotation>()
.shouldBeEmpty()
}

@Test
fun `should process DescriptionAnnotation of functions`() {
testPackage.processDescriptionAnnotations()

testFunction.description shouldBe "Important function"
}

@Test
fun `should remove DescriptionAnnotation of functions`() {
testPackage.processDescriptionAnnotations()

testFunction.annotations
.filterIsInstance<DescriptionAnnotation>()
.shouldBeEmpty()
}

@Test
fun `should process DescriptionAnnotation of parameters`() {
testPackage.processDescriptionAnnotations()

testParameter.description shouldBe "Important parameter"
}

@Test
fun `should remove DescriptionAnnotation of parameters`() {
testPackage.processDescriptionAnnotations()

testParameter.annotations
.filterIsInstance<DescriptionAnnotation>()
.shouldBeEmpty()
}
}
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ fun AnnotationDropdown(
showBoundary: Boolean = false,
showCalledAfter: Boolean = false,
showConstant: Boolean = false,
showDescription: Boolean = false,
showEnum: Boolean = false,
showGroup: Boolean = false,
showMove: Boolean = false,
@@ -56,6 +57,11 @@ fun AnnotationDropdown(
Text(labels.getString("AnnotationDropdown.Option.Constant"))
}
}
if (showDescription) {
DropdownMenuItem(onClick = {}) {
Text(labels.getString("AnnotationDropdown.Option.Description"))
}
}
if (showEnum) {
DropdownMenuItem(onClick = {}) {
Text(labels.getString("AnnotationDropdown.Option.Enum"))
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@ AnnotationDropdown.Option.Attribute=@attribute
AnnotationDropdown.Option.Boundary=@boundary
AnnotationDropdown.Option.CalledAfter=@calledAfter
AnnotationDropdown.Option.Constant=@constant
AnnotationDropdown.Option.Description=@description
AnnotationDropdown.Option.Enum=@enum
AnnotationDropdown.Option.Group=@group
AnnotationDropdown.Option.Move=@move
9 changes: 9 additions & 0 deletions api-editor/gui/src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ import { initializeAnnotations, persistAnnotations, selectAnnotations } from '..
import { BoundaryForm } from '../features/annotations/forms/BoundaryForm';
import { CalledAfterForm } from '../features/annotations/forms/CalledAfterForm';
import { ConstantForm } from '../features/annotations/forms/ConstantForm';
import { DescriptionForm } from '../features/annotations/forms/DescriptionForm';
import { EnumForm } from '../features/annotations/forms/EnumForm';
import { GroupForm } from '../features/annotations/forms/GroupForm';
import { MoveForm } from '../features/annotations/forms/MoveForm';
@@ -47,6 +48,8 @@ import {
selectFilteredPythonPackage,
selectPythonPackage,
} from '../features/packageData/apiSlice';
import { PythonClass } from '../features/packageData/model/PythonClass';
import { PythonParameter } from '../features/packageData/model/PythonParameter';

export const App: React.FC = function () {
useIndexedDB();
@@ -103,6 +106,12 @@ export const App: React.FC = function () {
{currentUserAction.type === 'constant' && (
<ConstantForm target={userActionTarget || pythonPackage} />
)}
{currentUserAction.type === 'description' &&
(userActionTarget instanceof PythonClass ||
userActionTarget instanceof PythonFunction ||
userActionTarget instanceof PythonParameter) && (
<DescriptionForm target={userActionTarget} />
)}
{currentUserAction.type === 'enum' && <EnumForm target={userActionTarget || pythonPackage} />}
{currentUserAction.type === 'group' && (
<GroupForm
4 changes: 2 additions & 2 deletions api-editor/gui/src/common/FilterHelpButton.tsx
Original file line number Diff line number Diff line change
@@ -86,8 +86,8 @@ export const FilterHelpButton = function () {
Displays only elements that are annotated with the given type xy. Replace [type]
with one of{' '}
<em>
@attribute, @boundary, @calledAfter, @constant, @enum, @group, @move, @optional,
@pure, @remove, @renaming, @required
@attribute, @boundary, @calledAfter, @constant, @description, @enum, @group,
@move, @optional, @pure, @remove, @renaming, @required
</em>
.
</ChakraText>
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ import {
InferableRemoveAnnotation,
InferableRenameAnnotation,
InferableRequiredAnnotation,
InferableDescriptionAnnotation,
} from './InferableAnnotation';

export class AnnotatedPythonPackageBuilder {
@@ -140,6 +141,7 @@ export class AnnotatedPythonPackageBuilder {
'Boundary',
'CalledAfters',
'Constant',
'Description',
'Enum',
'Groups',
'Move',
@@ -192,6 +194,12 @@ export class AnnotatedPythonPackageBuilder {
return new InferableConstantAnnotation(constantAnnotation);
}
break;
case 'Description':
const descriptionAnnotation = this.annotationStore.descriptions[target];
if (descriptionAnnotation) {
return new InferableDescriptionAnnotation(descriptionAnnotation);
}
break;
case 'Groups':
const groupAnnotations = this.annotationStore.groups[target];
if (!groupAnnotations) {
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import {
CalledAfterAnnotation,
ComparisonOperator,
ConstantAnnotation,
DescriptionAnnotation,
DefaultType,
DefaultValue,
EnumAnnotation,
@@ -92,6 +93,15 @@ export class InferableConstantAnnotation extends InferableAnnotation {
}
}

export class InferableDescriptionAnnotation extends InferableAnnotation {
readonly newDescription: string;

constructor(descriptionAnnotation: DescriptionAnnotation) {
super(dataPathPrefix + 'DescriptionAnnotation');
this.newDescription = descriptionAnnotation.newDescription;
}
}

export class InferableGroupAnnotation extends InferableAnnotation {
readonly groupName: string;
readonly parameters: string[];
Original file line number Diff line number Diff line change
@@ -13,13 +13,15 @@ import {
showMoveAnnotationForm,
showOptionalAnnotationForm,
showRenameAnnotationForm,
showDescriptionAnnotationForm,
} from '../ui/uiSlice';

interface AnnotationDropdownProps {
showAttribute?: boolean;
showBoundary?: boolean;
showCalledAfter?: boolean;
showConstant?: boolean;
showDescription?: boolean;
showEnum?: boolean;
showGroup?: boolean;
showMove?: boolean;
@@ -36,6 +38,7 @@ export const AnnotationDropdown: React.FC<AnnotationDropdownProps> = function ({
showBoundary = false,
showCalledAfter = false,
showConstant = false,
showDescription = false,
showGroup = false,
showEnum = false,
showMove = false,
@@ -79,6 +82,11 @@ export const AnnotationDropdown: React.FC<AnnotationDropdownProps> = function ({
{showConstant && (
<MenuItem onClick={() => dispatch(showConstantAnnotationForm(target))}>@constant</MenuItem>
)}
{showDescription && (
<MenuItem onClick={() => dispatch(showDescriptionAnnotationForm(target))}>
@description
</MenuItem>
)}
{showEnum && <MenuItem onClick={() => dispatch(showEnumAnnotationForm(target))}>@enum</MenuItem>}
{showGroup && (
<MenuItem
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ export const AnnotationImportDialog: React.FC = function () {
boundaries: {},
constants: {},
calledAfters: {},
descriptions: {},
enums: {},
groups: {},
moves: {},
12 changes: 12 additions & 0 deletions api-editor/gui/src/features/annotations/AnnotationView.tsx
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ import {
removeBoundary,
removeCalledAfter,
removeConstant,
removeDescription,
removeEnum,
removeGroup,
removeMove,
@@ -23,6 +24,7 @@ import {
selectBoundary,
selectCalledAfters,
selectConstant,
selectDescription,
selectEnum,
selectGroups,
selectMove,
@@ -36,6 +38,7 @@ import {
showAttributeAnnotationForm,
showBoundaryAnnotationForm,
showConstantAnnotationForm,
showDescriptionAnnotationForm,
showEnumAnnotationForm,
showGroupAnnotationForm,
showMoveAnnotationForm,
@@ -54,6 +57,7 @@ export const AnnotationView: React.FC<AnnotationViewProps> = function ({ target
const boundaryAnnotation = useAppSelector(selectBoundary(target));
const calledAfterAnnotation = useAppSelector(selectCalledAfters(target));
const constantAnnotation = useAppSelector(selectConstant(target));
const descriptionAnnotation = useAppSelector(selectDescription(target));
const enumAnnotation = useAppSelector(selectEnum(target));
const groupAnnotations = useAppSelector(selectGroups(target));
const moveAnnotation = useAppSelector(selectMove(target));
@@ -68,6 +72,7 @@ export const AnnotationView: React.FC<AnnotationViewProps> = function ({ target
!boundaryAnnotation &&
!calledAfterAnnotation &&
!constantAnnotation &&
!descriptionAnnotation &&
!enumAnnotation &&
!groupAnnotations &&
!moveAnnotation &&
@@ -115,6 +120,13 @@ export const AnnotationView: React.FC<AnnotationViewProps> = function ({ target
onDelete={() => dispatch(removeConstant(target))}
/>
)}
{descriptionAnnotation && (
<Annotation
type="description"
onEdit={() => dispatch(showDescriptionAnnotationForm(target))}
onDelete={() => dispatch(removeDescription(target))}
/>
)}
{enumAnnotation && (
<Annotation
type="enum"
28 changes: 28 additions & 0 deletions api-editor/gui/src/features/annotations/annotationSlice.ts
Original file line number Diff line number Diff line change
@@ -15,6 +15,9 @@ export interface AnnotationStore {
constants: {
[target: string]: ConstantAnnotation;
};
descriptions: {
[target: string]: DescriptionAnnotation;
};
enums: {
[target: string]: EnumAnnotation;
};
@@ -147,6 +150,18 @@ export interface ConstantAnnotation {
readonly defaultValue: DefaultValue;
}

export interface DescriptionAnnotation {
/**
* ID of the annotated Python declaration.
*/
readonly target: string;

/**
* Description for the declaration.
*/
readonly newDescription: string;
}

export interface EnumAnnotation {
/**
* ID of the annotated Python declaration.
@@ -263,6 +278,7 @@ export const initialState: AnnotationStore = {
boundaries: {},
calledAfters: {},
constants: {},
descriptions: {},
enums: {},
groups: {},
moves: {},
@@ -340,6 +356,12 @@ const annotationsSlice = createSlice({
removeConstant(state, action: PayloadAction<string>) {
delete state.constants[action.payload];
},
upsertDescription(state, action: PayloadAction<DescriptionAnnotation>) {
state.descriptions[action.payload.target] = action.payload;
},
removeDescription(state, action: PayloadAction<string>) {
delete state.descriptions[action.payload];
},
upsertEnum(state, action: PayloadAction<EnumAnnotation>) {
state.enums[action.payload.target] = action.payload;
},
@@ -444,6 +466,8 @@ export const {
removeCalledAfter,
upsertConstant,
removeConstant,
upsertDescription,
removeDescription,
upsertEnum,
removeEnum,
upsertGroup,
@@ -480,6 +504,10 @@ export const selectConstant =
(target: string) =>
(state: RootState): ConstantAnnotation | undefined =>
selectAnnotations(state).constants[target];
export const selectDescription =
(target: string) =>
(state: RootState): DescriptionAnnotation | undefined =>
selectAnnotations(state).descriptions[target];
export const selectEnum =
(target: string) =>
(state: RootState): EnumAnnotation | undefined =>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { FormControl, FormLabel, Textarea } from '@chakra-ui/react';
import React, { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import { useAppDispatch, useAppSelector } from '../../../app/hooks';
import { selectDescription, upsertDescription } from '../annotationSlice';
import { AnnotationForm } from './AnnotationForm';
import { hideAnnotationForm } from '../../ui/uiSlice';
import { PythonClass } from '../../packageData/model/PythonClass';
import { PythonFunction } from '../../packageData/model/PythonFunction';
import { PythonParameter } from '../../packageData/model/PythonParameter';

interface DescriptionFormProps {
readonly target: PythonClass | PythonFunction | PythonParameter;
}

interface DescriptionFormState {
newDescription: string;
}

export const DescriptionForm: React.FC<DescriptionFormProps> = function ({ target }) {
const targetPath = target.pathAsString();
const prevNewDescription = useAppSelector(selectDescription(targetPath))?.newDescription;
const oldDescription = target.description;

// Hooks -----------------------------------------------------------------------------------------------------------

const dispatch = useAppDispatch();
const { register, handleSubmit, setFocus, reset } = useForm<DescriptionFormState>({
defaultValues: {
newDescription: '',
},
});

useEffect(() => {
try {
setFocus('newDescription');
} catch (e) {
// ignore
}
}, [setFocus]);

useEffect(() => {
reset({
newDescription: prevNewDescription ?? oldDescription,
});
}, [reset, prevNewDescription, oldDescription]);

// Event handlers --------------------------------------------------------------------------------------------------

const onSave = (data: DescriptionFormState) => {
dispatch(
upsertDescription({
target: targetPath,
...data,
}),
);
dispatch(hideAnnotationForm());
};

const onCancel = () => {
dispatch(hideAnnotationForm());
};

// Rendering -------------------------------------------------------------------------------------------------------

return (
<AnnotationForm
heading={`${prevNewDescription ? 'Edit' : 'Add'} @description annotation`}
onSave={handleSubmit(onSave)}
onCancel={onCancel}
>
<FormControl>
<FormLabel>New description for "{target.name}":</FormLabel>
<Textarea {...register('newDescription')} />
</FormControl>
</AnnotationForm>
);
};
Original file line number Diff line number Diff line change
@@ -53,6 +53,7 @@ export class AnnotationFilter extends AbstractPythonFilter {
id in annotations.boundaries ||
id in annotations.calledAfters ||
id in annotations.constants ||
id in annotations.descriptions ||
id in annotations.enums ||
id in annotations.groups ||
id in annotations.moves ||
@@ -70,6 +71,8 @@ export class AnnotationFilter extends AbstractPythonFilter {
return id in annotations.calledAfters;
case AnnotationType.Constant:
return id in annotations.constants;
case AnnotationType.Description:
return id in annotations.descriptions;
case AnnotationType.Enum:
return id in annotations.enums;
case AnnotationType.Group:
@@ -98,6 +101,7 @@ export enum AnnotationType {
Boundary,
CalledAfter,
Constant,
Description,
Enum,
Group,
Move,
Original file line number Diff line number Diff line change
@@ -99,6 +99,8 @@ const parsePositiveToken = function (token: string): Optional<AbstractPythonFilt
return new AnnotationFilter(AnnotationType.CalledAfter);
case 'annotation:@constant':
return new AnnotationFilter(AnnotationType.Constant);
case 'annotation:@description':
return new AnnotationFilter(AnnotationType.Description);
case 'annotation:@enum':
return new AnnotationFilter(AnnotationType.Enum);
case 'annotation:@group':
Original file line number Diff line number Diff line change
@@ -20,7 +20,9 @@ export const ClassView: React.FC<ClassViewProps> = function ({ pythonClass }) {
<Heading as="h3" size="lg">
{pythonClass.name} {!pythonClass.isPublic && '(private)'}
</Heading>
{pythonClass.isPublic && <AnnotationDropdown target={id} showMove showRemove showRename />}
{pythonClass.isPublic && (
<AnnotationDropdown target={id} showDescription showMove showRemove showRename />
)}
</HStack>

<AnnotationView target={id} />
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ export const FunctionView: React.FC<FunctionViewProps> = function ({ pythonFunct
<AnnotationDropdown
target={id}
showCalledAfter={hasRemainingCalledAfters}
showDescription
showGroup={pythonFunction.explicitParameters().length >= 2}
showMove={pythonFunction.containingModuleOrClass instanceof PythonModule}
showPure
Original file line number Diff line number Diff line change
@@ -34,6 +34,7 @@ export const ParameterNode: React.FC<ParameterNodeProps> = function ({ isTitle,
showAttribute={isConstructorParameter}
showBoundary
showConstant
showDescription
showEnum
showOptional
showRename
Original file line number Diff line number Diff line change
@@ -52,6 +52,7 @@ const getMapWithAnnotation = function (pythonClass: PythonClass, annotations: An
let specificValue = 0;

specificValue += annotations.moves[qname] !== undefined ? 1 : 0;
specificValue += annotations.descriptions[qname] !== undefined ? 1 : 0;
specificValue += annotations.renamings[qname] !== undefined ? 1 : 0;
specificValue += annotations.removes[qname] !== undefined ? 1 : 0;

Original file line number Diff line number Diff line change
@@ -54,6 +54,7 @@ const getMapWithAnnotation = function (pythonFunction: PythonFunction, annotatio

specificValue += annotations.calledAfters[qname] !== undefined ? 1 : 0;
specificValue += annotations.pures[qname] !== undefined ? 1 : 0;
specificValue += annotations.descriptions[qname] !== undefined ? 1 : 0;
specificValue += annotations.renamings[qname] !== undefined ? 1 : 0;
specificValue += annotations.removes[qname] !== undefined ? 1 : 0;
specificValue += annotations.groups[qname] !== undefined ? 1 : 0;
Original file line number Diff line number Diff line change
@@ -61,6 +61,7 @@ const getMapWithAnnotation = function (pythonParameter: PythonParameter, annotat
specificValue += annotations.boundaries[qname] !== undefined ? 1 : 0;
specificValue += annotations.enums[qname] !== undefined ? 1 : 0;
specificValue += annotations.constants[qname] !== undefined ? 1 : 0;
specificValue += annotations.descriptions[qname] !== undefined ? 1 : 0;
specificValue += annotations.optionals[qname] !== undefined ? 1 : 0;
specificValue += annotations.requireds[qname] !== undefined ? 1 : 0;
specificValue += annotations.renamings[qname] !== undefined ? 1 : 0;
13 changes: 13 additions & 0 deletions api-editor/gui/src/features/ui/uiSlice.ts
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ type UserAction =
| BoundaryUserAction
| CalledAfterUserAction
| ConstantUserAction
| DescriptionUserAction
| GroupUserAction
| EnumUserAction
| RenameUserAction
@@ -56,6 +57,11 @@ interface ConstantUserAction {
readonly target: string;
}

interface DescriptionUserAction {
readonly type: 'description';
readonly target: string;
}

interface EnumUserAction {
readonly type: 'enum';
readonly target: string;
@@ -174,6 +180,12 @@ const uiSlice = createSlice({
target: action.payload,
};
},
showDescriptionAnnotationForm(state, action: PayloadAction<string>) {
state.currentUserAction = {
type: 'description',
target: action.payload,
};
},
showGroupAnnotationForm(state, action: PayloadAction<GroupTarget>) {
state.currentUserAction = {
type: 'group',
@@ -264,6 +276,7 @@ export const {
showBoundaryAnnotationForm,
showCalledAfterAnnotationForm,
showConstantAnnotationForm,
showDescriptionAnnotationForm,
showEnumAnnotationForm,
showGroupAnnotationForm,
showMoveAnnotationForm,