org.codehaus.groovy.control.SourceUnit Java Examples
The following examples show how to use
org.codehaus.groovy.control.SourceUnit.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PicocliScriptASTTransformation.java From picocli with Apache License 2.0 | 6 votes |
private void changeBaseScriptTypeFromDeclaration(final SourceUnit source, final DeclarationExpression de, final AnnotationNode node) { if (de.isMultipleAssignmentDeclaration()) { addError("Annotation " + MY_TYPE_NAME + " not supported with multiple assignment notation.", de); return; } ClassNode cNode = de.getDeclaringClass(); ClassNode baseScriptType = de.getVariableExpression().getType().getPlainNodeReference(); if (baseScriptType.isScript()) { if (!(de.getRightExpression() instanceof EmptyExpression)) { addError("Annotation " + MY_TYPE_NAME + " not supported with variable assignment.", de); return; } de.setRightExpression(new VariableExpression("this")); } else { baseScriptType = BASE_SCRIPT_TYPE; } Expression value = node.getMember("value"); if (value != null) { addError("Annotation " + MY_TYPE_NAME + " cannot have member 'value' if used on a declaration.", value); return; } changeBaseScriptType(source, de, cNode, baseScriptType, node); }
Example #2
Source File: ExternalizeMethodsASTTransformation.java From groovy with Apache License 2.0 | 6 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode anno = (AnnotationNode) nodes[0]; if (!MY_TYPE.equals(anno.getClassNode())) return; if (parent instanceof ClassNode) { ClassNode cNode = (ClassNode) parent; if (!checkNotInterface(cNode, MY_TYPE_NAME)) return; cNode.addInterface(EXTERNALIZABLE_TYPE); boolean includeFields = memberHasValue(anno, "includeFields", true); List<String> excludes = getMemberStringList(anno, "excludes"); if (!checkPropertyList(cNode, excludes, "excludes", anno, MY_TYPE_NAME, includeFields)) return; List<FieldNode> list = getInstancePropertyFields(cNode); if (includeFields) { list.addAll(getInstanceNonPropertyFields(cNode)); } createWriteExternal(cNode, excludes, list); createReadExternal(cNode, excludes, list); } }
Example #3
Source File: TestMethodUtilTest.java From netbeans with Apache License 2.0 | 6 votes |
private ModuleNode createGroovyModuleNode() { final CompilerConfiguration conf = new CompilerConfiguration(); conf.setTargetDirectory(compileDir); final CompilationUnit cu = new CompilationUnit( new GroovyClassLoader( getClass().getClassLoader() ) ); cu.configure(conf); final SourceUnit sn = cu.addSource("AGroovyClass.groovy", groovyScript.toString()); try { cu.compile(); } catch (Exception e) { //this groovy compile bit didn't work when running tests //but did work when debugging them, so odd, but the AST is in //place either way, and is all we need for this this.log(e.getMessage()); } final ModuleNode mn = sn.getAST(); return mn; }
Example #4
Source File: ExtendedGroovyClassLoader.java From everrest with Eclipse Public License 2.0 | 6 votes |
@Override protected Class createClass(byte[] code, ClassNode classNode) { ExtendedInnerLoader cl = (ExtendedInnerLoader)getDefiningClassLoader(); Class clazz = cl.defineClass(classNode.getName(), code, cunit.getAST().getCodeSource()); getLoadedClasses().add(clazz); if (target == null) { ClassNode targetClassNode = null; SourceUnit targetSunit = null; ModuleNode module = classNode.getModule(); if (module != null) { targetClassNode = module.getClasses().get(0); targetSunit = module.getContext(); } if (targetSunit == sunit && targetClassNode == classNode) { target = clazz; } } return clazz; }
Example #5
Source File: TraitASTTransformation.java From groovy with Apache License 2.0 | 6 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode anno = (AnnotationNode) nodes[0]; if (!Traits.TRAIT_CLASSNODE.equals(anno.getClassNode())) return; unit = source; init(nodes, source); if (parent instanceof ClassNode) { ClassNode cNode = (ClassNode) parent; if (!checkNotInterface(cNode, Traits.TRAIT_TYPE_NAME)) return; checkNoConstructor(cNode); checkExtendsClause(cNode); generateMethodsWithDefaultArgs(cNode); replaceExtendsByImplements(cNode); ClassNode helperClassNode = createHelperClass(cNode); resolveHelperClassIfNecessary(helperClassNode); } }
Example #6
Source File: ExternalizeVerifierASTTransformation.java From groovy with Apache License 2.0 | 6 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode anno = (AnnotationNode) nodes[0]; if (!MY_TYPE.equals(anno.getClassNode())) return; if (parent instanceof ClassNode) { ClassNode cNode = (ClassNode) parent; if (!hasNoArgConstructor(cNode)) { addError(MY_TYPE_NAME + ": An Externalizable class requires a no-arg constructor but none found", cNode); } if (!implementsExternalizable(cNode)) { addError(MY_TYPE_NAME + ": An Externalizable class must implement the Externalizable interface", cNode); } boolean includeFields = memberHasValue(anno, "includeFields", true); boolean checkPropertyTypes = memberHasValue(anno, "checkPropertyTypes", true); List<String> excludes = getMemberStringList(anno, "excludes"); if (!checkPropertyList(cNode, excludes, "excludes", anno, MY_TYPE_NAME, includeFields)) return; List<FieldNode> list = getInstancePropertyFields(cNode); if (includeFields) { list.addAll(getInstanceNonPropertyFields(cNode)); } checkProps(list, excludes, checkPropertyTypes); } }
Example #7
Source File: ASTTransformer.java From pom-manipulation-ext with Apache License 2.0 | 6 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode node = (AnnotationNode) nodes[0]; if (MAVEN_TYPE.equals( node.getClassNode()) || GRADLE_TYPE.equals( node.getClassNode() )) { type = ( MAVEN_TYPE.equals( node.getClassNode()) ) ? Type.MAVEN : Type.GRADLE; if ( parent instanceof DeclarationExpression ) { changeBaseScriptTypeFromDeclaration( (DeclarationExpression) parent, node ); } else if ( parent instanceof ImportNode || parent instanceof PackageNode ) { changeBaseScriptTypeFromPackageOrImport( source, parent, node ); } else if ( parent instanceof ClassNode ) { changeBaseScriptTypeFromClass( (ClassNode) parent ); } } }
Example #8
Source File: PicocliScriptASTTransformation.java From picocli with Apache License 2.0 | 6 votes |
private void changeBaseScriptTypeFromPackageOrImport(final SourceUnit source, final AnnotatedNode parent, final AnnotationNode node) { Expression value = node.getMember("value"); ClassNode scriptType; if (value == null) { scriptType = BASE_SCRIPT_TYPE; } else { if (!(value instanceof ClassExpression)) { addError("Annotation " + MY_TYPE_NAME + " member 'value' should be a class literal.", value); return; } scriptType = value.getType(); } List<ClassNode> classes = source.getAST().getClasses(); for (ClassNode classNode : classes) { if (classNode.isScriptBody()) { changeBaseScriptType(source, parent, classNode, scriptType, node); } } }
Example #9
Source File: CategoryASTTransformation.java From groovy with Apache License 2.0 | 6 votes |
private static boolean ensureNoInstanceFieldOrProperty(final SourceUnit source, final ClassNode parent) { boolean valid = true; for (FieldNode fieldNode : parent.getFields()) { if (!fieldNode.isStatic() && fieldNode.getLineNumber()>0) { // if <0, probably an AST transform or internal code (like generated metaclass field, ...) addUnsupportedError(fieldNode, source); valid = false; } } for (PropertyNode propertyNode : parent.getProperties()) { if (!propertyNode.isStatic() && propertyNode.getLineNumber()>0) { // if <0, probably an AST transform or internal code (like generated metaclass field, ...) addUnsupportedError(propertyNode, source); valid = false; } } return valid; }
Example #10
Source File: AutoImplementASTTransformation.java From groovy with Apache License 2.0 | 6 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode anno = (AnnotationNode) nodes[0]; if (!MY_TYPE.equals(anno.getClassNode())) return; if (parent instanceof ClassNode) { ClassNode cNode = (ClassNode) parent; if (!checkNotInterface(cNode, MY_TYPE_NAME)) return; ClassNode exception = getMemberClassValue(anno, "exception"); if (exception != null && Undefined.isUndefinedException(exception)) { exception = null; } String message = getMemberStringValue(anno, "message"); Expression code = anno.getMember("code"); if (code != null && !(code instanceof ClosureExpression)) { addError("Expected closure value for annotation parameter 'code'. Found " + code, cNode); return; } createMethods(cNode, exception, message, (ClosureExpression) code); if (code != null) { anno.setMember("code", new ClosureExpression(Parameter.EMPTY_ARRAY, EmptyStatement.INSTANCE)); } } }
Example #11
Source File: TraitComposer.java From groovy with Apache License 2.0 | 6 votes |
/** * Given a class node, if this class node implements a trait, then generate all the appropriate * code which delegates calls to the trait. It is safe to call this method on a class node which * does not implement a trait. * @param cNode a class node * @param unit the source unit */ public static void doExtendTraits(final ClassNode cNode, final SourceUnit unit, final CompilationUnit cu) { if (cNode.isInterface()) return; boolean isItselfTrait = Traits.isTrait(cNode); SuperCallTraitTransformer superCallTransformer = new SuperCallTraitTransformer(unit); if (isItselfTrait) { checkTraitAllowed(cNode, unit); return; } if (!cNode.getNameWithoutPackage().endsWith(Traits.TRAIT_HELPER)) { List<ClassNode> traits = Traits.findTraits(cNode); for (ClassNode trait : traits) { TraitHelpersTuple helpers = Traits.findHelpers(trait); applyTrait(trait, cNode, helpers, unit); superCallTransformer.visitClass(cNode); if (unit!=null) { ASTTransformationCollectorCodeVisitor collector = new ASTTransformationCollectorCodeVisitor(unit, cu.getTransformLoader()); collector.visitClass(cNode); } } } }
Example #12
Source File: PowsyblDslAstTransformation.java From powsybl-core with Mozilla Public License 2.0 | 6 votes |
protected void visit(SourceUnit sourceUnit, ClassCodeExpressionTransformer transformer) { LOGGER.trace("Apply AST transformation"); ModuleNode ast = sourceUnit.getAST(); BlockStatement blockStatement = ast.getStatementBlock(); if (DEBUG) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(AstUtil.toString(blockStatement)); } } List<MethodNode> methods = ast.getMethods(); for (MethodNode methodNode : methods) { methodNode.getCode().visit(transformer); } blockStatement.visit(transformer); if (DEBUG) { if (LOGGER.isDebugEnabled()) { LOGGER.debug(AstUtil.toString(blockStatement)); } } }
Example #13
Source File: MacroGroovyMethods.java From groovy with Apache License 2.0 | 6 votes |
protected static ClosureExpression getClosureArgument(SourceUnit source, MethodCallExpression call) { TupleExpression tupleArguments = getMacroArguments(source, call); int size = tupleArguments == null ? -1 : tupleArguments.getExpressions().size(); if (size < 1) { source.addError(new SyntaxException("Call arguments should have at least one argument" + '\n', tupleArguments)); return null; } Expression result = tupleArguments.getExpression(size - 1); if (!(result instanceof ClosureExpression)) { source.addError(new SyntaxException("Last call argument should be a closure" + '\n', result)); return null; } return (ClosureExpression) result; }
Example #14
Source File: NewifyASTTransformation.java From groovy with Apache License 2.0 | 6 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { this.source = source; if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { internalError("Expecting [AnnotationNode, AnnotatedClass] but got: " + Arrays.asList(nodes)); } AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode node = (AnnotationNode) nodes[0]; if (!MY_TYPE.equals(node.getClassNode())) { internalError("Transformation called from wrong annotation: " + node.getClassNode().getName()); } final boolean autoFlag = determineAutoFlag(node.getMember("auto")); final Expression classNames = node.getMember("value"); final Pattern cnPattern = determineClassNamePattern(node.getMember("pattern")); if (parent instanceof ClassNode) { newifyClass((ClassNode) parent, autoFlag, determineClasses(classNames, false), cnPattern); } else if (parent instanceof MethodNode || parent instanceof FieldNode) { newifyMethodOrField(parent, autoFlag, determineClasses(classNames, false), cnPattern); } else if (parent instanceof DeclarationExpression) { newifyDeclaration((DeclarationExpression) parent, autoFlag, determineClasses(classNames, true), cnPattern); } }
Example #15
Source File: NullCheckASTTransformation.java From groovy with Apache License 2.0 | 6 votes |
@Override public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode anno = (AnnotationNode) nodes[0]; if (!NULL_CHECK_TYPE.equals(anno.getClassNode())) return; boolean includeGenerated = isIncludeGenerated(anno); if (parent instanceof ClassNode) { ClassNode cNode = (ClassNode) parent; if (!checkNotInterface(cNode, NULL_CHECK_NAME)) return; for (ConstructorNode cn : cNode.getDeclaredConstructors()) { adjustMethod(cn, includeGenerated); } for (MethodNode mn : cNode.getAllDeclaredMethods()) { adjustMethod(mn, includeGenerated); } } else if (parent instanceof MethodNode) { // handles constructor case too adjustMethod((MethodNode) parent, false); } }
Example #16
Source File: MarkupTemplateEngine.java From groovy with Apache License 2.0 | 6 votes |
public MarkupTemplateEngine(final ClassLoader parentLoader, final TemplateConfiguration tplConfig, final TemplateResolver resolver) { compilerConfiguration = new CompilerConfiguration(); templateConfiguration = tplConfig; compilerConfiguration.addCompilationCustomizers(new TemplateASTTransformer(tplConfig)); compilerConfiguration.addCompilationCustomizers( new ASTTransformationCustomizer(Collections.singletonMap("extensions", "groovy.text.markup.MarkupTemplateTypeCheckingExtension"), CompileStatic.class)); if (templateConfiguration.isAutoNewLine()) { compilerConfiguration.addCompilationCustomizers( new CompilationCustomizer(CompilePhase.CONVERSION) { @Override public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException { new AutoNewLineTransformer(source).visitClass(classNode); } } ); } groovyClassLoader = AccessController.doPrivileged((PrivilegedAction<TemplateGroovyClassLoader>) () -> new TemplateGroovyClassLoader(parentLoader, compilerConfiguration)); if (DEBUG_BYTECODE) { compilerConfiguration.setBytecodePostprocessor(BytecodeDumper.STANDARD_ERR); } templateResolver = resolver == null ? new DefaultTemplateResolver() : resolver; templateResolver.configure(groovyClassLoader, templateConfiguration); }
Example #17
Source File: IndexedPropertyASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode node = (AnnotationNode) nodes[0]; if (!MY_TYPE.equals(node.getClassNode())) return; if (parent instanceof FieldNode) { FieldNode fNode = (FieldNode) parent; ClassNode cNode = fNode.getDeclaringClass(); if (cNode.getProperty(fNode.getName()) == null) { addError("Error during " + MY_TYPE_NAME + " processing. Field '" + fNode.getName() + "' doesn't appear to be a property; incorrect visibility?", fNode); return; } ClassNode fType = fNode.getType(); if (fType.isArray()) { addArraySetter(fNode); addArrayGetter(fNode); } else if (fType.isDerivedFrom(LIST_TYPE)) { addListSetter(fNode); addListGetter(fNode); } else { addError("Error during " + MY_TYPE_NAME + " processing. Non-Indexable property '" + fNode.getName() + "' found. Type must be array or list but found " + fType.getName(), fNode); } } }
Example #18
Source File: ASTNodeVisitor.java From groovy-language-server with Apache License 2.0 | 5 votes |
public void visitSourceUnit(SourceUnit unit) { sourceUnit = unit; URI uri = sourceUnit.getSource().getURI(); nodesByURI.put(uri, new ArrayList<>()); classNodesByURI.put(uri, new ArrayList<>()); stack.clear(); ModuleNode moduleNode = unit.getAST(); if (moduleNode != null) { visitModule(moduleNode); } sourceUnit = null; stack.clear(); }
Example #19
Source File: AstUtils.java From Pushjet-Android with BSD 2-Clause "Simplified" License | 5 votes |
public static void visitScriptCode(SourceUnit source, GroovyCodeVisitor transformer) { source.getAST().getStatementBlock().visit(transformer); for (Object method : source.getAST().getMethods()) { MethodNode methodNode = (MethodNode) method; methodNode.getCode().visit(transformer); } }
Example #20
Source File: DetectorTransform.java From pushfish-android with BSD 2-Clause "Simplified" License | 5 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { if (nodes.length == 0 || !(nodes[0] instanceof ModuleNode)) { source.getErrorCollector().addError(new SimpleMessage( "internal error in DetectorTransform", source)); return; } ModuleNode module = (ModuleNode)nodes[0]; for (ClassNode clazz : (List<ClassNode>)module.getClasses()) { FieldNode field = clazz.getField(VERSION_FIELD_NAME); if (field != null) { field.setInitialValueExpression(new ConstantExpression(ReleaseInfo.getVersion())); break; } } }
Example #21
Source File: TemplateASTTransformer.java From groovy with Apache License 2.0 | 5 votes |
@Override public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException { if (classNode.isScriptBody()) { classNode.setSuperClass(ClassHelper.make(config.getBaseTemplateClass())); createConstructor(classNode); transformRunMethod(classNode, source); VariableScopeVisitor visitor = new VariableScopeVisitor(source); visitor.visitClass(classNode); } }
Example #22
Source File: AstUtils.java From pushfish-android with BSD 2-Clause "Simplified" License | 5 votes |
public static void visitScriptCode(SourceUnit source, GroovyCodeVisitor transformer) { source.getAST().getStatementBlock().visit(transformer); for (Object method : source.getAST().getMethods()) { MethodNode methodNode = (MethodNode) method; methodNode.getCode().visit(transformer); } }
Example #23
Source File: AstUtils.java From pushfish-android with BSD 2-Clause "Simplified" License | 5 votes |
public static ClassNode getScriptClass(SourceUnit source) { if (source.getAST().getStatementBlock().getStatements().isEmpty() && source.getAST().getMethods().isEmpty()) { // There is no script class when there are no statements or methods declared in the script return null; } return source.getAST().getClasses().get(0); }
Example #24
Source File: SortableASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotationNode annotation = (AnnotationNode) nodes[0]; AnnotatedNode parent = (AnnotatedNode) nodes[1]; if (parent instanceof ClassNode) { createSortable(annotation, (ClassNode) parent); } }
Example #25
Source File: ImmutableASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode anno = (AnnotationNode) nodes[0]; if (!MY_TYPE.equals(anno.getClassNode())) return; if (parent instanceof ClassNode) { final GroovyClassLoader classLoader = compilationUnit != null ? compilationUnit.getTransformLoader() : source.getClassLoader(); final PropertyHandler handler = PropertyHandler.createPropertyHandler(this, classLoader, (ClassNode) parent); if (handler == null) return; if (!handler.validateAttributes(this, anno)) return; doMakeImmutable((ClassNode) parent, anno, handler); } }
Example #26
Source File: AstUtils.java From Pushjet-Android with BSD 2-Clause "Simplified" License | 5 votes |
public static boolean isVisible(SourceUnit source, String className) { try { source.getClassLoader().loadClass(className); return true; } catch (ClassNotFoundException e) { return false; } }
Example #27
Source File: MyIntegerAnnoTraceASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
public void visit(ASTNode[] nodes, final SourceUnit source) { if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) { throw new RuntimeException("Internal error: expecting [AnnotationNode, AnnotatedNode] but got: " + Arrays.asList(nodes)); } AnnotatedNode parent = (AnnotatedNode) nodes[1]; File f = new File("temp/log.txt"); try { ResourceGroovyMethods.append(f, parent.getClass().getSimpleName() + " " + parent.getAnnotations().get(0).getMember("value").getText() + " "); } catch (IOException e) { e.printStackTrace(); } }
Example #28
Source File: InheritConstructorsASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotationNode anno = (AnnotationNode) nodes[0]; AnnotatedNode target = (AnnotatedNode) nodes[1]; if (INHERIT_CONSTRUCTORS_TYPE.equals(anno.getClassNode()) && target instanceof ClassNode) { processClass((ClassNode) target, anno); } }
Example #29
Source File: VetoableASTTransformation.java From groovy with Apache License 2.0 | 5 votes |
/** * Snoops through the declaring class and all parents looking for a field * of type VetoableChangeSupport. Remembers the field and returns false * if found otherwise returns true to indicate that such support should * be added. * * @param declaringClass the class to search * @return true if vetoable change support should be added */ protected boolean needsVetoableChangeSupport(ClassNode declaringClass, SourceUnit sourceUnit) { boolean foundAdd = false, foundRemove = false, foundFire = false; ClassNode consideredClass = declaringClass; while (consideredClass!= null) { for (MethodNode method : consideredClass.getMethods()) { // just check length, MOP will match it up foundAdd = foundAdd || method.getName().equals("addVetoableChangeListener") && method.getParameters().length == 1; foundRemove = foundRemove || method.getName().equals("removeVetoableChangeListener") && method.getParameters().length == 1; foundFire = foundFire || method.getName().equals("fireVetoableChange") && method.getParameters().length == 3; if (foundAdd && foundRemove && foundFire) { return false; } } consideredClass = consideredClass.getSuperClass(); } // check if a super class has @Vetoable annotations consideredClass = declaringClass.getSuperClass(); while (consideredClass!=null) { if (hasVetoableAnnotation(consideredClass)) return false; for (FieldNode field : consideredClass.getFields()) { if (hasVetoableAnnotation(field)) return false; } consideredClass = consideredClass.getSuperClass(); } if (foundAdd || foundRemove || foundFire) { sourceUnit.getErrorCollector().addErrorAndContinue( new SimpleMessage("@Vetoable cannot be processed on " + declaringClass.getName() + " because some but not all of addVetoableChangeListener, removeVetoableChange, and fireVetoableChange were declared in the current or super classes.", sourceUnit) ); return false; } return true; }
Example #30
Source File: FilteringStatementTransformer.java From Pushjet-Android with BSD 2-Clause "Simplified" License | 5 votes |
public Statement transform(SourceUnit sourceUnit, Statement statement) { if (spec.isSatisfiedBy(statement)) { return statement; } else { return null; } }