<commit_before>package de.stefanocke.japkit.support

import de.stefanocke.japkit.gen.GenAnnotationMirror
import de.stefanocke.japkit.gen.GenElement
import de.stefanocke.japkit.gen.GenExtensions
import de.stefanocke.japkit.gen.GenParameter
import de.stefanocke.japkit.metaannotations.Param
import de.stefanocke.japkit.support.el.ELSupport
import de.stefanocke.japkit.support.el.ELVariableRule
import java.util.ArrayList
import java.util.Collections
import java.util.List
import java.util.Set
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.Element
import javax.lang.model.element.ExecutableElement
import javax.lang.model.element.Modifier
import javax.lang.model.element.VariableElement
import javax.lang.model.type.TypeMirror

import static extension de.stefanocke.japkit.util.MoreCollectionExtensions.*

/** Many rules have common components, for example annotation mappings or setting modifiers. This class provides
 * those common components as reusable closures. Each one establishes as certain naming convention for the according
 * annotation values, for example "nameExpr" for the AV the contains an expression to determine the name of the element to be generated.
 */
class RuleUtils {
	val protected extension ElementsExtensions = ExtensionRegistry.get(ElementsExtensions)
	val protected extension ELSupport = ExtensionRegistry.get(ELSupport)
	val protected extension MessageCollector = ExtensionRegistry.get(MessageCollector)
	val protected extension AnnotationExtensions  = ExtensionRegistry.get(AnnotationExtensions)
	val protected extension GenExtensions = ExtensionRegistry.get(GenExtensions)
	val protected extension TypeResolver typesResolver = ExtensionRegistry.get(TypeResolver)
	val protected extension GenerateClassContext = ExtensionRegistry.get(GenerateClassContext)
	val protected extension TypesExtensions = ExtensionRegistry.get(TypesExtensions)
	
	
	public static def withPrefix(String name, String prefix){
		(if(prefix.nullOrEmpty) name else '''«prefix»«name.toFirstUpper»''').toString
	}
	
	public static val ()=>Iterable<? extends Object> SINGLE_SRC_ELEMENT = [|  Collections.singleton(ExtensionRegistry.get(ELSupport).currentSrc)]
	
	/**
	 * To iterate over a collection of elements and apply the rule for each element.
	 */
	public def ()=>Iterable<? extends Object> createSrcExpressionRule(AnnotationMirror metaAnnotation, String avPrefix) {
		if(metaAnnotation==null) return SINGLE_SRC_ELEMENT
		
		val srcExpr = metaAnnotation.value("src".withPrefix(avPrefix), String)
		val srcLang = metaAnnotation.value("srcLang".withPrefix(avPrefix), String);

		[|
			val srcElements = if (srcExpr.nullOrEmpty) {
					null //Use parent's src. No new scope.
				} else {
					val elements = eval(srcExpr, srcLang, Object,
						'''Src expression «srcExpr» could not be evaluated''', emptyList)
						
					if(elements instanceof Iterable<?>){	
						(elements as Iterable<?>).filterInstanceOf(Element)					
					} else {
						Collections.singleton(elements)
					} 
				} 
			srcElements
		]
	}
	

	/**Scope rule that gets the source element from "src" AV */
	public def <T> ((Object)=>T)=>Iterable<T>  createScopeRule(AnnotationMirror metaAnnotation, String avPrefix) {
		createScopeRule(metaAnnotation, avPrefix, createSrcExpressionRule(metaAnnotation, avPrefix))
	}
	
	/**Rule that creates a new scope for each src element given by the source rule and executes the given closure within that scope. 
	 * Optionally puts EL-Variables into that scope. 
	 */
	public def <T> ((Object)=>T)=>Iterable<T>  createScopeRule(AnnotationMirror metaAnnotation, String avPrefix, ()=>Iterable<? extends Object> srcRule) {
			
		val srcVarName = metaAnnotation?.value("srcVar".withPrefix(avPrefix), String)
		val varRules = createELVariableRules(metaAnnotation, avPrefix);

		[(Object)=>T closure |
			val srcElements = srcRule?.apply	
			if (srcElements != null || !varRules.nullOrEmpty || !srcVarName.nullOrEmpty) {
				//as soon as a new src is defined or other EL variables, we need a new scope
				(srcElements ?: Collections.singleton(currentSrc)).map [ e |
					scope(e) [
						if(!srcVarName.nullOrEmpty){valueStack.put(srcVarName, e)}
						varRules?.forEach[it.putELVariable]
						closure.apply(e)
					]
				]
			} else {
				// No new scope required. Use parent's src.
				applyInExistingScope(closure)
			}
		
		]
	}
	
