/** * generated by Xtext */ package org.example.smalljava.validation; import com.google.common.base.Objects; import com.google.common.collect.Iterables; import com.google.inject.Inject; import java.util.ArrayList; import java.util.List; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.xtend2.lib.StringConcatenation; import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.naming.IQualifiedNameProvider; import org.eclipse.xtext.naming.QualifiedName; import org.eclipse.xtext.resource.IEObjectDescription; import org.eclipse.xtext.validation.Check; import org.eclipse.xtext.validation.CheckType; 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.ListExtensions; import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; import org.example.smalljava.scoping.SmallJavaIndex; import org.example.smalljava.smallJava.SJAccessLevel; import org.example.smalljava.smallJava.SJBlock; import org.example.smalljava.smallJava.SJClass; import org.example.smalljava.smallJava.SJExpression; import org.example.smalljava.smallJava.SJField; import org.example.smalljava.smallJava.SJMember; import org.example.smalljava.smallJava.SJMemberSelection; import org.example.smalljava.smallJava.SJMethod; import org.example.smalljava.smallJava.SJMethodBody; import org.example.smalljava.smallJava.SJParameter; import org.example.smalljava.smallJava.SJProgram; import org.example.smalljava.smallJava.SJReturn; import org.example.smalljava.smallJava.SJStatement; import org.example.smalljava.smallJava.SJSuper; import org.example.smalljava.smallJava.SJVariableDeclaration; import org.example.smalljava.smallJava.SmallJavaPackage; import org.example.smalljava.typing.SmallJavaTypeConformance; import org.example.smalljava.typing.SmallJavaTypeProvider; import org.example.smalljava.util.SmallJavaModelUtil; import org.example.smalljava.validation.AbstractSmallJavaValidator; import org.example.smalljava.validation.SmallJavaAccessibility; /** * Custom validation rules. * * see http://www.eclipse.org/Xtext/documentation.html#validation */ @SuppressWarnings("all") public class SmallJavaValidator extends AbstractSmallJavaValidator { @Inject @Extension private SmallJavaIndex _smallJavaIndex; @Inject @Extension private SmallJavaTypeProvider _smallJavaTypeProvider; @Inject @Extension private SmallJavaTypeConformance _smallJavaTypeConformance; @Inject @Extension private SmallJavaAccessibility _smallJavaAccessibility; @Inject @Extension private IQualifiedNameProvider _iQualifiedNameProvider; public final static String HIERARCHY_CYCLE = "org.example.smalljava.HierarchyCycle"; public final static String DUPLICATE_CLASS = "org.example.smalljava.DuplicateClass"; public final static String MEMBER_NOT_ACCESSIBLE = "org.example.smalljava.MemberNotAccessible"; public final static String METHOD_INVOCATION_ON_FIELD = "org.example.smalljava.MethodInvocationOnField"; public final static String FIELD_SELECTION_ON_METHOD = "org.example.smalljava.FieldSelectionOnMethod"; public final static String INCOMPATIBLE_TYPES = "org.example.smalljava.IncompatibleTypes"; public final static String DUPLICATE_ELEMENT = "org.example.smalljava.DuplicateElement"; public final static String UNREACHABLE_CODE = "org.example.smalljava.UnreachableCode"; public final static String MISSING_FINAL_RETURN = "org.example.smalljava.MissingFinalReturn"; public final static String INVALID_ARGS = "org.example.smalljava.InvalidArgs"; public final static String WRONG_METHOD_OVERRIDE = "org.example.smalljava.WrongMethodOverride"; public final static String WRONG_SUPER_USAGE = "org.example.smalljava.WrongSuperUsage"; @Check public void checkClassHierarchy(final SJClass c) { ArrayList<SJClass> _classHierarchy = SmallJavaModelUtil.classHierarchy(c); boolean _contains = _classHierarchy.contains(c); if (_contains) { String _name = c.getName(); String _plus = ("cycle in hierarchy of class \'" + _name); String _plus_1 = (_plus + "\'"); EReference _sJClass_Superclass = SmallJavaPackage.eINSTANCE.getSJClass_Superclass(); SJClass _superclass = c.getSuperclass(); String _name_1 = _superclass.getName(); this.error(_plus_1, _sJClass_Superclass, SmallJavaValidator.HIERARCHY_CYCLE, _name_1); } } @Check(CheckType.NORMAL) public void checkDuplicateClassesInFiles(final SJClass c) { final QualifiedName className = this._iQualifiedNameProvider.getFullyQualifiedName(c); Iterable<IEObjectDescription> _visibleClassesDescriptions = this._smallJavaIndex.getVisibleClassesDescriptions(c); final Procedure1<IEObjectDescription> _function = new Procedure1<IEObjectDescription>() { @Override public void apply(final IEObjectDescription desc) { boolean _and = false; boolean _and_1 = false; QualifiedName _qualifiedName = desc.getQualifiedName(); boolean _equals = Objects.equal(_qualifiedName, className); if (!_equals) { _and_1 = false; } else { EObject _eObjectOrProxy = desc.getEObjectOrProxy(); boolean _notEquals = (!Objects.equal(_eObjectOrProxy, c)); _and_1 = _notEquals; } if (!_and_1) { _and = false; } else { URI _eObjectURI = desc.getEObjectURI(); URI _trimFragment = _eObjectURI.trimFragment(); Resource _eResource = c.eResource(); URI _uRI = _eResource.getURI(); boolean _notEquals_1 = (!Objects.equal(_trimFragment, _uRI)); _and = _notEquals_1; } if (_and) { String _name = c.getName(); String _plus = ("The type " + _name); String _plus_1 = (_plus + " is already defined"); EAttribute _sJClass_Name = SmallJavaPackage.eINSTANCE.getSJClass_Name(); SmallJavaValidator.this.error(_plus_1, _sJClass_Name, SmallJavaValidator.DUPLICATE_CLASS); return; } } }; IterableExtensions.<IEObjectDescription>forEach(_visibleClassesDescriptions, _function); } @Check public void checkAccessibility(final SJMemberSelection sel) { final SJMember member = sel.getMember(); boolean _and = false; boolean _and_1 = false; boolean _notEquals = (!Objects.equal(member, null)); if (!_notEquals) { _and_1 = false; } else { boolean _isAccessibleFrom = this._smallJavaAccessibility.isAccessibleFrom(member, sel); boolean _not = (!_isAccessibleFrom); _and_1 = _not; } if (!_and_1) { _and = false; } else { String _name = member.getName(); boolean _notEquals_1 = (!Objects.equal(_name, null)); _and = _notEquals_1; } if (_and) { StringConcatenation _builder = new StringConcatenation(); _builder.append("The "); SJAccessLevel _access = member.getAccess(); _builder.append(_access, ""); _builder.append(" member "); String _name_1 = member.getName(); _builder.append(_name_1, ""); _builder.append(" is not accessible here"); EReference _sJMemberSelection_Member = SmallJavaPackage.eINSTANCE.getSJMemberSelection_Member(); this.error(_builder.toString(), _sJMemberSelection_Member, SmallJavaValidator.MEMBER_NOT_ACCESSIBLE); } } @Check public void checkMemberSelection(final SJMemberSelection sel) { final SJMember member = sel.getMember(); boolean _notEquals = (!Objects.equal(member, null)); if (_notEquals) { boolean _and = false; if (!(member instanceof SJField)) { _and = false; } else { boolean _isMethodinvocation = sel.isMethodinvocation(); _and = _isMethodinvocation; } if (_and) { StringConcatenation _builder = new StringConcatenation(); _builder.append("Method invocation on a field"); EAttribute _sJMemberSelection_Methodinvocation = SmallJavaPackage.eINSTANCE.getSJMemberSelection_Methodinvocation(); this.error(_builder.toString(), _sJMemberSelection_Methodinvocation, SmallJavaValidator.METHOD_INVOCATION_ON_FIELD); } boolean _and_1 = false; if (!(member instanceof SJMethod)) { _and_1 = false; } else { boolean _isMethodinvocation_1 = sel.isMethodinvocation(); boolean _not = (!_isMethodinvocation_1); _and_1 = _not; } if (_and_1) { StringConcatenation _builder_1 = new StringConcatenation(); _builder_1.append("Field selection on a method"); EReference _sJMemberSelection_Member = SmallJavaPackage.eINSTANCE.getSJMemberSelection_Member(); this.error(_builder_1.toString(), _sJMemberSelection_Member, SmallJavaValidator.FIELD_SELECTION_ON_METHOD); } } } @Check public void checkCompatibleTypes(final SJExpression exp) { final SJClass actualType = this._smallJavaTypeProvider.typeFor(exp); final SJClass expectedType = this._smallJavaTypeProvider.expectedType(exp); boolean _or = false; boolean _equals = Objects.equal(expectedType, null); if (_equals) { _or = true; } else { boolean _equals_1 = Objects.equal(actualType, null); _or = _equals_1; } if (_or) { return; } boolean _isConformant = this._smallJavaTypeConformance.isConformant(actualType, expectedType); boolean _not = (!_isConformant); if (_not) { String _name = null; if (expectedType!=null) { _name=expectedType.getName(); } String _plus = ("Incompatible types. Expected \'" + _name); String _plus_1 = (_plus + "\' but was \'"); String _name_1 = null; if (actualType!=null) { _name_1=actualType.getName(); } String _plus_2 = (_plus_1 + _name_1); String _plus_3 = (_plus_2 + "\'"); this.error(_plus_3, null, SmallJavaValidator.INCOMPATIBLE_TYPES); } } @Check public void checkMethodInvocationArguments(final SJMemberSelection sel) { boolean _and = false; SJMember _member = sel.getMember(); boolean _notEquals = (!Objects.equal(_member, null)); if (!_notEquals) { _and = false; } else { SJMember _member_1 = sel.getMember(); _and = (_member_1 instanceof SJMethod); } if (_and) { SJMember _member_2 = sel.getMember(); final SJMethod method = ((SJMethod) _member_2); EList<SJParameter> _params = method.getParams(); int _size = _params.size(); EList<SJExpression> _args = sel.getArgs(); int _size_1 = _args.size(); boolean _notEquals_1 = (_size != _size_1); if (_notEquals_1) { String _memberAsStringWithType = SmallJavaModelUtil.memberAsStringWithType(method); String _plus = ("Invalid number of arguments. The method " + _memberAsStringWithType); String _plus_1 = (_plus + " is not applicable for the arguments "); String _argsTypesAsStrings = this._smallJavaTypeProvider.argsTypesAsStrings(sel); String _plus_2 = (_plus_1 + _argsTypesAsStrings); EReference _sJMemberSelection_Member = SmallJavaPackage.eINSTANCE.getSJMemberSelection_Member(); this.error(_plus_2, _sJMemberSelection_Member, SmallJavaValidator.INVALID_ARGS); } } } @Check public void checkNoDuplicateVariable(final SJVariableDeclaration vardecl) { SJMethod _containingMethod = SmallJavaModelUtil.containingMethod(vardecl); SJMethodBody _body = _containingMethod.getBody(); List<SJVariableDeclaration> _allContentsOfType = EcoreUtil2.<SJVariableDeclaration>getAllContentsOfType(_body, SJVariableDeclaration.class); final Function1<SJVariableDeclaration, Boolean> _function = new Function1<SJVariableDeclaration, Boolean>() { @Override public Boolean apply(final SJVariableDeclaration it) { boolean _and = false; boolean _notEquals = (!Objects.equal(it, vardecl)); if (!_notEquals) { _and = false; } else { String _name = it.getName(); String _name_1 = vardecl.getName(); boolean _equals = Objects.equal(_name, _name_1); _and = _equals; } return Boolean.valueOf(_and); } }; final SJVariableDeclaration duplicate = IterableExtensions.<SJVariableDeclaration>findFirst(_allContentsOfType, _function); boolean _notEquals = (!Objects.equal(duplicate, null)); if (_notEquals) { String _name = vardecl.getName(); String _plus = ("Duplicate variable declaration \'" + _name); String _plus_1 = (_plus + "\'"); EAttribute _sJSymbol_Name = SmallJavaPackage.eINSTANCE.getSJSymbol_Name(); this.error(_plus_1, _sJSymbol_Name, SmallJavaValidator.DUPLICATE_ELEMENT); } } @Check public void checkNoDuplicateMember(final SJMember member) { SJClass _containingClass = SmallJavaModelUtil.containingClass(member); EList<SJMember> _members = _containingClass.getMembers(); final Function1<SJMember, Boolean> _function = new Function1<SJMember, Boolean>() { @Override public Boolean apply(final SJMember it) { boolean _and = false; boolean _and_1 = false; boolean _notEquals = (!Objects.equal(it, member)); if (!_notEquals) { _and_1 = false; } else { EClass _eClass = it.eClass(); EClass _eClass_1 = member.eClass(); boolean _equals = Objects.equal(_eClass, _eClass_1); _and_1 = _equals; } if (!_and_1) { _and = false; } else { String _name = it.getName(); String _name_1 = member.getName(); boolean _equals_1 = Objects.equal(_name, _name_1); _and = _equals_1; } return Boolean.valueOf(_and); } }; final SJMember duplicate = IterableExtensions.<SJMember>findFirst(_members, _function); boolean _notEquals = (!Objects.equal(duplicate, null)); if (_notEquals) { String _name = member.getName(); String _plus = ("Duplicate member \'" + _name); String _plus_1 = (_plus + "\'"); EAttribute _sJMember_Name = SmallJavaPackage.eINSTANCE.getSJMember_Name(); this.error(_plus_1, _sJMember_Name, SmallJavaValidator.DUPLICATE_ELEMENT); } } @Check public void checkNoDuplicateClass(final SJClass c) { SJProgram _containingProgram = SmallJavaModelUtil.containingProgram(c); EList<SJClass> _classes = _containingProgram.getClasses(); final Function1<SJClass, Boolean> _function = new Function1<SJClass, Boolean>() { @Override public Boolean apply(final SJClass it) { boolean _and = false; boolean _notEquals = (!Objects.equal(it, c)); if (!_notEquals) { _and = false; } else { String _name = it.getName(); String _name_1 = c.getName(); boolean _equals = Objects.equal(_name, _name_1); _and = _equals; } return Boolean.valueOf(_and); } }; boolean _exists = IterableExtensions.<SJClass>exists(_classes, _function); if (_exists) { String _name = c.getName(); String _plus = ("Duplicate class \'" + _name); String _plus_1 = (_plus + "\'"); EAttribute _sJClass_Name = SmallJavaPackage.eINSTANCE.getSJClass_Name(); this.error(_plus_1, _sJClass_Name, SmallJavaValidator.DUPLICATE_ELEMENT); } } @Check public void checkNoStatementAfterReturn(final SJReturn ret) { SJBlock _containingBlock = SmallJavaModelUtil.containingBlock(ret); final EList<SJStatement> statements = _containingBlock.getStatements(); SJStatement _last = IterableExtensions.<SJStatement>last(statements); boolean _notEquals = (!Objects.equal(_last, ret)); if (_notEquals) { int _indexOf = statements.indexOf(ret); int _plus = (_indexOf + 1); SJStatement _get = statements.get(_plus); this.error("Unreachable code", _get, null, SmallJavaValidator.UNREACHABLE_CODE); } } @Check public void checkMethodEndsWithReturn(final SJMethod method) { SJReturn _returnStatement = SmallJavaModelUtil.returnStatement(method); boolean _equals = Objects.equal(_returnStatement, null); if (_equals) { EReference _sJMethod_Body = SmallJavaPackage.eINSTANCE.getSJMethod_Body(); this.error("Method must end with a return statement", _sJMethod_Body, SmallJavaValidator.MISSING_FINAL_RETURN); } } @Check public void checkMethodOverride(final SJMethod m) { SJClass _containingClass = SmallJavaModelUtil.containingClass(m); ArrayList<SJClass> _classHierarchy = SmallJavaModelUtil.classHierarchy(_containingClass); final Function1<SJClass, Iterable<SJMethod>> _function = new Function1<SJClass, Iterable<SJMethod>>() { @Override public Iterable<SJMethod> apply(final SJClass it) { return SmallJavaModelUtil.methods(it); } }; List<Iterable<SJMethod>> _map = ListExtensions.<SJClass, Iterable<SJMethod>>map(_classHierarchy, _function); Iterable<SJMethod> _flatten = Iterables.<SJMethod>concat(_map); final Function1<SJMethod, Boolean> _function_1 = new Function1<SJMethod, Boolean>() { @Override public Boolean apply(final SJMethod it) { String _name = it.getName(); String _name_1 = m.getName(); return Boolean.valueOf(Objects.equal(_name, _name_1)); } }; final SJMethod overridden = IterableExtensions.<SJMethod>findFirst(_flatten, _function_1); boolean _notEquals = (!Objects.equal(overridden, null)); if (_notEquals) { boolean _or = false; SJClass _type = m.getType(); SJClass _type_1 = overridden.getType(); boolean _isConformant = this._smallJavaTypeConformance.isConformant(_type, _type_1); boolean _not = (!_isConformant); if (_not) { _or = true; } else { EList<SJParameter> _params = m.getParams(); final Function1<SJParameter, SJClass> _function_2 = new Function1<SJParameter, SJClass>() { @Override public SJClass apply(final SJParameter it) { return it.getType(); } }; List<SJClass> _map_1 = ListExtensions.<SJParameter, SJClass>map(_params, _function_2); EList<SJParameter> _params_1 = overridden.getParams(); final Function1<SJParameter, SJClass> _function_3 = new Function1<SJParameter, SJClass>() { @Override public SJClass apply(final SJParameter it) { return it.getType(); } }; List<SJClass> _map_2 = ListExtensions.<SJParameter, SJClass>map(_params_1, _function_3); boolean _elementsEqual = IterableExtensions.elementsEqual(_map_1, _map_2); boolean _not_1 = (!_elementsEqual); _or = _not_1; } if (_or) { StringConcatenation _builder = new StringConcatenation(); _builder.append("The method \'"); String _name = m.getName(); _builder.append(_name, ""); _builder.append("\' must override a superclass method"); EReference _sJMember_Type = SmallJavaPackage.eINSTANCE.getSJMember_Type(); this.error(_builder.toString(), _sJMember_Type, SmallJavaValidator.WRONG_METHOD_OVERRIDE); } } } @Check public void checkSuper(final SJSuper s) { EStructuralFeature _eContainingFeature = s.eContainingFeature(); EReference _sJMemberSelection_Receiver = SmallJavaPackage.eINSTANCE.getSJMemberSelection_Receiver(); boolean _notEquals = (!Objects.equal(_eContainingFeature, _sJMemberSelection_Receiver)); if (_notEquals) { this.error("\'super\' can be used only as member selection receiver", null, SmallJavaValidator.WRONG_SUPER_USAGE); } } }