Releases: junkdog/sift
sift-0.15.0
sift-0.15.0 2023-08-21
Further Performance Improvements to Traced(/Tracked) elements
- Optimized element trace tracking for elements with registered entities.
- A bloom-like filter for expediently discarding element traces during lookups.
- Discarding traces which are subsets of other traces is now more efficient.
- Considerably fewer traces are now generated during template execution.
New/Tweaks
- Dsl.Synthesis:
inject(ByteArray|KClass|Class)
embeds the provided class into the template and adds it
to the set of input classes. This method is primarily used to introduce new classes to the system model
that are not originally part of the input classes. These could be shared code utility classes or any
other classes that augment the functionality or structural understanding of the system. --statistics
has been updated with template deserialization time amd additional data on element traces.- Added repeatable
--column
option to tree output. Valid columns identifiers:all
,element-id
,element-type
,
entity-type
. -x
/--debug-element-trace
shows all traces associated with the requested element id. The element id can be
obtained from--column element-id
or--column all
. Elements traverse parent and child nodes when associating
entities with one another and when associatingproperty()
data with entities.
-X
/--debug-inverse-trace
reverses the element trace, used together with--debug-element-trace
.
Breaking changes
--dump-system-model
short option name has been renamed to-D
.
Fixes
- DSL: fix
invocationsOf()
discarding traces when multiple multiple elements invoke the same method element. - DSL:
methods {}
now iterates methods for interfaces, even when there's no implementation. - Fix parsing the signature involving formal type parameters.
- Resolving inherited methods from interfaces failed to traverse the hierarchy beyond the first interface.
sift-0.14.0
sift-0.14.0 2023-07-07
Improved Element Tracking Performance
The tracking of element associations during template execution in Sift has undergone substantial performance
enhancements. Traced elements are now assigned unique integer identifiers, facilitating the replacement of
the previously tracked List<Element>
with an int[]
. This greatly improves cache locality, which in
turn, leads to much faster comparisons.
Fixes
- StackOverflowError when resolving formal type parameters of generic enum.
- DSL:
readType()
of signatures could omit the package name when constructing the type. - Exception during
--statistics
on empty results.
sift-0.13.0
sift-0.13.0 2023-07-02
Annotations scope
The annotations scope enables working with annotations beyond reading top-level elements. It provides functions
to traverse nested annotations and to initiate a class scope from types referenced by annotations.
annotations(filter: SiftType?) {}
has been added to all scopes representing elements which can be annotated.
The filter parameter is optional and defaults to null
, hence, if not specified, all annotations get returned.
Three unique functions are included within the annotations scope:
nested(element) {}
: Iterates child annotations referenced by the specified element. Theelement
parameter
corresponds to the name of the annotation element which nested annotations are to be accessed.explodeTypes(element, synthesize) {}
: Iterates over classes stored within a specific annotation element. The
parameterelement
represents the name of the annotation element to be processed.synthesize
is an optional
parameter, defaulting tofalse
. When set totrue
, missing types are stubbed based on those stored within the
annotation element.synthesize
is useful for stubbing classes not included with the input classes, providing a
mechanism to register entities over unknown types.readAttribute(attribute)
: operates similarly toreadAnnotation(type, attribute)
, but reads the attribute from
the currently scoped annotations instead of the specified type.
Method selection filter
The selection enum definition for methods(<selection>) {}
has been updated to include the following options:
constructors
: Matches all constructors in a class.staticInitializers
: Matches the class initializers.declared
: Matches all methods that are directly declared by the class, excluding constructors. This is the default filter.inherited
: Matches all declared and inherited methods, excluding constructors.synthetic
: Matches synthetic methods, such as default-value functions in Kotlin.accessors
: Matches Kotlin's property getters and setters.
It is possible to compose multiple selection options in the methods()
function by using the +
operator, like so:
methods(declared + constructors) {}
.
Note that constructors are no longer included by default.
New/Tweaks
- New property text transformers:
uppercase()
andlowercase()
. - DSL: added
label
overloads forclasses()
,fields()
,methods()
,parameters()
,classesOf()
,fieldsOf()
,
methodsOf()
,parametersOf()
,elementsOf()
andouterScope()
. The label is displayed when running with
--profile
, under the associatedfork
action.
Breaking changes
- DSL: entity properties from
readAnnotation()
are now flattened if they are arrays.
Fixes
- DSL:
property()
ignoredPropertyStrategy
when used together withentity()
registration. - DSL:
readAnnotation()
now convertsorg.objectweb.asm.Type
tosift.core.dsl.Type
for fields containing class values. - DSL:
readAnnotation()
thefield
parameter is now more appropriately named 'attribute'.
sift-0.12.0
sift-0.12.0 2023-06-17
Kotlin language support
This update incorporates Kotlin language support:
- Extension function names are rendered appropriately.
- Value classes, formerly known as inline classes, now display the value class name instead of the underlying type.
- The enumeration of methods and parameters has been improved for relevance.
- It's now possible to filter based on Kotlin's internal visibility modifier.
- Visibility of properties now mirrors the associated getter method's visibility, instead of the backing field's private visibility.
Kotlin support is achieved through parsing @kotlin.Metadata
class annotations, utilizing
the kotlin-reflect-lite library.
Selection enum for methods()
and parameters()
DSL functions parameters() {}
and properties() {}
now take an optional ParameterSelection
and
MethodSelection
enum, in order to make it easier to iterate over the pertinent elements.
The ParameterSelection
enum can be used with the parameters()
function. It provides the following options:
all
: Iterates over all parameters including Kotlin's extension receivers. This is the default behavior, matching previous functionality.excludingReceiver
: Iterates over all parameters, but excludes the extension receiver in Kotlin.onlyReceiver
: Focuses solely on the extension receiver, excluding all other parameters.
The MethodSelection
can be used with methods()
:
declared
: Selects all methods directly declared by the class, excluding Kotlin property accessors.inherited
: Includes all declared methods and inherited methods.declaredAndAccessors
: Similar to declared, but also includes Kotlin property accessors.
property()
extraction with andThen(TextTransformer)
Previously, the primary method for updating an entity label was to pass TextTransformers
to label()
. For instance:
annotatedBy(httpMethod)
entity(E.endpoint,
label("\${http-method} /\${base-path:}/\${path:}",
dedupe('/')), // dedupe is a TextTransformer
...
This approach served well for scenarios like substituting common paths/names or removing duplicate separators, but was
somewhat cumbersome for handling finer, more intricate transformations.
To address this, the andThen
infix function has been introduced to enable direct transformation of entity properties:
classes {
entity(e, label("CLS \${name}"),
property("name",
readName() andThen replace(Regex("^CommonPrefix"), ""))
)
}
In the example, property("name")
, readName()
extracts the class name, andThen
applies replace(Regex("^CommonPrefix"), "")
,
removing any starting "CommonPrefix" from the name
property.
New property TextTransformer function: stylize(TextStyle)
The stylize
function wraps a TextStyle
around the text. For example, stylize(Gruvbox.orange2 + bold)
. This
is also how --template sift
renders the function parameter names with a different color compared to the function name:
parameters(excludingReceiver) {
property(E.dsl, "params", readName() andThen stylize(blue2))
The current list of TextTransformer
functions are:
edit
: takes a list of text transformers and applies them in sequence.dedupe
: removes duplicate instances of a specified character.replace
: replaces all occurrences of a specified string or regular expression with a given replacement string.idSequence
: replaces matches of a given regular expression with sequentially assigned values, starting at 1.uuidSequence
: replaces UUID:s with sequentially assigned values, starting at 1.stylize
: applies aTextStyle
, for example(Gruvbox.orange2 + bold)
, to the text.
New/Tweaks
- DSL:
filter(Visibility)
added to class, field and method scopes. For kotlin properties, field visibility
is reported as the visibility of the property getter. - DSL/Signature:
readType()
added to signature scope. - Entity label parameters now always return all values. Previously, only the initial value was utilized unless
the property name was prefixed with +.
Breaking changes
- DSL:
editText()
has been renamed toeditor()
. This function is currently only used during graphviz dot generation,
and will likely be removed in later releases.
Fixes
- SiftType
Type::simpleName
now correctly handles types with generic signatures. - DSL/Parameter: fix
readType()
serialization key colliding withreadType()
in class scope. - DSL/Signature:
filter()
has been enhanced to check against both the full and simple name signatures for each type,
fixing the previous limitation of considering only the raw type. PropertyStrategy.unique
now takes the set of its own input to ensure distinct values.- DSL/Signature:
explodeType()
andexplodeTypeT()
no longer output duplicate types.
sift-0.11.0
sift-0.11.0 2023-06-06
Error Handling
sift's error reporting mechanism has been improved and now supports integration with the --profile
option.
The --profile
option assists in identifying problematic DSL methods by marking the operation causing the
error. This feature enables traceability back to the template DSL.
New/Tweaks
--no-emoji
option to disable emoji output, for terminals that do not support it. The
implementation is coarse, but should work for most emoji.- Added
jakarta-ws
, "Supporting template for Jakarta RESTful Web Services".
Fixes
- DSL/Class:
implements()
now correctly matches types even when they are not incorporated within the input classes. - SiftType
RegexType::simpleName
trims the regex pattern to only include the substring following the last dot.
Breaking changes
- DSL: The complete parameter sequence for the
property()
method has been revised to (entity, key, strategy, extract).
For the relevant overloads that includestrategy
, it is now positioned prior to theextract
parameter.
sift-0.10.0
sift-0.10.0 2023-05-17
The sift
template now enables direct comparison between releases without any
local prerequisites. Previously, one needed to have the older .jar
locally available and execute a --save
on
the older version before running --diff <OLD_VERSION.JSON>
. The new release simplifies the process. Now,
the --diff
command can be applied directly to Maven coordinates, eliminating the previous steps. For example:
sift --template sift -f "net.onedaybeard.sift:core:0.10.0" --diff "net.onedaybeard.sift:core:0.9.0"
to
identify changes to the API in the latest release.
New/Tweaks
- Introduced
RegexType
for flexible type matching using regular expressions. Use the.regexType
extension function on a string, or.type
on a Regex, to create a RegexType. For example,
Regex("java.util.*").type
matches all types in the java.util package. DSL methodsimplements()
,
filterType()
andannotatedBy()
have been updated accordingly. -f
option has been updated to also support URI paths and maven coordinates, for example:
sift -f https:///path/to/classes.jar ...
andsift -f net.onedaybead.sift:core:0.9.0 ...
.--diff
now also works against class directories, jars, URI:s and maven coordinates. This
means that it is no longer necessary to--save
the system model before running--diff
, e.g.:
sift --template sift -f net.onedaybead.sift:core:0.9.0 --diff net.onedaybead.sift:core:0.7.0
--maven-repository
option has been added to specify additional Maven repositories for downloading artifacts.
By default, Maven Central and local user repositories are always included.- Remaining usages of
org.objectweb.asm.Type
replaced withsift.core.dsl.Type
. sift
template: DSL methods for dealing with entity properties are now prefixed with a ⚙️ icon.- DSL: The
fork
actions displayed when using the--profile
flag now incorporate the
labels from thescope()
functions.
Breaking change
siftrc.sh
andsiftrc.zsh
replaced bysift.config
. Update custom configurations to this new file.
sift-0.9.0
sift-0.9.0 2023-04-22
Entity Registration with Generic Types
Entities can now be registered against generic type signatures, such as Repository<User>
. This first iteration
does not cover all use-cases, specifically type arguments inferred from context are currently not resolved,
leading to sift ignoring the generic signatures of method invocations.
Breaking change: sift.core.dsl.Type
supersedes org.objectweb.asm.Type
The sift.core.dsl.Type
class supersedes org.objectweb.asm.Type
usage in the DSL. The new type
class supports incorporating generic type information and is generally easier to work with. Instances
of the new Type
class are created with the type()
function or the String.type
extension property,
for example: type("java.lang.String")
and "java.lang.String".type
.
Breaking change: entity property update strategies
Entity properties now overwrite existing properties by default, instead of appending to them . You can
can modify this behavior by specifying the strategy
parameter in the property()
function. For example:
property(PropertyStrategy.unique, foo, "labels", withValue("hello"))
Property strategies are one of: replace
, append
, prepend
, immutable
and unique
.
New/Tweaks
- DSL/Class: added
inherited
parameter tomethods()
andfields()
to include inherited methods and fields. - Enhanced performance primarily focused on element trace optimizations - the process of interrelating
elements as they are navigated by the DSL. This enhancement reduces the total execution time by up to
40% for complex templates. - DSL/Method:
filterName()
added string overload forname
. - DSL/Method:
fieldAccess {}
to iterate accessed fields. - Entity elements of
Entity.Type.fieldAccess
can now be either fields or classes. If the latter,
then the type of the field is used. - siftrc.zsh|sh is now created under
~/.local/share/sift/
. It currently holdsSIFT_ARGS
, CLI options
always appended. --stastistics
prints statistics about the state from the execution of the system model template.
Breaking changes
- TODO: methods affected by
Type
change
Fixes
- sift template:
object
Actions were not associated with their DSL methods.
sift-0.8.0
sift-0.8.0 2023-03-20
Example template: Game Rental Sample Application
A short template for the Game Rental demo application. It demonstrates
how to work with JPA entities, and wires axon entities against @MessageMapping
endpoints.
New/Tweaks
--tree-root
option is now repeatable, allowing you to specify multiple roots.
For example:sift -t spring-axon -r command -r query ...
--list-templates
option now displays a brief description for each template.--dump-system-model
option now converts entity UUIDs to integers, making the output more readable.
Fixes
DSL.property()
: would sometimes fail to update entity properties.sift
template: fix DSL registration.- IllegalArgumentException for methods declaring thrown exceptions as generic types, e.g.:
public static <X extends Throwable> void propagate(Throwable t) throws X
spring-axon
: no longer fails if a@Controller
doesn't register any REST endpoints.
sift-0.7.0
sift-0.7.0 2023-03-06
DSL documentation published to https://junkdog.github.io/sift/
Example template: Spring PetClinic Sample Application
This is a short, custom template for the Spring Boot Pet Clinic demo
application. It demonstrates how to combine existing templates with custom templates,
describes relationships between entities, and configures properties for Graphviz visualization.
New/Tweaks
--profile
now includesety#
column, tracking entity registrations.--stacktrace
to print stacktrace on errors.- DSL/Core:
editText(TextTransformer...)
forproperty()
, currently used bygraphviz()
. - DSL/Elements: inherits from
Core
, making it a bit more useful.
Breaking changes
- DSL: changed package to
sift.core.dsl
fromsift.core.api
. - DSL/Template:
graphviz(label=List<TextTransformer>)
replacesremoveSuffix
argument. - All scopes (Template, Classes, Methods...) are now top-level classes.
- DSL/Core: restricted value of
withValue(value)
to String, Number, Boolean, Enum. This
solves a lot of issues with serialization.
Fixes
- DSL/property: Improved the
property()
method to resolve relationships via direct association
first. If direct association fails for all entities, it falls back on identifying relationships
through shared common associations. The old behavior was to rely solely on shared common
associations, but this could produce false positives. - Fix NPE when
--list-entity-types
is used with no path argument. --list-entity-types
now resolves entity counts when system model is deserialized with--load
.
sift-0.6.0
sift-0.6.0 2023-02-26
New/Tweaks
- DSL.Template:
classesOf()
/methodsOf()
/fieldsOf()
now passes along the Entity.Type as a lambda parameter. - DSL.Template:
entity[key] = foo.(instantations|invocation|fieldAccess)
, replacingregisterInvocationsOf
andregisterInstantiationsOf
. - DSL.Class:
interfaces(recurisve, synthesize)
iterates interfaces of inspected class nodes. - DSL.Class:
filter(Modifiers..., invert)
iterates classes with matching modifiers. - DSL.Class:
enums {}
opens a field scope iterating all enum values (as static final fields). - DSL.Field:
filterType()
of fields. - DSL.Field:
filter(Modifiers..., invert)
iterates fields with matching modifiers. - DSL.Method:
filter(Modifiers..., invert)
iterates methods with matching modifiers. - DSL.Parameter:
filterType()
of parameters. - dot: Remove need for specifying
"dot-ignore"
property. - DSL: re-registering the same entity using
entity(entitty, label...)
will now update the entity label. - CLI:
--edge-layout=spline|polyline|ortho
, used together with-R
/--render
. spring-axon
: member aggregate label changed to$aggregate[$member]
.spring-boot
: base template, extended byspring-axon
.
Breaking changes
- Instrumenter Service renamed to System Model Template:
- pipeline() is now template()
instrumenter {}
is nowtemplate {}
DSL.Instrumenter.graphviz()
: parameterstripLabelSuffix
renamed toremoveSuffix
.- Entity Types can can only be associated with a single element type (class, method, etc).
- Internal visibility on many classes previously marked as public.
Fixes
spring-axon
: fix member aggregate identification when field type is a Map.spring-axon
: improved identification of projections.- Inadvertent exclusion of entities from the tree if the added entity also occurred as a parent.
- graphviz: childless entities could throw a NoSuchElementException.