Skip to content

Commit

Permalink
fix 1341 - allow to annotate constructors types for core classes.
Browse files Browse the repository at this point in the history
Also we add a first version of constructor expectations (c.f. issue 1342)
  • Loading branch information
npasserini committed Mar 8, 2018
1 parent eb326ae commit 2cdf98c
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ abstract class AbstractWollokTypeSystemTestCase extends AbstractWollokParameteri

def assertConstructorType(EObject program, String className, String paramsSignature) {
val nrOfParams = paramsSignature.split(',').length;
assertEquals(paramsSignature,
"(" + findConstructor(className, nrOfParams).parameters.map[type?.name].join(", ") + ")")
assertEquals(paramsSignature, findConstructor(className, nrOfParams).constructorType(tsystem))

}

def assertMethodSignature(EObject program, String expectedSignature, String methodFQN) {
Expand Down Expand Up @@ -231,7 +231,7 @@ abstract class AbstractWollokTypeSystemTestCase extends AbstractWollokParameteri
}

def findConstructor(String className, int nrOfParams) {
WClass.find(className).constructors.findFirst[matches(nrOfParams)]
WClass.find(className).getOwnConstructor(nrOfParams)
}

def findMethod(String methodFQN) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.uqbar.project.wollok.tests.typesystem.AbstractWollokTypeSystemTestCas
import org.uqbar.project.wollok.tests.typesystem.WollokTypeSystemTestModule
import org.uqbar.project.wollok.typesystem.ConcreteType
import org.uqbar.project.wollok.typesystem.TypeSystem
import org.uqbar.project.wollok.wollokDsl.WConstructorCall
import org.uqbar.project.wollok.wollokDsl.WMemberFeatureCall
import org.uqbar.project.wollok.wollokDsl.WMethodDeclaration
import org.xpect.XpectImport
Expand All @@ -25,6 +26,7 @@ import org.xpect.xtext.lib.tests.ValidationTest
import org.xpect.xtext.lib.tests.ValidationTestModuleSetup.ConsumedIssues
import org.xpect.xtext.lib.util.XtextOffsetAdapter.IEStructuralFeatureAndEObject

import static extension org.uqbar.project.wollok.model.WollokModelExtensions.*
import static extension org.uqbar.project.wollok.typesystem.TypeSystemUtils.*
import static extension org.uqbar.project.wollok.typesystem.constraints.WollokModelPrintForDebug.*

Expand Down Expand Up @@ -65,6 +67,18 @@ class TypeSystemXpectTestCase extends AbstractWollokTypeSystemTestCase {
expectation.assertEquals(method.functionType(typeSystem))
}

