Skip to content

Conversation

@markwpearce
Copy link
Collaborator

@markwpearce markwpearce commented Jan 1, 2025

Addresses #1348

Plugins must declare their annotations, so that can be validated.

  • Add Documentation about Annotations
  • Fix Deprecated docs with references to old plugin events
  • Add validation on annotation names and args
  • Ensure Annotation args are literals
  • Agree on format of annotation declarations

Future PR:

  • Enhance hovers/completions/Signature help for annotations

image

image

image

image

Extra info logging:

[11:24:45:357 AM] [prj0] Adding annotation 'takesString' (testPlugin)

@markwpearce markwpearce added this to the v1.0.0 milestone Jan 1, 2025
@markwpearce
Copy link
Collaborator Author

@TwitchBronBron

The docs I added follow along with the description from the issue, but I'm thinking it may be easier to deal with annotations that are provided as Types?

eg:

const myAnnotation = new TypedFunctionType()
myAnnotation.name = 'MyAnnotation';
myAnnotation.params = [
    {name: 'id', type: StringType.instance},
    {name: 'extraData', type: new AssociativeArrayType(), optional: true}
];

this.annotations = [myAnnotation]

(perhaps we could update the constructor or create a helper function to create it all at once?)

This would mean we wouldn't have to parse the declaration, but instead use it directly... and wouldn't need to have extra error handling on bad parsed values, etc.

Copy link
Collaborator

@luis-j-soares luis-j-soares left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly off-topic feedback 👼

@markwpearce markwpearce changed the title Plugins Must Declare Annotations [WIP] Plugins Must Declare Annotations Jan 13, 2025
@markwpearce markwpearce marked this pull request as ready for review January 13, 2025 14:44
docs/plugins.md Outdated
Comment on lines 657 to 658
'inline()',
'log(prefix as string, addLineNumbers = false as boolean)'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already itching to use this for our internal plugins once v1 arrives. I do have a couple of questions, maybe both could be reflected in the docs?

  • Can a plugin author expect the full type system to be supported, or will it only support the built-in types? (I see onlyAllowLiterals: true, so maybe that's a "no"? I'm not familiar with the type system yet)
  • If I have annotation declaration that is implemented by more than one plugin, should a developer assume that the prevalent annotation is based on the order in which the plugins are declared in bsconfig?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Annotation arguments can only be literals - there’s no way of knowing at compile time what the value of a variable is.

That being said, we could support const and enum values as annotation args too. Plan on that in v1.1

so that means, literal strings, integers, floats, literal arrays (with literal values) and literal AA’s can be used as args.

This would be perfectly fine:

@annotation(“test”, {values: [1.1, 4, 7.2], data:{name: “Luis”}}, [{abc: 123}])

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ll update the docs to reflect that

@TwitchBronBron
Copy link
Member

...I'm thinking it may be easier to deal with annotations that are provided as Types?

I think the challenge comes when we get into more advanced types for these annotations. Consider an annotation that takes one string, or exactly 2 arguments, or exactly 4 arguments (i know we don't have this in bsc yet, but might someday). In typescript we would represent that as:

function someAnnotation(someArg: string | [number, number] | [number, number, number, number]) { }

We'd be pushing plugin authors to all start learning a more about the type system than perhaps necessary depending on their annotation argument needs.

It feels like declaring annotations as brighterscript code would be more approachable for plugin authors, and might also have a few other benefits:

  • avoids the plugins using a slightly older brighterscript internally and producing types that don't quite work right with whatever latest brighterscript is currently running
  • no new syntax or AST or type system knowledge necessary
  • much easier to define complex argument types (whenever they're eventually implemented in bsc)

Maybe I'm making this into a bigger deal than it needs to be? Thoughts?

@TwitchBronBron
Copy link
Member

Perhaps a counter-argument to my argument above would be to provide plugin authors with a helper function to build types from code. Something like this:

const complexType = util.createType(`string | [integer, integer] | [integer, integer, integer, integer]`);

But it's not too hard to just do this with existing paradigms either...

const type = Parser.parse(`
    function test(arg as string | [integer, integer] | [integer, integer, integer, integer]): end function
`).ast.findChild(isFunctionStatement).getType();

For example:
```typescript
this.annotations = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be really nice to enforce which statement types this annotation could be declared on. For example, rooibos @suite() only works when attached to classes. Adding @suite() to a namespace should be an error. BrighterScript could provide consistent validations for these. I envision configuring it something like this:

this.annotations.push({
    restrictTo: ['class'], //this would be a list of all types the annotation maybe declared above
    func:  new TypedFunctionType(VoidType.instance).setName('inline'),
        { 
            description: 'Add a log message whenever this function is called',
            type: new TypedFunctionType(VoidType.instance)
                .setName('log')
                .addParameter('prefix', StringType.instance)
                .addParameter('addLineNumbers', BooleanType.instance, true)
        }
    

@TwitchBronBron TwitchBronBron deleted the branch v1 May 1, 2025 19:34
@TwitchBronBron TwitchBronBron reopened this Jun 5, 2025
@TwitchBronBron TwitchBronBron changed the base branch from release-1.0.0 to v1 June 5, 2025 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants