Package org.ek9lang.compiler.phase5
At this point, before the compiler builds the intermediate representation it completes some more checks.
PreIntermediateRepresentationChecks is the main entry point for this phase.
Most of the processing is delegated to PreIRListener.
This now follows the same pattern as most of the other Listeners, using
SymbolsAndScopes for handling scope traversals and locating recorded
symbols and scopes.
There is a 'complexity' calculator built into this phase, it is quite tolerant of high complexity. It does emit compiler errors if a single method/function has complexity at level 50 or higher or if an aggregate has a total complexity of 500 or higher. The rules for calculating complexity are based on a modified McCabe region algorithm. It is quite simple in its approach, as code elements are encountered a level of complexity is incremented.
There are additional checks around simple evaluation of whether variables have been initialised or not. In some cases properties on aggregates may need to be defined in uninitialised for i.e.
prop1 as String?
In such cases the EK9 compiler will mandate that the EK9 developer create all necessary coded constructors, it will not mandate that 'prop1' is then initialised - it will leave that to the Ek9 developer to 'take the risk' and understand what may or may not go wrong in their code.
Ideally, all properties and variables are always declared in initialised form (even if the value is 'un-set'). But this cannot always be mandated, so the EK9 compiler has some tolerance for these uninitialised variables.
-
ClassDescriptionChecks for abandoned resources (Rule 2 - E81056) at scope exit.Does checks on the control part of a while loop to see if Optional/Result/Iterator are now safe via method access.Once an expression has been assessed as being simple enough to process, this consumer is called to mark the appropriate symbol(s) used in the expression as safe if the appropriate methods are called.Emit error if there are too many arguments.Validates class design patterns for Construct Misuse Detection (E11022-E11025).Checks cognitive complexity at function/method/operator exit and emits error if too high.Checks LCOM4 cohesion against thresholds and emits errors if exceeded.Checks the combined complexity and statement count at function/method/operator exit.Looks for the complexity value in the complexityCounter and adds the value to the appropriate symbol.Checks efferent coupling (Ce) against thresholds and emits errors if exceeded.Checks expression complexity when a coalescing expression tree completes.Checks inheritance depth (DIT) against thresholds and emits errors if exceeded.Pops the injection count from the counter and stores it as squirrelled data on the symbol.Validates DI injection design quality for components (E11040).Validates module-level cohesion against threshold and emits E11017 error if exceeded.Functional interface to get the appropriate ErrorListener for a ParsedModule.Validates module-level efferent coupling against threshold and emits E11016 error if exceeded.Functional interface to get the appropriate ErrorListener for a ParsedModule.Checks nesting depth at function/method/operator exit and emits error if too deep.Checks statement count at function/method/operator exit and emits error if too many.Enforces 'allow only' constraints on traits and classes (sealed type pattern).Checks call sites for ambiguous positional arguments.Check the assignment to a variable can be a single assignment or a deep copy type assignment.Detects if a closeable variable is being used in an "escape context" where ownership is transferred elsewhere.Tracks cognitive complexity within functions/methods/operators.Tracks method-field relationships to calculate LCOM4 (Lack of Cohesion of Methods v4).Designed to give a broad indication of complexity, this is not true pure Cyclometric Complexity.Detects tautological and contradictory compound conditions using range algebra (E08086/E08087).Finds all concrete (non-abstract) subtypes of a given abstract aggregate type.Detects confusingly similar variable, parameter, and field names within the same scope.Detects arithmetic expressions that always produce a constant result (E08083).Detects comparisons where both operands are literals (E08082).Tracks efferent coupling (Ce) - the number of external types a construct depends on.Validates that a module does not contain data clumps (E11053).Tracks function/method/constructor parameter signatures for data clump detection (E11053).An immutable (type, name) pair from a parameter, ordered for deterministic comparison.One callable's parameter signature for data clump analysis.Reports DI/AOP analysis to stderr when the
-diflag is set.Detects discarded return values in bare statement calls (E11050, E11051, E11052, E11055).Validates that no reachable type in a dispatcher's hierarchy resolves ambiguously between two or more handlers at equal cost.Validates that dispatchers on sealed traits have handlers for all permitted types.Validates that dispatcher handler parameter types are reachable from the base dispatch type's hierarchy.Deals with handling any returning values in a dynamic function.Checks for excessive type traversal in method chains (Law of Demeter).Tracks complexity of coalescing expression trees with depth-based multiplier.Once an expression has been assessed as being simple enough to process, this consumer is called to mark the appropriate symbol(s) used in the expression as safe if the appropriate methods are called.Just checks if the expression as defined by the ANTLR AST is simple enough to be assessed to make any Result/Optional get()/ok()/error() method calls safe.Classifies fields in an aggregate as service-type (abstract/interface) or data-type (concrete).Result of field classification for an aggregate.Detects conditions that are always true or always false based on data flow analysis (E08086/E08087).Does checks on both for loops and for range in terms of pre-flow and expressions (for loop).Predicate to determine if an expression is a Boolean logical operator (and/or) with Boolean type operands.When looking to calculate complexity of methods/functions it is important to work out if parts of an expression are in some way conditional.Checks the for structure via the code analysers.Typically checks any returning values to see if they have now been initialised on a function.Extracts the guard variable if there is a guard expression.Given an identifier, this consumer checks if it is a property of some aggregate.Emits an error if an identifier (typically a variable) has been used before being initialised.Does basic checks on the if condition to see if a Result/Optional access has been made safe.Deals with checking if all paths through if/else/else-if/else result in variables meeting criteria.Calculates the Depth of Inheritance Tree (DIT) for aggregate symbols.Tracks injection counts within functions/methods/operators.Detects circular dependencies in component injection chains per application (E08190).Validates ordering in application blocks (E08200).Detects logical tautologies and contradictions (E08085).Validates that a module does not contain repeated magic literals (E11065).Detects bare literals used as operands in comparison, relational, matching, and range expressions (E11064).Tracks literal occurrences across files for repeated magic literal detection (E11065).One recorded occurrence of a literal.A bit of a catch 22, need to issue errors and the like when traversing an identifier in some circumstances.Typically checks any returning values to see if they have now been initialised on a method.Tracks module-level cohesion by recording constructs and their intra-module type references.Tracks module-level efferent coupling (Ce) - the number of distinct external modules that a module depends on.Tracks nesting depth within functions/methods/operators.Detects non-descriptive variable names (E11031).In the case of specific variables of type like 'Result' and 'Optional' it is important to check if the method being called needs a previous call to isOk or isError or just '?' before accessing specific methods.Checks the object access start for uninitialised variable usage.Detects variable names that shadow operator keywords (E11032).Typically checks any returning values to see if they have now been initialised on an operator.Used as a base for a range of constructs that can be expressions.Detects string concatenation chains with 3 or more parts and recommends string interpolation instead (E11068).At this point all templates should be present and all symbols resolved.Designed to do additional logic checks once everything has been resolved.Checks that reveal() on Sensitive is only called from within classes that have the Privileged trait.Deals with handling any returning values in a dynamic function.Checks on a guard expression and marks the identifier variable as initialised.Validates that program injection fields are satisfied by the linked application (E08200).Detects comparisons of a Boolean expression with a Boolean literal (E08084).Detects empty checks that are always true or always false based on data flow analysis (E08092/E08093).Detects isSet checks that are always true or always false based on data flow analysis (E08088/E08089).Detects when an override method/operator body is textually identical to the super (E11044).Checks if return variables are initialised.Marks specific types of variable of specific types (generic Result/Option) in a manner that enables the compiler to check if access to certain methods is safe.Tests specific types of variable of specific types (generic Result/Option) in a manner that enables the compiler to check if access to certain methods is safe.It may be that before calling this you have determined that 'isSet' has been called or you 'know' that the value of the variable is present and set.Detects hardcoded secrets in string literals at compile time (E11080-E11086).Detects self-comparison expressions where both sides resolve to the same symbol (E08081).Typically checks any returning values to see if they have now been initialised on a service operation.Tracks statement counts within functions/methods/operators.Used with aggregates to check that if they have any properties that are not initialised at declaration the developer has taken appropriate steps to ensure initialisation.Deals with checking if all paths through switch/case/default (return) result in variables meeting criteria.Only triggers the call the retrieve the appropriate symbol for the node.Similar to the if block check, but this is focused on the true part of the ternary expression.Analyzes how traits are implemented in an aggregate to detect E11023 pattern (missing 'by' delegation).Result of analyzing trait implementation for potential missing 'by' delegation.Detects when multiple traits implemented by an aggregate have methods with the same signature.Post-parallel detector for transitive injection ordering validation.Checks the try/catch/finally structure via the code analysers.Union-Find (Disjoint Set Union) data structure for O(n * alpha(n)) connected components.Detects unused parameters in functions, methods, constructors, and service operations (E08091).Accepts a variable only declaration and ensures the variable is recorded if appropriate, for transient flow checks.Does checks on the control part of a while loop to see if Optional/Result/Iterator are now safe via method access.Checks the while statement via the code analysers.