| /** |
| * Copyright (c) 2016 TypeFox and others. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| package org.eclipse.lsp4j.generator; |
| |
| import com.google.common.base.Objects; |
| import com.google.common.collect.Iterables; |
| import com.google.gson.annotations.JsonAdapter; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.function.Consumer; |
| import org.eclipse.lsp4j.generator.EitherTypeArgument; |
| import org.eclipse.lsp4j.generator.JsonRpcData; |
| import org.eclipse.lsp4j.generator.JsonRpcDataTransformationContext; |
| import org.eclipse.lsp4j.generator.JsonType; |
| import org.eclipse.lsp4j.jsonrpc.validation.NonNull; |
| import org.eclipse.xtend.lib.annotations.AccessorsProcessor; |
| import org.eclipse.xtend.lib.annotations.EqualsHashCodeProcessor; |
| import org.eclipse.xtend.lib.macro.AbstractClassProcessor; |
| import org.eclipse.xtend.lib.macro.TransformationContext; |
| import org.eclipse.xtend.lib.macro.declaration.AnnotationReference; |
| import org.eclipse.xtend.lib.macro.declaration.AnnotationTypeDeclaration; |
| import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration; |
| import org.eclipse.xtend.lib.macro.declaration.CompilationStrategy; |
| import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration; |
| import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration; |
| import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration; |
| import org.eclipse.xtend.lib.macro.declaration.MutableMethodDeclaration; |
| import org.eclipse.xtend.lib.macro.declaration.MutableParameterDeclaration; |
| import org.eclipse.xtend.lib.macro.declaration.Type; |
| import org.eclipse.xtend.lib.macro.declaration.TypeDeclaration; |
| import org.eclipse.xtend.lib.macro.declaration.TypeReference; |
| import org.eclipse.xtend.lib.macro.declaration.Visibility; |
| import org.eclipse.xtend2.lib.StringConcatenation; |
| import org.eclipse.xtend2.lib.StringConcatenationClient; |
| import org.eclipse.xtext.xbase.lib.CollectionLiterals; |
| import org.eclipse.xtext.xbase.lib.Extension; |
| import org.eclipse.xtext.xbase.lib.Functions.Function1; |
| import org.eclipse.xtext.xbase.lib.IterableExtensions; |
| import org.eclipse.xtext.xbase.lib.ObjectExtensions; |
| import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; |
| import org.eclipse.xtext.xbase.lib.Pure; |
| import org.eclipse.xtext.xbase.lib.util.ToStringBuilder; |
| |
| @SuppressWarnings("all") |
| public class JsonRpcDataProcessor extends AbstractClassProcessor { |
| @Override |
| public void doTransform(final MutableClassDeclaration annotatedClass, final TransformationContext context) { |
| this.generateImpl(annotatedClass, context); |
| } |
| |
| protected MutableClassDeclaration generateImpl(final MutableClassDeclaration impl, @Extension final TransformationContext context) { |
| final Function1<AnnotationReference, Boolean> _function = (AnnotationReference it) -> { |
| AnnotationTypeDeclaration _annotationTypeDeclaration = it.getAnnotationTypeDeclaration(); |
| Type _findTypeGlobally = context.findTypeGlobally(JsonRpcData.class); |
| return Boolean.valueOf(Objects.equal(_annotationTypeDeclaration, _findTypeGlobally)); |
| }; |
| impl.removeAnnotation(IterableExtensions.findFirst(impl.getAnnotations(), _function)); |
| JsonRpcDataTransformationContext _jsonRpcDataTransformationContext = new JsonRpcDataTransformationContext(context); |
| this.generateImplMembers(impl, _jsonRpcDataTransformationContext); |
| this.generateToString(impl, context); |
| Type _type = impl.getExtendedClass().getType(); |
| Type _type_1 = context.newTypeReference(Object.class).getType(); |
| final boolean shouldIncludeSuper = (!Objects.equal(_type, _type_1)); |
| final EqualsHashCodeProcessor.Util equalsHashCodeUtil = new EqualsHashCodeProcessor.Util(context); |
| final Function1<MutableFieldDeclaration, Boolean> _function_1 = (MutableFieldDeclaration it) -> { |
| boolean _isStatic = it.isStatic(); |
| return Boolean.valueOf((!_isStatic)); |
| }; |
| final Iterable<? extends MutableFieldDeclaration> fields = IterableExtensions.filter(impl.getDeclaredFields(), _function_1); |
| equalsHashCodeUtil.addEquals(impl, fields, shouldIncludeSuper); |
| equalsHashCodeUtil.addHashCode(impl, fields, shouldIncludeSuper); |
| return impl; |
| } |
| |
| protected void generateImplMembers(final MutableClassDeclaration impl, @Extension final JsonRpcDataTransformationContext context) { |
| final Function1<MutableFieldDeclaration, Boolean> _function = (MutableFieldDeclaration it) -> { |
| boolean _isStatic = it.isStatic(); |
| return Boolean.valueOf((!_isStatic)); |
| }; |
| final Consumer<MutableFieldDeclaration> _function_1 = (MutableFieldDeclaration field) -> { |
| final AccessorsProcessor.Util accessorsUtil = new AccessorsProcessor.Util(context); |
| final AnnotationReference deprecated = field.findAnnotation(context.findTypeGlobally(Deprecated.class)); |
| accessorsUtil.addGetter(field, Visibility.PUBLIC); |
| AnnotationReference _findAnnotation = field.findAnnotation(context.newTypeReference(NonNull.class).getType()); |
| final boolean hasNonNull = (_findAnnotation != null); |
| AnnotationReference _findAnnotation_1 = field.findAnnotation(context.newTypeReference(JsonAdapter.class).getType()); |
| final boolean hasJsonAdapter = (_findAnnotation_1 != null); |
| MutableMethodDeclaration _findDeclaredMethod = impl.findDeclaredMethod(accessorsUtil.getGetterName(field)); |
| final Procedure1<MutableMethodDeclaration> _function_2 = (MutableMethodDeclaration it) -> { |
| it.setDocComment(field.getDocComment()); |
| if (hasNonNull) { |
| it.addAnnotation(context.newAnnotationReference(NonNull.class)); |
| } |
| if ((deprecated != null)) { |
| it.addAnnotation(context.newAnnotationReference(Deprecated.class)); |
| } |
| }; |
| ObjectExtensions.<MutableMethodDeclaration>operator_doubleArrow(_findDeclaredMethod, _function_2); |
| boolean _isInferred = field.getType().isInferred(); |
| boolean _not = (!_isInferred); |
| if (_not) { |
| accessorsUtil.addSetter(field, Visibility.PUBLIC); |
| final String setterName = accessorsUtil.getSetterName(field); |
| MutableMethodDeclaration _findDeclaredMethod_1 = impl.findDeclaredMethod(setterName, field.getType()); |
| final Procedure1<MutableMethodDeclaration> _function_3 = (MutableMethodDeclaration it) -> { |
| it.setDocComment(field.getDocComment()); |
| if (hasNonNull) { |
| final MutableParameterDeclaration parameter = IterableExtensions.head(it.getParameters()); |
| parameter.addAnnotation(context.newAnnotationReference(NonNull.class)); |
| StringConcatenationClient _client = new StringConcatenationClient() { |
| @Override |
| protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) { |
| _builder.append("this."); |
| String _simpleName = field.getSimpleName(); |
| _builder.append(_simpleName); |
| _builder.append(" = "); |
| TypeReference _preconditionsUtil = JsonRpcDataProcessor.this.getPreconditionsUtil(impl, context); |
| _builder.append(_preconditionsUtil); |
| _builder.append(".checkNotNull("); |
| String _simpleName_1 = parameter.getSimpleName(); |
| _builder.append(_simpleName_1); |
| _builder.append(", \""); |
| String _simpleName_2 = field.getSimpleName(); |
| _builder.append(_simpleName_2); |
| _builder.append("\");"); |
| _builder.newLineIfNotEmpty(); |
| } |
| }; |
| it.setBody(_client); |
| } |
| if ((deprecated != null)) { |
| it.addAnnotation(context.newAnnotationReference(Deprecated.class)); |
| } |
| }; |
| ObjectExtensions.<MutableMethodDeclaration>operator_doubleArrow(_findDeclaredMethod_1, _function_3); |
| final Collection<EitherTypeArgument> childTypes = context.getChildTypes(field.getType()); |
| boolean _isEmpty = childTypes.isEmpty(); |
| boolean _not_1 = (!_isEmpty); |
| if (_not_1) { |
| final Function1<EitherTypeArgument, JsonType> _function_4 = (EitherTypeArgument it) -> { |
| return context.getJsonType(it.getType()); |
| }; |
| final List<JsonType> jsonTypes = IterableExtensions.<JsonType>toList(IterableExtensions.<EitherTypeArgument, JsonType>map(childTypes, _function_4)); |
| int _size = jsonTypes.size(); |
| int _size_1 = IterableExtensions.<JsonType>toSet(jsonTypes).size(); |
| boolean _tripleNotEquals = (_size != _size_1); |
| if (_tripleNotEquals) { |
| if ((!hasJsonAdapter)) { |
| StringConcatenation _builder = new StringConcatenation(); |
| _builder.append("The json types of an Either must be distinct."); |
| context.addWarning(field, _builder.toString()); |
| } |
| } else { |
| for (final EitherTypeArgument childType : childTypes) { |
| this.addEitherSetter(field, setterName, childType, context); |
| } |
| } |
| } |
| } |
| }; |
| IterableExtensions.filter(impl.getDeclaredFields(), _function).forEach(_function_1); |
| } |
| |
| protected void addEitherSetter(final MutableFieldDeclaration field, final String setterName, final EitherTypeArgument argument, @Extension final JsonRpcDataTransformationContext context) { |
| final Procedure1<MutableMethodDeclaration> _function = (MutableMethodDeclaration method) -> { |
| context.setPrimarySourceElement(method, context.getPrimarySourceElement(field)); |
| method.addParameter(field.getSimpleName(), argument.getType()); |
| method.setStatic(field.isStatic()); |
| method.setVisibility(Visibility.PUBLIC); |
| method.setReturnType(context.getPrimitiveVoid()); |
| final CompilationStrategy _function_1 = (CompilationStrategy.CompilationContext ctx) -> { |
| return this.compileEitherSetterBody(field, argument, field.getSimpleName(), ctx, context); |
| }; |
| method.setBody(_function_1); |
| }; |
| field.getDeclaringType().addMethod(setterName, _function); |
| } |
| |
| protected CharSequence compileEitherSetterBody(final MutableFieldDeclaration field, final EitherTypeArgument argument, final String variableName, @Extension final CompilationStrategy.CompilationContext compilationContext, @Extension final JsonRpcDataTransformationContext context) { |
| CharSequence _xblockexpression = null; |
| { |
| AnnotationReference _findAnnotation = field.findAnnotation(context.newTypeReference(NonNull.class).getType()); |
| final boolean hasNonNull = (_findAnnotation != null); |
| final String newVariableName = ("_" + variableName); |
| StringConcatenation _builder = new StringConcatenation(); |
| String _javaCode = compilationContext.toJavaCode(context.getEitherType()); |
| _builder.append(_javaCode); |
| _builder.append(".for"); |
| { |
| boolean _isRight = argument.isRight(); |
| if (_isRight) { |
| _builder.append("Right"); |
| } else { |
| _builder.append("Left"); |
| } |
| } |
| _builder.append("("); |
| _builder.append(variableName); |
| _builder.append(")"); |
| final CharSequence compileNewEither = _builder; |
| StringConcatenation _builder_1 = new StringConcatenation(); |
| _builder_1.append("if ("); |
| _builder_1.append(variableName); |
| _builder_1.append(" == null) {"); |
| _builder_1.newLineIfNotEmpty(); |
| { |
| if (hasNonNull) { |
| _builder_1.append(" "); |
| TypeReference _preconditionsUtil = this.getPreconditionsUtil(field.getDeclaringType(), context); |
| _builder_1.append(_preconditionsUtil, " "); |
| _builder_1.append(".checkNotNull("); |
| _builder_1.append(variableName, " "); |
| _builder_1.append(", \""); |
| String _simpleName = field.getSimpleName(); |
| _builder_1.append(_simpleName, " "); |
| _builder_1.append("\");"); |
| _builder_1.newLineIfNotEmpty(); |
| } |
| } |
| _builder_1.append(" "); |
| _builder_1.append("this."); |
| String _simpleName_1 = field.getSimpleName(); |
| _builder_1.append(_simpleName_1, " "); |
| _builder_1.append(" = null;"); |
| _builder_1.newLineIfNotEmpty(); |
| _builder_1.append(" "); |
| _builder_1.append("return;"); |
| _builder_1.newLine(); |
| _builder_1.append("}"); |
| _builder_1.newLine(); |
| { |
| EitherTypeArgument _parent = argument.getParent(); |
| boolean _tripleNotEquals = (_parent != null); |
| if (_tripleNotEquals) { |
| _builder_1.append("final "); |
| String _javaCode_1 = compilationContext.toJavaCode(argument.getParent().getType()); |
| _builder_1.append(_javaCode_1); |
| _builder_1.append(" "); |
| _builder_1.append(newVariableName); |
| _builder_1.append(" = "); |
| _builder_1.append(compileNewEither); |
| _builder_1.append(";"); |
| _builder_1.newLineIfNotEmpty(); |
| CharSequence _compileEitherSetterBody = this.compileEitherSetterBody(field, argument.getParent(), newVariableName, compilationContext, context); |
| _builder_1.append(_compileEitherSetterBody); |
| _builder_1.newLineIfNotEmpty(); |
| } else { |
| _builder_1.append("this."); |
| String _simpleName_2 = field.getSimpleName(); |
| _builder_1.append(_simpleName_2); |
| _builder_1.append(" = "); |
| _builder_1.append(compileNewEither); |
| _builder_1.append(";"); |
| _builder_1.newLineIfNotEmpty(); |
| } |
| } |
| _xblockexpression = _builder_1; |
| } |
| return _xblockexpression; |
| } |
| |
| protected MutableMethodDeclaration generateToString(final MutableClassDeclaration impl, @Extension final TransformationContext context) { |
| MutableMethodDeclaration _xblockexpression = null; |
| { |
| final ArrayList<FieldDeclaration> toStringFields = CollectionLiterals.<FieldDeclaration>newArrayList(); |
| ClassDeclaration c = impl; |
| do { |
| { |
| Iterable<? extends FieldDeclaration> _declaredFields = c.getDeclaredFields(); |
| Iterables.<FieldDeclaration>addAll(toStringFields, _declaredFields); |
| TypeReference _extendedClass = c.getExtendedClass(); |
| Type _type = null; |
| if (_extendedClass!=null) { |
| _type=_extendedClass.getType(); |
| } |
| c = ((ClassDeclaration) _type); |
| } |
| } while(((c != null) && (!Objects.equal(c, context.getObject())))); |
| final Procedure1<MutableMethodDeclaration> _function = (MutableMethodDeclaration it) -> { |
| it.setReturnType(context.getString()); |
| it.addAnnotation(context.newAnnotationReference(Override.class)); |
| it.addAnnotation(context.newAnnotationReference(Pure.class)); |
| final AccessorsProcessor.Util accessorsUtil = new AccessorsProcessor.Util(context); |
| StringConcatenationClient _client = new StringConcatenationClient() { |
| @Override |
| protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) { |
| _builder.append(ToStringBuilder.class); |
| _builder.append(" b = new "); |
| _builder.append(ToStringBuilder.class); |
| _builder.append("(this);"); |
| _builder.newLineIfNotEmpty(); |
| { |
| for(final FieldDeclaration field : toStringFields) { |
| _builder.append("b.add(\""); |
| String _simpleName = field.getSimpleName(); |
| _builder.append(_simpleName); |
| _builder.append("\", "); |
| { |
| TypeDeclaration _declaringType = field.getDeclaringType(); |
| boolean _equals = Objects.equal(_declaringType, impl); |
| if (_equals) { |
| _builder.append("this."); |
| String _simpleName_1 = field.getSimpleName(); |
| _builder.append(_simpleName_1); |
| } else { |
| String _getterName = accessorsUtil.getGetterName(field); |
| _builder.append(_getterName); |
| _builder.append("()"); |
| } |
| } |
| _builder.append(");"); |
| _builder.newLineIfNotEmpty(); |
| } |
| } |
| _builder.append("return b.toString();"); |
| _builder.newLine(); |
| } |
| }; |
| it.setBody(_client); |
| }; |
| _xblockexpression = impl.addMethod("toString", _function); |
| } |
| return _xblockexpression; |
| } |
| |
| private TypeReference getPreconditionsUtil(final Type type, @Extension final TransformationContext context) { |
| TypeReference _xifexpression = null; |
| boolean _startsWith = type.getQualifiedName().startsWith("org.eclipse.lsp4j.debug"); |
| if (_startsWith) { |
| _xifexpression = context.newTypeReference("org.eclipse.lsp4j.debug.util.Preconditions"); |
| } else { |
| _xifexpression = context.newTypeReference("org.eclipse.lsp4j.util.Preconditions"); |
| } |
| return _xifexpression; |
| } |
| } |