@Xpect(liveExecution=LiveExecutionType.FAST)
@ParameterParser(syntax="'at' arg1=OFFSET")
@ConsumedIssues(#[Severity.INFO, Severity.ERROR, Severity.WARNING])
def void constructorType( //
@StringExpectation IStringExpectation expectation,
IEStructuralFeatureAndEObject target,
@ThisResource XtextResource resource,
@ThisModel EObject file
) {
println(target.EObject.constructor.constructorType(typeSystem))
}

def dispatch method(EObject object) {
throw new IllegalArgumentException(object.debugInfo)
}
Expand All @@ -77,5 +91,14 @@ class TypeSystemXpectTestCase extends AbstractWollokTypeSystemTestCase {
def dispatch method(WMethodDeclaration method) {
method
}

def dispatch constructor(EObject target) {
throw new IllegalArgumentException(target.debugInfo)
}

def dispatch constructor(WConstructorCall it) {
// TODO Tal vez acá uno quisiera contemplar la posibilidad de heredar constructores
classRef.getOwnConstructor(arguments.size)
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* XPECT_SETUP org.uqbar.project.wollok.tests.typesystem.xpect.TypeSystemXpectTestCase END_SETUP */

object constructorTests {
method m1() {
// XPECT constructorType at Date --> (Number, Number, Number)
return new Date(1, 2, 3)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.uqbar.project.wollok.typesystem

import java.util.List
import org.uqbar.project.wollok.wollokDsl.WClass
import org.uqbar.project.wollok.wollokDsl.WConstructor

import static org.uqbar.project.wollok.ui.utils.XTendUtilExtensions.*

Expand All @@ -18,6 +20,10 @@ class ClassBasedWollokType extends AbstractContainerWollokType {

def clazz() { container as WClass }

def WConstructor getConstructor(List<?> parameterTypes) {
clazz.getOwnConstructor(parameterTypes.size)
}

override acceptAssignment(WollokType other) {
val value = this == other ||
// hackeo por ahora. Esto no permite compatibilidad entre classes y structural types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,4 @@ interface ConcreteType extends WollokType {

def WMethodDeclaration lookupMethod(MessageType message)
def WMethodDeclaration lookupMethod(String selector, List<?> parameterTypes)

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.uqbar.project.wollok.typesystem

import org.uqbar.project.wollok.wollokDsl.WConstructor
import org.uqbar.project.wollok.wollokDsl.WMethodDeclaration

import static org.uqbar.project.wollok.sdk.WollokDSK.*
Expand All @@ -14,6 +15,10 @@ class TypeSystemUtils {
"(" + m.parameterTypes(ts).map[it?.name].join(", ") + ') => ' + m.type?.name
}

def static constructorType(WConstructor it, extension TypeSystem ts) {
"(" + parameters.map[type?.name].join(", ") + ")"
}

def static parameterTypes(WMethodDeclaration m, extension TypeSystem ts) {
m.parameters.map[it.type]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ class ClosureTypeAnnotation implements TypeAnnotation {
this.returnType = returnType
}

}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package org.uqbar.project.wollok.typesystem.annotations

import org.uqbar.project.wollok.typesystem.ClassBasedWollokType
import org.uqbar.project.wollok.typesystem.ConcreteType
import org.uqbar.project.wollok.typesystem.annotations.TypeAnnotation

interface TypeDeclarationTarget {
// TODO Is it ok to receive strings or should be have smarter types?
def void addTypeDeclaration(ConcreteType receiver, String selector, TypeAnnotation[] parameterTypes, TypeAnnotation returnType)
def void addMethodTypeDeclaration(ConcreteType receiver, String selector, TypeAnnotation[] parameterTypes, TypeAnnotation returnType)

def void addConstructorTypeDeclaration(ClassBasedWollokType receiver, TypeAnnotation[] parameterTypes)

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.uqbar.project.wollok.typesystem.annotations
import java.util.List
import org.eclipse.emf.ecore.EObject
import org.eclipse.xtend.lib.annotations.Accessors
import org.uqbar.project.wollok.typesystem.ClassBasedWollokType
import org.uqbar.project.wollok.typesystem.ConcreteType
import org.uqbar.project.wollok.typesystem.TypeProvider
import org.uqbar.project.wollok.typesystem.WollokType
Expand Down Expand Up @@ -37,6 +38,10 @@ abstract class TypeDeclarations {
def operator_doubleArrow(List<? extends TypeAnnotation> parameterTypes, TypeAnnotation returnType) {
new MethodTypeDeclaration(parameterTypes, returnType)
}

def constructor(SimpleTypeAnnotation<? extends ClassBasedWollokType> owner, TypeAnnotation... parameterTypes) {
target.addConstructorTypeDeclaration(owner.type, parameterTypes)
}

// ****************************************************************************
// ** Synthetic operator syntax
Expand Down Expand Up @@ -156,7 +161,7 @@ class ExpectReturnType {
}

def operator_doubleArrow(TypeAnnotation returnType) {
target.addTypeDeclaration(receiver, selector, parameterTypes, returnType)
target.addMethodTypeDeclaration(receiver, selector, parameterTypes, returnType)
}
}

Expand All @@ -172,7 +177,7 @@ class MethodIdentifier {
}

def operator_tripleEquals(MethodTypeDeclaration methodType) {
target.addTypeDeclaration(receiver, selector, methodType.parameterTypes, methodType.returnType)
target.addMethodTypeDeclaration(receiver, selector, methodType.parameterTypes, methodType.returnType)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class WollokCoreTypeDeclarations extends TypeDeclarations {
Set >> "contains" === #[ELEMENT] => Boolean
Set >> "sum" === #[closure(#[ELEMENT], Number)] => Number;

Date.constructor(Number, Number, Number)
(Date == Date) => Boolean
Date - Date => Number
Date >> "initialize" === #[Number, Number, Number] => Void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.uqbar.project.wollok.typesystem.constraints.variables.ITypeVariable
import org.uqbar.project.wollok.typesystem.constraints.variables.TypeVariablesRegistry

import static extension org.uqbar.project.wollok.utils.XtendExtensions.biForEach
import org.uqbar.project.wollok.typesystem.ClassBasedWollokType

class AnnotatedTypeRegistry implements TypeDeclarationTarget {
TypeVariablesRegistry registry
Expand All @@ -22,11 +23,16 @@ class AnnotatedTypeRegistry implements TypeDeclarationTarget {
this.context = context
}

override addTypeDeclaration(ConcreteType receiver, String selector, TypeAnnotation[] paramTypes, TypeAnnotation returnType) {
override addMethodTypeDeclaration(ConcreteType receiver, String selector, TypeAnnotation[] paramTypes, TypeAnnotation returnType) {
val method = receiver.lookupMethod(selector, paramTypes)
method.parameters.biForEach(paramTypes)[parameter, type|parameter.beSealed(type)]
method.beSealed(returnType)
}

override addConstructorTypeDeclaration(ClassBasedWollokType receiver, TypeAnnotation[] paramTypes) {
var constructor = receiver.getConstructor(paramTypes)
constructor.parameters.biForEach(paramTypes)[parameter, type|parameter.beSealed(type)]
}

def dispatch ITypeVariable beSealed(EObject object, SimpleTypeAnnotation<?> annotation) {
registry.newSealed(object, annotation.type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,6 @@ class WollokModelExtensions {
matches(call.feature, call.memberCallArguments)
}

def static constructor(WConstructorCall c) {
c.classRef.constructors.findFirst [ const | const.parameters.size.equals(c.arguments.size) ]
}

def static isValidConstructorCall(WConstructorCall c) {
c.classRef.hasConstructorForArgs(c.numberOfParameters)
}
Expand Down Expand Up @@ -337,6 +333,15 @@ class WollokModelExtensions {
c.parent.allConstructors
}

/**
* Look for a constructor matching the number of parameters,
* but only among the constructors written in the class itself.
* Ignore constructor inheritance.
*/
def static getOwnConstructor(WClass clazz, int nrOfParams) {
clazz.constructors.findFirst[matches(nrOfParams)]
}

def static dispatch getConstructors(EObject o) { newArrayList }
def static dispatch getConstructors(WClass c) { c.allConstructors }

Expand Down

0 comments on commit 2cdf98c

Please sign in to comment.