Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Compilation Time Expressions in Annotations #8954

Merged
merged 40 commits into from
Mar 25, 2023

Conversation

graemerocher
Copy link
Contributor

@graemerocher graemerocher commented Mar 16, 2023

From feature request #8323 this PR implements the following set of features:

  1. Declaring literals.
  • strings (delimited by single quotes)
  • numeric types (int, long, float, double, incl. scientific notation and hex)
  • boolean
  • null
  1. Mathematical operators
  • -, /, *, %,^ on numeric types
  • + on both numeric types and strings
  1. Relational operators
  • Standart relational operators (>, <, >=, <=, ==, !=)
  • instanceof operator (e.g. 'abc' instanceof T(java.langString))
  • matches for regex mathing (e.g. 'abc' matches '^[a-z]*') (including /.+/ syntax for regex)
  • empty for checking of an object is null or empty
  • Relational operators need to support comparables as well
  1. Logical operators
  • &&, ||, !. We should probably also allow using aliases here (and, or, not)
  1. Working with type references
  • as part of instanceof operation
  • as an argument for method invocation which is treated as io.micronaut.CutsomType.class (e.g. getBean(T(io.micronaut.CustomType))
  • as a type reference followed by static method invocation (e.g. T(java.lang.Math).random())
  1. Working with collections
  • Accessing by index for lists (e.g. list[1])
  • Accessing by key for maps (e.g. map['key'])
  • Collection filtering (e.g. ages.filter(age -> age > 18) )
  • Collection mapping (e.g. persons.map(p -> p.age) )

For filtering/mapping probably makes sense to support lambda syntax.

  1. Accessing object properties
  • This should allow chaining property access with . (e.g. object.property.nestedProperty)
  • Safe property access allowing to avoid NPE (object?.property.?.nestedProperty)
  1. Methods invocation
  • Object method invocation (e.g. object.name().lenght())
  • Static method invocation (T(java.lang.Math).random())
  1. Ternary operator
  • Standard expr ? 'trueResult' : 'falseResult'
  • Elvis operator (e.g. age?:18, note only makes sense if we implement coercion to boolean for numbers, lists, strings etc.)
  1. Object construction
  • construction with new keyword (this might be useful in @Value annotation, e.g. @Value(#{ new io.micronaut.CustomType() })
  • array construcation (new int[] {1, 2, 3}) - not sure whether this is a useful one, since inlining list gives similar behavior
  • lists with {1, 2, 3} syntax
  • maps with { 'first': 1, 'second': 2 }
  1. Predefined syntax constructs, e.g.
  • Getting beans from context (e.g. ctx[io.micronaut.CustomBean])
  • Accessing properties (e.g. env['custom.property'] )

See #8323

@graemerocher graemerocher marked this pull request as ready for review March 21, 2023 14:59
@graemerocher graemerocher requested a review from sdelamo March 21, 2023 14:59
@graemerocher graemerocher added the type: enhancement New feature or request label Mar 21, 2023
@graemerocher
Copy link
Contributor Author

test failures are unrelated and related to the latest changes to the validation module

@graemerocher graemerocher added this to the 4.0.0-M2 milestone Mar 22, 2023
@sdelamo
Copy link
Contributor

sdelamo commented Mar 22, 2023

I will review this PR tomorrow.

Copy link
Contributor

@sdelamo sdelamo left a comment

Choose a reason for hiding this comment

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

I have created several improvements PRs:

It misses package-info.java in the package and subpackages of io.micronaut.expressions.

What’s new section does not contain anything about Expression. It would be great if you could add a link such as:

 `<<evaluatedExpressions, Evaluated Expressions>>`
 

I think this is an exciting feature. I will create an issue in security to support something like: @Secured(condition = "#{authentication.attributes.email == '[email protected]' }

@sonarqubecloud
Copy link

SonarCloud Quality Gate failed.    Quality Gate failed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 77 Code Smells

79.0% 79.0% Coverage
0.7% 0.7% Duplication

@graemerocher graemerocher merged commit 72b1a7e into 4.0.x Mar 25, 2023
@graemerocher graemerocher deleted the compile-time-expression-language branch March 25, 2023 18:15
@graemerocher
Copy link
Contributor Author

@GavrilovSV I have merged the first cut of this. Thank you for your work implementing the basics of this feature, I think it has great potential.

There are still areas of improvement that I would like to address before GA:

  • The performance of bean lookups via the evaluation context. I think we should make context objects effectively singleton and cache them in the evaluation context otherwise I am not sure how well this will perform for hot paths like request processing. Given most of the execution part is marked as @Experimental I am fine to address this later.
  • A default context that gives access to the Environment object to simplify writing conditions that resolve properties
  • Research into extending the HTTP annotations to allow conditional routes (if we address the performance concern above)
  • Probably we should support Comparable interface for logical operators
  • Probably we should support collection filtering and mapping. For this I think we should use the lambda syntax alreaded defined in Java and Jakarta EL.

@graemerocher
Copy link
Contributor Author

@sdelamo

I have created several improvements PRs:

* #9000

* #8999

* #8998

* #8997

* #8996

closed / merged these.

It misses package-info.java in the package and subpackages of io.micronaut.expressions.

This is not public API as it is part of the processor module which is mostly internal API. However we can add this if you feel strongly about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants