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
Show file tree
Hide file tree
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
Expand Up @@ -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() {

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
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
Expand Up @@ -28,6 +28,7 @@ private fun PythonPackage.preprocess(newPackageName: String) {
*/
private fun PythonPackage.processAnnotations() {
processRemoveAnnotations()
processDescriptionAnnotations()
processRenameAnnotations()
processMoveAnnotations()
processBoundaryAnnotations()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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
Expand Up @@ -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,
Expand Down Expand Up @@ -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"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions api-editor/gui/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions api-editor/gui/src/common/FilterHelpButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
InferableRemoveAnnotation,
InferableRenameAnnotation,
InferableRequiredAnnotation,
InferableDescriptionAnnotation,
} from './InferableAnnotation';

export class AnnotatedPythonPackageBuilder {
Expand Down Expand Up @@ -140,6 +141,7 @@ export class AnnotatedPythonPackageBuilder {
'Boundary',
'CalledAfters',
'Constant',
'Description',
'Enum',
'Groups',
'Move',
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
CalledAfterAnnotation,
ComparisonOperator,
ConstantAnnotation,
DescriptionAnnotation,
DefaultType,
DefaultValue,
EnumAnnotation,
Expand Down Expand Up @@ -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[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down
Loading