	public static def <T> applyInExistingScope((Object)=>T closure) {
		Collections.singleton(closure.apply(ExtensionRegistry.get(ELSupport).currentSrc))
	}<commit_msg>make sure, the scope rule is eagerly applied<commit_after>package de.stefanocke.japkit.support

import de.stefanocke.japkit.gen.GenAnnotationMirror
import de.stefanocke.japkit.gen.GenElement
import de.stefanocke.japkit.gen.GenExtensions
import de.stefanocke.japkit.gen.GenParameter
import de.stefanocke.japkit.metaannotations.Param
import de.stefanocke.japkit.support.el.ELSupport
import de.stefanocke.japkit.support.el.ELVariableRule
import java.util.ArrayList
import java.util.Collections
import java.util.List
import java.util.Set
import javax.lang.model.element.AnnotationMirror
import javax.lang.model.element.Element
import javax.lang.model.element.ExecutableElement
import javax.lang.model.element.Modifier
import javax.lang.model.element.VariableElement
import javax.lang.model.type.TypeMirror

import static extension de.stefanocke.japkit.util.MoreCollectionExtensions.*

/** Many rules have common components, for example annotation mappings or setting modifiers. This class provides
 * those common components as reusable closures. Each one establishes as certain naming convention for the according
 * annotation values, for example "nameExpr" for the AV the contains an expression to determine the name of the element to be generated.
 */
class RuleUtils {
	val protected extension ElementsExtensions = ExtensionRegistry.get(ElementsExtensions)
	val protected extension ELSupport = ExtensionRegistry.get(ELSupport)
	val protected extension MessageCollector = ExtensionRegistry.get(MessageCollector)
	val protected extension AnnotationExtensions  = ExtensionRegistry.get(AnnotationExtensions)
	val protected extension GenExtensions = ExtensionRegistry.get(GenExtensions)
	val protected extension TypeResolver typesResolver = ExtensionRegistry.get(TypeResolver)
	val protected extension GenerateClassContext = ExtensionRegistry.get(GenerateClassContext)
	val protected extension TypesExtensions = ExtensionRegistry.get(TypesExtensions)
	
	
	public static def withPrefix(String name, String prefix){
		(if(prefix.nullOrEmpty) name else '''«prefix»«name.toFirstUpper»''').toString
	}
	
	public static val ()=>Iterable<? extends Object> SINGLE_SRC_ELEMENT = [|  Collections.singleton(ExtensionRegistry.get(ELSupport).currentSrc)]
	
	/**
	 * To iterate over a collection of elements and apply the rule for each element.
	 */
	public def ()=>Iterable<? extends Object> createSrcExpressionRule(AnnotationMirror metaAnnotation, String avPrefix) {
		if(metaAnnotation==null) return SINGLE_SRC_ELEMENT
		
		val srcExpr = metaAnnotation.value("src".withPrefix(avPrefix), String)
		val srcLang = metaAnnotation.value("srcLang".withPrefix(avPrefix), String);

		[|
			val srcElements = if (srcExpr.nullOrEmpty) {
					null //Use parent's src. No new scope.
				} else {
					val elements = eval(srcExpr, srcLang, Object,
						'''Src expression «srcExpr» could not be evaluated''', emptyList)
						
					if(elements instanceof Iterable<?>){	
						(elements as Iterable<?>).filterInstanceOf(Element)					
					} else {
						Collections.singleton(elements)
					} 
				} 
			srcElements
		]
	}
	

	/**Scope rule that gets the source element from "src" AV */
	public def <T> ((Object)=>T)=>Iterable<T>  createScopeRule(AnnotationMirror metaAnnotation, String avPrefix) {
		createScopeRule(metaAnnotation, avPrefix, createSrcExpressionRule(metaAnnotation, avPrefix))
	}
	
	/**Rule that creates a new scope for each src element given by the source rule and executes the given closure within that scope. 
	 * Optionally puts EL-Variables into that scope. 
	 */
	public def <T> ((Object)=>T)=>Iterable<T>  createScopeRule(AnnotationMirror metaAnnotation, String avPrefix, ()=>Iterable<? extends Object> srcRule) {
			
		val srcVarName = metaAnnotation?.value("srcVar".withPrefix(avPrefix), String)
		val varRules = createELVariableRules(metaAnnotation, avPrefix);

		[(Object)=>T closure |
			val srcElements = srcRule?.apply	
			if (srcElements != null || !varRules.nullOrEmpty || !srcVarName.nullOrEmpty) {
				//as soon as a new src is defined or other EL variables, we need a new scope
				(srcElements ?: Collections.singleton(currentSrc)).map [ e |
					scope(e) [
						if(!srcVarName.nullOrEmpty){valueStack.put(srcVarName, e)}
						varRules?.forEach[it.putELVariable]
						closure.apply(e)
					]
				].toList
			} else {
				// No new scope required. Use parent's src.
				applyInExistingScope(closure)
			}
		
		]
	}
	
	public static def <T> applyInExistingScope((Object)=>T closure) {
		Collections.singleton(closure.apply(ExtensionRegistry.get(ELSupport).currentSrc))
	}
{'fraction_non_alphanumeric': 0.09361982021486516, 'fraction_numerical': 0.0, 'mean_word_length': 4.935588809368901, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1698855', 'n_tokens_mistral': 2834, 'n_tokens_neox': 2515, 'n_words': 714}