/* * $Id$ * * SARL is an general-purpose agent programming language. * More details on http://www.sarl.io * * Copyright (C) 2014-2017 the original authors or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.sarl.lang.mwe2.codebuilder.extractor; import com.google.common.base.Objects; import com.google.inject.ImplementedBy; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.xtext.AbstractRule; import org.eclipse.xtext.Grammar; import org.eclipse.xtext.util.Strings; import org.eclipse.xtext.xbase.lib.Functions.Function4; import org.eclipse.xtext.xbase.lib.Pure; import org.eclipse.xtext.xtext.generator.model.TypeReference; import io.sarl.lang.mwe2.codebuilder.config.CodeBuilderConfig; import io.sarl.lang.mwe2.keywords.GrammarKeywordAccessFragment2; /** Extract elements from the grammar. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ @ImplementedBy(NoBacktrackGrammarCodeElementExtractor.class) public interface CodeElementExtractor { /** Replies the fully qualified name for the classifier. * * <p>Copied from AbstractSubCodeBuilderFragment. * * @param classifier the classifier. * @return the fully qualified name for the given classifier. */ TypeReference newTypeReference(EClassifier classifier); /** Replies the type that is generated by a rule. * * @param rule the rule. * @return the generated type. */ EClassifier getGeneratedTypeFor(AbstractRule rule); /** Replies the first classifier that is defined in the given grammar element. * * @param grammarElement the grammar element. * @return the classifier or <code>null</code> if none. */ EClassifier getGeneratedTypeFor(EObject grammarElement); /** Initialize the extractor. * * @param grammar the grammar to use. */ void initialize(Grammar grammar); /** Replies the interface for the code builder that is creating the element of the given name. * * @param elementName the name of the element. * @return the interface. */ @Pure TypeReference getElementBuilderInterface(String elementName); /** Replies the implementation for the code builder that is creating the element of the given name. * * @param elementName the name of the element. * @return the interface. */ @Pure TypeReference getElementBuilderImpl(String elementName); /** Replies the custom implementation for the code builder that is creating the element of the given name. * * @param elementName the name of the element. * @return the interface. */ @Pure TypeReference getElementBuilderImplCustom(String elementName); /** Replies the base package for the code builder. * * @return the base package for the code builder. */ @Pure String getBasePackage(); /** Replies the base package for the builders. * * @return the base package for the builders. */ @Pure String getAppenderPackage(); /** Replies the base package for the documentation tools. * * @return the base package for the documentation tools. */ @Pure String getDocumentationPackage(); /** Replies the adapter for inner-block documentation. * * @return the adapter. */ @Pure TypeReference getInnerBlockDocumentationAdapter(); /** Replies the base package for the serialization tools. * * @return the base package for the serialization tools. */ @Pure String getSerializerPackage(); /** Replies the base package for the builders. * * @return the base package for the builders. */ @Pure String getBuilderPackage(); /** Replies the type associated to the top elements. * * @return the type of the top elements. */ @Pure TypeReference getLanguageTopElementType(); /** Replies the type associated to the utility for accessing the keywords. * * @return the type of the languaage keyword accessor. * @see GrammarKeywordAccessFragment2 */ @Pure TypeReference getLanguageKeywordAccessor(); /** Replies the implementation for the code appender that is creating the element of the given name. * * @param elementName the name of the element. * @return the interface. */ @Pure TypeReference getElementAppenderImpl(String elementName); /** Replies the custom implementation for the code appender that is creating the element of the given name. * * @param elementName the name of the element. * @return the interface. */ @Pure TypeReference getElementAppenderImplCustom(String elementName); /** Replies the implementation for the code adapter. * * @return the implementation. */ @Pure TypeReference getAbstractAppenderImpl(); /** Replies the base package for the ecore elements of the grammar. * * @return the base package for the ecore elements. */ @Pure String getLanguageBasePackage(); /** Replies the type for the scripts from the grammar. * * @return the language script. */ @Pure TypeReference getLanguageScriptInterface(); /** Replies the the top elements of the grammar. * * @param grammar the grammar. * @param config the configuration. * @return the top elements. */ @Pure Iterable<ElementDescription> getTopElements(Grammar grammar, CodeBuilderConfig config); /** Extract type members from the given rule. * * <p>The callback functions are invoked for each member discovered in the grammar. * * <p>When a callback is replying a value, the visiting is stopping and the value is replied. * * @param <T> type of the value to extract. * @param element the element that is containing the members. * @param grammarContainer the member's container in the grammar. It is should be called by the grammar element * of the given element. * @param constructorCallback the function to call on each discovered constructor. * The parameters of the callback function are: the grammar container given to the visiting function; * and the grammar container of the member. * @param namedMemberCallback the function to call on each discovered named member. A named member is * a member that has a field "name" defined in the grammar. * The parameters of the callback function are: the grammar container given to the visiting function; * the grammar container of the member, and the name of the member. * @param typeReferencingMemberCallback the function to call on each discovered member that are referencing * types, for example a kind of "import". * The parameters of the callback function are: the grammar container given to the visiting function; * the grammar container of the member, and the name of the member. * @return the first value replied by the callback, or <code>null</code>. */ <T> T visitMemberElements( ElementDescription element, EObject grammarContainer, Function4<CodeElementExtractor, EObject, EObject, EClassifier, T> constructorCallback, Function4<CodeElementExtractor, EObject, EObject, EClassifier, T> namedMemberCallback, Function4<CodeElementExtractor, EObject, EObject, EClassifier, T> typeReferencingMemberCallback); /** Construct an element description. * * @param name the name of the element. * @param grammarComponent the grammar component of the element. * @param elementType the type of the element. * @param commonType the common type to all the elements in the same category. * @return the element description. */ default ElementDescription newElementDescription(String name, EObject grammarComponent, EClassifier elementType, EClassifier commonType) { return newElementDescription(name, grammarComponent, elementType, newTypeReference(commonType)); } /** Construct an element description. * * @param name the name of the element. * @param grammarComponent the grammar component of the element. * @param elementType the type of the element. * @param commonType the common type to all the elements in the same category. * @return the element description. */ default ElementDescription newElementDescription(String name, EObject grammarComponent, EClassifier elementType, Class<?> commonType) { return newElementDescription(name, grammarComponent, elementType, new TypeReference(commonType)); } /** Construct an element description. * * @param name the name of the element. * @param grammarComponent the grammar component of the element. * @param elementType the type of the element. * @param commonType the common type to all the elements in the same category. * @return the element description. */ ElementDescription newElementDescription(String name, EObject grammarComponent, EClassifier elementType, TypeReference commonType); /** Replies the description of the formal parameters. * * @return the description of the formal parameter. */ ElementDescription getFormalParameter(); /** Replies the type of the formal parameter container. * * @return the type of the formal parameter container. */ TypeReference getFormalParameterContainerType(); /** Replies the description of the type parameters. * * @return the description of the type parameter. */ ElementDescription getTypeParameter(); /** Description of an element. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ class ElementDescription { private final EObject grammarComponent; private final String name; private final TypeReference builderInterfaceType; private final TypeReference builderImplementationType; private final TypeReference builderCustomImplementationType; private final TypeReference appenderType; private final TypeReference elementType; private final TypeReference commonSuperType; private final boolean isAnnotationInfo; /** Construct a description. * * @param name the name of the element. * @param grammarComponent the grammar component of the element. * @param elementType the type for the element. * @param commonSuperType the common type to all the elements in the same category. * @param builderInterfaceType the type for the interface that corresponds to this element builder. * @param builderImplementationType the type for the class that corresponds to this element builder. * @param builderCustomImplementationType the type for the class that corresponds to this element builder. * @param appenderType the type for the class that corresponds to this element appender. * @param annotationInfo indicates if the annotationInfo field is declared for the element. */ ElementDescription(String name, EObject grammarComponent, TypeReference elementType, TypeReference commonSuperType, TypeReference builderInterfaceType, TypeReference builderImplementationType, TypeReference builderCustomImplementationType, TypeReference appenderType, boolean annotationInfo) { this.name = Strings.toFirstUpper(name); this.grammarComponent = grammarComponent; this.elementType = elementType; this.commonSuperType = commonSuperType; this.builderInterfaceType = builderInterfaceType; this.builderImplementationType = builderImplementationType; this.builderCustomImplementationType = builderCustomImplementationType; this.appenderType = appenderType; this.isAnnotationInfo = annotationInfo; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (this == obj) { return true; } if (ElementDescription.class.equals(obj.getClass())) { final ElementDescription desc = (ElementDescription) obj; return getElementType().equals(desc.getElementType()) && getName().equals(desc.getName()) && getBuilderInterfaceType().equals(desc.getBuilderInterfaceType()) && getBuilderImplementationType().equals(desc.getBuilderImplementationType()); } return false; } @Override public int hashCode() { return Objects.hashCode(getName(), getElementType(), getBuilderInterfaceType(), getBuilderImplementationType()); } @Override public String toString() { return getElementType().toString(); } /** Replies the type of the element. * * @return the type of the element. */ public TypeReference getElementType() { return this.elementType; } /** Replies the common super type to all the elements in the same category. * * @return the common super type of the element. */ public TypeReference getCommonSuperType() { return this.commonSuperType; } /** Replies the interface type for the element builder. * * @return the interface type. */ public TypeReference getBuilderInterfaceType() { return this.builderInterfaceType; } /** Replies the type for the element appender. * * @return the interface type. */ public TypeReference getAppenderType() { return this.appenderType; } /** Replies the implementation type for the element builder. * * @return the implementation type. */ public TypeReference getBuilderImplementationType() { return this.builderImplementationType; } /** Replies the custom implementation type for the element builder. * * @return the custom implementation type. */ public TypeReference getBuilderCustomImplementationType() { return this.builderCustomImplementationType; } /** Replies the grammar component that is associated to the element. * * @return the grammar component */ public EObject getGrammarComponent() { return this.grammarComponent; } /** Replies the name of the element. * * @return the name. */ public String getName() { return this.name; } /** Replies if the annotationInfo field is declared for the element. * * @return <code>true</code> if the annotationInfo is declared. */ public boolean isAnnotationInfo() { return this.isAnnotationInfo; } } }