/* * Copyright Red Hat Inc. and/or its affiliates and other contributors * as indicated by the authors tag. All rights reserved. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU General Public License version 2. * * This particular file is subject to the "Classpath" exception as provided in the * LICENSE file that accompanied this code. * * This program is distributed in the hope that it will be useful, but WITHOUT A * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more details. * You should have received a copy of the GNU General Public License, * along with this distribution; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ package com.redhat.ceylon.compiler.java.test.model; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import com.redhat.ceylon.cmr.api.RepositoryManager; import com.redhat.ceylon.cmr.ceylon.CeylonUtils; import com.redhat.ceylon.common.Backend; import com.redhat.ceylon.common.Versions; import com.redhat.ceylon.compiler.java.codegen.CeylonTransformer; import com.redhat.ceylon.compiler.java.codegen.ClassTransformer; import com.redhat.ceylon.compiler.java.codegen.Decl; import com.redhat.ceylon.compiler.java.codegen.ExpressionTransformer; import com.redhat.ceylon.compiler.java.codegen.StatementTransformer; import com.redhat.ceylon.compiler.java.loader.CeylonEnter; import com.redhat.ceylon.compiler.java.loader.CeylonModelLoader; import com.redhat.ceylon.compiler.java.runtime.metamodel.Metamodel; import com.redhat.ceylon.compiler.java.runtime.model.RuntimeModelLoader; import com.redhat.ceylon.compiler.java.runtime.model.RuntimeModuleManager; import com.redhat.ceylon.compiler.java.test.CompilerError; import com.redhat.ceylon.compiler.java.test.CompilerTests; import com.redhat.ceylon.compiler.java.tools.CeyloncTaskImpl; import com.redhat.ceylon.compiler.java.tools.LanguageCompiler; import com.redhat.ceylon.compiler.typechecker.TypeChecker; import com.redhat.ceylon.compiler.typechecker.TypeCheckerBuilder; import com.redhat.ceylon.compiler.typechecker.context.PhasedUnit; import com.redhat.ceylon.compiler.typechecker.context.PhasedUnits; import com.redhat.ceylon.compiler.typechecker.io.ClosableVirtualFile; import com.redhat.ceylon.compiler.typechecker.io.VFS; import com.redhat.ceylon.model.cmr.JDKUtils; import com.redhat.ceylon.model.loader.AbstractModelLoader; import com.redhat.ceylon.model.loader.ModelLoader; import com.redhat.ceylon.model.loader.ModelLoader.DeclarationType; import com.redhat.ceylon.model.loader.impl.reflect.mirror.ReflectionUtils; import com.redhat.ceylon.model.loader.model.LazyElement; import com.redhat.ceylon.model.typechecker.model.Annotation; import com.redhat.ceylon.model.typechecker.model.Class; import com.redhat.ceylon.model.typechecker.model.ClassOrInterface; import com.redhat.ceylon.model.typechecker.model.Constructor; import com.redhat.ceylon.model.typechecker.model.Declaration; import com.redhat.ceylon.model.typechecker.model.Function; import com.redhat.ceylon.model.typechecker.model.FunctionOrValue; import com.redhat.ceylon.model.typechecker.model.Interface; import com.redhat.ceylon.model.typechecker.model.ModelUtil; import com.redhat.ceylon.model.typechecker.model.Module; import com.redhat.ceylon.model.typechecker.model.Modules; import com.redhat.ceylon.model.typechecker.model.Package; import com.redhat.ceylon.model.typechecker.model.Parameter; import com.redhat.ceylon.model.typechecker.model.ParameterList; import com.redhat.ceylon.model.typechecker.model.Scope; import com.redhat.ceylon.model.typechecker.model.Setter; import com.redhat.ceylon.model.typechecker.model.Type; import com.redhat.ceylon.model.typechecker.model.TypeDeclaration; import com.redhat.ceylon.model.typechecker.model.TypeParameter; import com.redhat.ceylon.model.typechecker.model.Value; import com.sun.source.util.TaskEvent; import com.sun.source.util.TaskEvent.Kind; import com.sun.source.util.TaskListener; import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.util.Context; @RunWith(Parameterized.class) public class ModelLoaderTests extends CompilerTests { @Parameters public static Iterable<Object[]> testParameters() { return Arrays.asList(new Object[]{true}, new Object[]{false}); } private final boolean simpleAnnotationModels; public ModelLoaderTests(boolean simpleAnnotationModels) { this.simpleAnnotationModels = simpleAnnotationModels; } protected static String getQualifiedPrefixedName(Declaration decl){ String name = Decl.className(decl); String prefix; if(decl instanceof ClassOrInterface) prefix = "C"; else if(Decl.isValue(decl)) prefix = "V"; else if(Decl.isGetter(decl)) prefix = "G"; else if(decl instanceof Setter) prefix = "S"; else if(decl instanceof Function) prefix = "M"; else throw new RuntimeException("Don't know how to prefix decl: "+decl); return prefix + name; } protected void verifyCompilerClassLoading(String ceylon) { verifyCompilerClassLoading(ceylon, new ModelComparison()); } protected void verifyCompilerClassLoading(String ceylon, final ModelComparison modelCompare){ // now compile the ceylon decl file CeyloncTaskImpl task = getCompilerTask(ceylon); // get the context to grab the phased units Context context = task.getContext(); if (simpleAnnotationModels) { CeylonEnter.instance(context); ExpressionTransformer.getInstance(context).simpleAnnotationModels = true; CeylonTransformer.getInstance(context).simpleAnnotationModels = true; StatementTransformer.getInstance(context).simpleAnnotationModels = true; ClassTransformer.getInstance(context).simpleAnnotationModels = true; } Boolean success = task.call(); Assert.assertTrue(success); PhasedUnits phasedUnits = LanguageCompiler.getPhasedUnitsInstance(context); // find out what was in that file Assert.assertEquals(2, phasedUnits.getPhasedUnits().size()); PhasedUnit one = phasedUnits.getPhasedUnits().get(0); PhasedUnit two = phasedUnits.getPhasedUnits().get(1); PhasedUnit phasedUnit = one.getUnitFile().getName().endsWith("module.ceylon") ? two : one; final Map<String,Declaration> decls = new HashMap<String,Declaration>(); for(Declaration decl : phasedUnit.getUnit().getDeclarations()){ if(decl.isToplevel()){ decls.put(getQualifiedPrefixedName(decl), decl); } } // now compile the ceylon usage file // remove the extension, make lowercase and add "test" String testfile = ceylon.substring(0, ceylon.length()-7).toLowerCase()+"test.ceylon"; JavacTaskImpl task2 = getCompilerTask(testfile); // get the context to grab the declarations final Context context2 = task2.getContext(); // check the declarations after Enter but before the compilation is done otherwise we can't load lazy // declarations from the jar anymore because we've overridden the jar and the javac jar index is corrupted class Listener implements TaskListener{ @Override public void started(TaskEvent e) { } @Override public void finished(TaskEvent e) { if(e.getKind() == Kind.ENTER){ AbstractModelLoader modelLoader = CeylonModelLoader.instance(context2); Modules modules = LanguageCompiler.getCeylonContextInstance(context2).getModules(); // now see if we can find our declarations compareDeclarations(modelCompare, decls, modelLoader, modules); } } } Listener listener = new Listener(); task2.setTaskListener(listener); success = task2.call(); Assert.assertTrue("Compilation failed", success); // now check with the runtime model loader too String module = moduleForJavaModelLoading(); String version = "1"; ModuleWithArtifact moduleWithArtifact = new ModuleWithArtifact(module, version); synchronized(RUN_LOCK){ // this initialises the metamodel, even if we don't use the resulting ClassLoader URLClassLoader classLoader; try { classLoader = getClassLoader("runtime model loader tests", moduleWithArtifact); } catch (MalformedURLException e) { throw new RuntimeException(e); } try{ RuntimeModuleManager moduleManager = Metamodel.getModuleManager(); RuntimeModelLoader modelLoader = moduleManager.getModelLoader(); Modules modules = moduleManager.getModules(); // now see if we can find our declarations compareDeclarations(modelCompare, decls, modelLoader, modules); }finally{ try { classLoader.close(); } catch (IOException e) { // ignore e.printStackTrace(); } } } } private void compareDeclarations(final ModelComparison modelCompare, final Map<String, Declaration> decls, AbstractModelLoader modelLoader, Modules modules) { Module testModule = getTestModule(modules); for(Entry<String, Declaration> entry : decls.entrySet()){ String quotedQualifiedName = entry.getKey().substring(1); Declaration modelDeclaration = modelLoader.getDeclaration(testModule, quotedQualifiedName, Decl.isValue(entry.getValue()) ? DeclarationType.VALUE : DeclarationType.TYPE); Assert.assertNotNull(modelDeclaration); // make sure we loaded them exactly the same modelCompare.compareDeclarations(entry.getValue().getQualifiedNameString(), entry.getValue(), modelDeclaration); } } private Module getTestModule(Modules modules) { for(Module mod : modules.getListOfModules()){ if(mod.getNameAsString().equals(moduleForJavaModelLoading())) return mod; } Assert.fail("Could not find module "+moduleForJavaModelLoading()); return null; } protected void verifyCompilerClassLoading(String ceylon, final RunnableTest test){ verifyCompilerClassLoading(ceylon, test, defaultOptions); } protected void verifyCompilerClassLoading(String ceylon, final RunnableTest test, List<String> options){ // now compile the ceylon usage file JavacTaskImpl task2 = getCompilerTask(options, ceylon); // get the context to grab the declarations final Context context2 = task2.getContext(); // check the declarations after Enter but before the compilation is done otherwise we can'tload lazy // declarations from the jar anymore because we've overridden the jar and the javac jar index is corrupted class Listener implements TaskListener{ @Override public void started(TaskEvent e) { } @Override public void finished(TaskEvent e) { if(e.getKind() == Kind.ENTER){ CeylonModelLoader modelLoader = (CeylonModelLoader) CeylonModelLoader.instance(context2); test.test(modelLoader); } } } Listener listener = new Listener(); task2.setTaskListener(listener); try{ Boolean success = task2.call(); Assert.assertTrue("Compilation failed", success); }catch(AssertionError x){ throw x; }catch(Throwable x){ // make sure we unwrap it while(x.getCause() != null) x = x.getCause(); if(x instanceof Error) throw (Error)x; if(x instanceof RuntimeException) throw (RuntimeException)x; throw new RuntimeException(x); } } protected void verifyRuntimeClassLoading(RunnableTest test) { RepositoryManager repoManager = CeylonUtils.repoManager() .buildManager(); VFS vfs = new VFS(); com.redhat.ceylon.compiler.typechecker.context.Context context = new com.redhat.ceylon.compiler.typechecker.context.Context(repoManager, vfs); RuntimeModuleManager moduleManager = new RuntimeModuleManager(); context.setModules(new Modules()); moduleManager.initCoreModules(new Modules()); moduleManager.loadModule(AbstractModelLoader.CEYLON_LANGUAGE, Versions.CEYLON_VERSION_NUMBER, repoManager.getArtifactResult("ceylon.language", Versions.CEYLON_VERSION_NUMBER), getClass().getClassLoader()); RuntimeModelLoader modelLoader = moduleManager.getModelLoader(); modelLoader.setupWithNoStandardModules(); modelLoader.loadStandardModules(); test.test(modelLoader); } static protected class ModelComparison { private boolean isUltimatelyVisible(Declaration d) { if (d instanceof FunctionOrValue && ((FunctionOrValue)d).isParameter()) { Scope container = d.getContainer(); if (container instanceof Declaration) { return isUltimatelyVisible((Declaration)container); } } return d.isShared(); } public void compareDeclarations(String name, Declaration validDeclaration, Declaration modelDeclaration) { if (validDeclaration.isNativeHeader()) { // It's a native header, best to compare against its JVM implementation Declaration impl = ModelUtil.getNativeDeclaration(validDeclaration, Backend.Java); if (impl != null) { validDeclaration = impl; } } compareDeclarations(name, validDeclaration, modelDeclaration, false); } public void compareDeclarations(String name, Declaration validDeclaration, Declaration modelDeclaration, boolean skipAnnotations) { if(alreadyCompared(validDeclaration, modelDeclaration) || validDeclaration instanceof LazyElement) return; Assert.assertNotNull("Missing model declararion for: "+name, modelDeclaration); // check that we have a unit Assert.assertNotNull("Missing Unit: "+modelDeclaration.getQualifiedNameString(), modelDeclaration.getUnit()); Assert.assertNotNull("Invalid Unit", modelDeclaration.getUnit().getPackage()); // let's not check java stuff for now, due to missing types in the jdk's private methods if(name.startsWith("java.")) return; // only compare parameter names for public methods if(!(validDeclaration instanceof FunctionOrValue) || !((FunctionOrValue)validDeclaration).isParameter() || isUltimatelyVisible(validDeclaration)) { Assert.assertEquals(name+" [name]", validDeclaration.getQualifiedNameString(), modelDeclaration.getQualifiedNameString()); } Assert.assertEquals(name+" [shared]", validDeclaration.isShared(), modelDeclaration.isShared()); Assert.assertEquals(name+" [annotation]", validDeclaration.isAnnotation(), modelDeclaration.isAnnotation()); // if they're not shared, stop at making sure they are the same type of object if(!validDeclaration.isShared() && !isUltimatelyVisible(validDeclaration) && !(validDeclaration instanceof TypeParameter)){ boolean sameType = validDeclaration.getClass().isAssignableFrom(modelDeclaration.getClass()); // we may replace Getter or Setter with Value, no harm done sameType |= validDeclaration instanceof Value && modelDeclaration instanceof Value; sameType |= validDeclaration instanceof Setter && modelDeclaration instanceof Value; Assert.assertTrue(name+" [type] " + validDeclaration + " is not the same as " + modelDeclaration, sameType); return; } if(!skipAnnotations) compareAnnotations(validDeclaration, modelDeclaration); // check containers compareContainers(validDeclaration, modelDeclaration); compareScopes(validDeclaration, modelDeclaration); // full check if(validDeclaration instanceof ClassOrInterface){ Assert.assertTrue(name+" [ClassOrInterface]", modelDeclaration instanceof ClassOrInterface); compareClassOrInterfaceDeclarations((ClassOrInterface)validDeclaration, (ClassOrInterface)modelDeclaration); } else if(Decl.isConstructor(validDeclaration)){ Assert.assertTrue(name+" [Constructor]", Decl.isConstructor(modelDeclaration)); } else if(validDeclaration instanceof Function){ Assert.assertTrue(name+" [Method]", modelDeclaration instanceof Function); compareMethodDeclarations((Function)validDeclaration, (Function)modelDeclaration); }else if(validDeclaration instanceof Value || validDeclaration instanceof Setter){ Assert.assertTrue(name+" [Attribute]", modelDeclaration instanceof Value); compareAttributeDeclarations((FunctionOrValue)validDeclaration, (Value)modelDeclaration); }else if(validDeclaration instanceof TypeParameter){ Assert.assertTrue(name+" [TypeParameter]", modelDeclaration instanceof TypeParameter); compareTypeParameters((TypeParameter)validDeclaration, (TypeParameter)modelDeclaration); } } protected void compareContainers(Declaration validDeclaration, Declaration modelDeclaration) { String name = validDeclaration.getQualifiedNameString(); Scope validContainer = validDeclaration.getContainer(); Scope modelContainer = modelDeclaration.getContainer(); if(validContainer instanceof Declaration){ Assert.assertTrue(name+" [Container is Declaration]", modelContainer instanceof Declaration); compareDeclarations(name+" [container]", (Declaration)validContainer, (Declaration)modelContainer); }else{ Assert.assertTrue(name+" [Container is not Declaration]", modelContainer instanceof Declaration == false); } } protected void compareScopes(Declaration validDeclaration, Declaration modelDeclaration) { String name = validDeclaration.getQualifiedNameString(); Scope validContainer = validDeclaration.getContainer(); Scope modelContainer = modelDeclaration.getContainer(); if(validContainer instanceof Declaration){ Assert.assertTrue(name+" [Scope is Declaration]", modelContainer instanceof Declaration); compareDeclarations(name+" [scope]", (Declaration)validContainer, (Declaration)modelContainer); }else{ Assert.assertTrue(name+" [Scope is not Declaration]", modelContainer instanceof Declaration == false); } } protected void compareAnnotations(Declaration validDeclaration, Declaration modelDeclaration) { // let's not compare setter annotations if(validDeclaration instanceof Setter) return; String name = validDeclaration.getQualifiedNameString(); Comparator<Annotation> cmp = new Comparator<Annotation>() { public int compare(Annotation a, Annotation b) { return a.getName().compareTo(b.getName()); } }; Set<Annotation> validAnnotations = new TreeSet<Annotation>(cmp); validAnnotations.addAll(validDeclaration.getAnnotations()); Set<Annotation> modelAnnotations = new TreeSet<Annotation>(cmp); modelAnnotations.addAll(modelDeclaration.getAnnotations()); Assert.assertEquals(name+" [annotation count]", validAnnotations.size(), modelAnnotations.size()); Iterator<Annotation> validIter = validAnnotations.iterator(); Iterator<Annotation> modelIter = modelAnnotations.iterator(); while(validIter.hasNext() || modelIter.hasNext()){ compareAnnotation(name, validIter.next(), modelIter.next()); } } protected void compareAnnotation(String element, Annotation validAnnotation, Annotation modelAnnotation) { Assert.assertEquals(element+ " [annotation name]", validAnnotation.getName(), modelAnnotation.getName()); String name = element+"@"+validAnnotation.getName(); List<String> validPositionalArguments = validAnnotation.getPositionalArguments(); List<String> modelPositionalArguments = modelAnnotation.getPositionalArguments(); Assert.assertEquals(name+ " [annotation argument size]", validPositionalArguments.size(), modelPositionalArguments.size()); for(int i=0;i<validPositionalArguments.size();i++){ Assert.assertEquals(name+ " [annotation argument "+i+"]", validPositionalArguments.get(i), modelPositionalArguments.get(i)); } Map<String, String> validNamedArguments = validAnnotation.getNamedArguments(); Map<String, String> modelNamedArguments = modelAnnotation.getNamedArguments(); Assert.assertEquals(name+ " [annotation named argument size]", validNamedArguments.size(), modelNamedArguments.size()); for(Entry<String,String> validEntry : validNamedArguments.entrySet()){ String modelValue = modelNamedArguments.get(validEntry.getKey()); Assert.assertEquals(name+ " [annotation named argument "+validEntry.getKey()+"]", validEntry.getValue(), modelValue); } } private Map<Integer, Set<Integer>> alreadyCompared = new HashMap<Integer, Set<Integer>>(); private boolean alreadyCompared(Declaration validDeclaration, Declaration modelDeclaration) { int hashCode = System.identityHashCode(modelDeclaration); Set<Integer> comparedDeclarations = alreadyCompared.get(hashCode); if(comparedDeclarations == null){ comparedDeclarations = new HashSet<Integer>(); alreadyCompared.put(hashCode, comparedDeclarations); } return !comparedDeclarations.add(System.identityHashCode(validDeclaration)); } protected void compareTypeParameters(TypeParameter validDeclaration, TypeParameter modelDeclaration) { String name = validDeclaration.getContainer().toString()+"<"+validDeclaration.getName()+">"; Assert.assertEquals(name+" [Contravariant]", validDeclaration.isContravariant(), modelDeclaration.isContravariant()); Assert.assertEquals(name+" [Covariant]", validDeclaration.isCovariant(), modelDeclaration.isCovariant()); Assert.assertEquals(name+" [SelfType]", validDeclaration.isSelfType(), modelDeclaration.isSelfType()); Assert.assertEquals(name+" [Defaulted]", validDeclaration.isDefaulted(), modelDeclaration.isDefaulted()); if (validDeclaration.getDeclaration() != null && modelDeclaration.getDeclaration() != null) { compareDeclarations(name+" [type param]", validDeclaration.getDeclaration(), modelDeclaration.getDeclaration()); } else if (!(validDeclaration.getDeclaration() == null && modelDeclaration.getDeclaration() == null)) { Assert.fail("[Declaration] one has declaration the other not"); } if (validDeclaration.getSelfTypedDeclaration() != null && modelDeclaration.getSelfTypedDeclaration() != null) { compareDeclarations(name+" [type param self typed]", validDeclaration.getSelfTypedDeclaration(), modelDeclaration.getSelfTypedDeclaration()); } else if (!(validDeclaration.getSelfTypedDeclaration() == null && modelDeclaration.getSelfTypedDeclaration() == null)) { Assert.fail("[SelfType] one has self typed declaration the other not"); } if (validDeclaration.getDefaultTypeArgument() != null && modelDeclaration.getDefaultTypeArgument() != null) { compareDeclarations(name+" [type param default]", validDeclaration.getDefaultTypeArgument().getDeclaration(), modelDeclaration.getDefaultTypeArgument().getDeclaration()); } else if (!(validDeclaration.getDefaultTypeArgument() == null && modelDeclaration.getDefaultTypeArgument() == null)) { Assert.fail("[DefaultTypeArgument] one has default type argument the other not"); } compareSatisfiedTypes(name, validDeclaration.getSatisfiedTypes(), modelDeclaration.getSatisfiedTypes()); compareCaseTypes(name, validDeclaration.getCaseTypes(), modelDeclaration.getCaseTypes()); } protected void compareClassOrInterfaceDeclarations(ClassOrInterface validDeclaration, ClassOrInterface modelDeclaration) { String name = validDeclaration.getQualifiedNameString(); Assert.assertEquals(name+" [abstract]", validDeclaration.isAbstract(), modelDeclaration.isAbstract()); Assert.assertEquals(name+" [formal]", validDeclaration.isFormal(), modelDeclaration.isFormal()); Assert.assertEquals(name+" [actual]", validDeclaration.isActual(), modelDeclaration.isActual()); Assert.assertEquals(name+" [default]", validDeclaration.isDefault(), modelDeclaration.isDefault()); Assert.assertEquals(name+" [sealed]", validDeclaration.isSealed(), modelDeclaration.isSealed()); Assert.assertEquals(name+" [dynamic]", validDeclaration.isDynamic(), modelDeclaration.isDynamic()); // extended type if(validDeclaration.getExtendedType() == null) Assert.assertTrue(name+" [null supertype]", modelDeclaration.getExtendedType() == null); else compareDeclarations(name+" [supertype]", validDeclaration.getExtendedType().getDeclaration(), modelDeclaration.getExtendedType()==null ? null : modelDeclaration.getExtendedType().getDeclaration()); // satisfied types! compareSatisfiedTypes(name, validDeclaration.getSatisfiedTypes(), modelDeclaration.getSatisfiedTypes()); // case types compareCaseTypes(name, validDeclaration.getCaseTypes(), modelDeclaration.getCaseTypes()); // work on type parameters compareTypeParameters(name, validDeclaration.getTypeParameters(), modelDeclaration.getTypeParameters()); // tests specific to classes if(validDeclaration instanceof Class){ Assert.assertTrue(name+" [is class]", modelDeclaration instanceof Class); // self type compareSelfTypes((Class)validDeclaration, (Class)modelDeclaration, name); // parameters compareParameterLists(validDeclaration.getQualifiedNameString(), ((Class)validDeclaration).getParameterLists(), ((Class)modelDeclaration).getParameterLists()); // final Assert.assertEquals(name+" [is final]", validDeclaration.isFinal(), modelDeclaration.isFinal()); }else{ // tests specific to interfaces Assert.assertTrue(name+" [is interface]", modelDeclaration instanceof Interface); } // make sure it has every member required for(Declaration validMember : validDeclaration.getMembers()){ // skip non-shared members if(!validMember.isShared()) continue; Declaration modelMember = lookupMember(modelDeclaration, validMember); Assert.assertNotNull(validMember.getClass().getSimpleName() + " " + validMember.getQualifiedNameString()+" ["+validMember.getDeclarationKind()+"] not found in loaded model", modelMember); compareDeclarations(modelMember.getQualifiedNameString(), validMember, modelMember); } // and not more for(Declaration modelMember : modelDeclaration.getMembers()){ // skip non-shared members if(!modelMember.isShared()) continue; Declaration validMember = lookupMember(validDeclaration, modelMember); if (validMember == null && validDeclaration.isNative()) { Declaration hdr = ModelUtil.getNativeHeader(validDeclaration); if (hdr instanceof ClassOrInterface) { validMember = lookupMember((ClassOrInterface)hdr, modelMember); } } Assert.assertNotNull(modelMember.getQualifiedNameString()+" [extra member] encountered in loaded model", validMember); } } protected void compareCaseTypes(String name, List<Type> validTypeDeclarations, List<Type> modelTypeDeclarations) { if(validTypeDeclarations != null){ Assert.assertNotNull(name+ " [null case types]", modelTypeDeclarations); }else{ Assert.assertNull(name+ " [non-null case types]", modelTypeDeclarations); return; } Assert.assertEquals(name+ " [case types count]", validTypeDeclarations.size(), modelTypeDeclarations.size()); for(int i=0;i<validTypeDeclarations.size();i++){ TypeDeclaration validTypeDeclaration = validTypeDeclarations.get(i).getDeclaration(); TypeDeclaration modelTypeDeclaration = modelTypeDeclarations.get(i).getDeclaration(); compareDeclarations(name+ " [case types]", validTypeDeclaration, modelTypeDeclaration); } } protected void compareSelfTypes(Class validDeclaration, Class modelDeclaration, String name) { if(validDeclaration.getSelfType() == null) Assert.assertTrue(name+" [null self type]", modelDeclaration.getSelfType() == null); else{ Type validSelfType = validDeclaration.getSelfType(); Type modelSelfType = modelDeclaration.getSelfType(); Assert.assertNotNull(name+" [non-null self type]", modelSelfType); // self types are always type parameters so they must have a declaration compareDeclarations(name+" [non-null self type]", validSelfType.getDeclaration(), modelSelfType.getDeclaration()); } } private Declaration lookupMember(ClassOrInterface container, Declaration referenceMember) { String name = referenceMember.getName(); for(Declaration member : container.getMembers()){ if ((referenceMember instanceof Constructor && member instanceof FunctionOrValue) || (referenceMember instanceof FunctionOrValue && member instanceof Constructor)) { continue; } if (name == null && member.getName() == null) { return member; } else if(member.getName() != null && member.getName().equals(name)){ // we have a special case if we're asking for a Value and we find a Class, it means it's an "object"'s // class with the same name so we ignore it if(Decl.isValue(referenceMember) && (member instanceof Class || (member instanceof Value && ((Value)member).isParameter()))) continue; // the opposite is also true if((referenceMember instanceof Class || referenceMember instanceof Value && ((Value)referenceMember).isParameter()) && Decl.isValue(member)) continue; // otherwise we found it return member; } } // not found return null; } protected void compareSatisfiedTypes(String name, List<Type> validTypeDeclarations, List<Type> modelTypeDeclarations) { Assert.assertEquals(name+ " [Satisfied types count]", validTypeDeclarations.size(), modelTypeDeclarations.size()); for(int i=0;i<validTypeDeclarations.size();i++){ TypeDeclaration validTypeDeclaration = validTypeDeclarations.get(i).getDeclaration(); TypeDeclaration modelTypeDeclaration = modelTypeDeclarations.get(i).getDeclaration(); compareDeclarations(name+ " [Satisfied types]", validTypeDeclaration, modelTypeDeclaration); } } protected void compareParameterLists(String name, List<ParameterList> validParameterLists, List<ParameterList> modelParameterLists) { Assert.assertEquals(name+" [param lists count]", validParameterLists.size(), modelParameterLists.size()); for(int i=0;i<validParameterLists.size();i++){ List<Parameter> validParameterList = validParameterLists.get(i).getParameters(); List<Parameter> modelParameterList = modelParameterLists.get(i).getParameters(); compareParameterList(name, i, validParameterList, modelParameterList); } } protected void compareParameterList(String name, int i, List<Parameter> validParameterList, List<Parameter> modelParameterList) { Assert.assertEquals(name+" [param lists "+i+" count]", validParameterList.size(), modelParameterList.size()); for(int p=0;p<validParameterList.size();p++){ Parameter validParameter = validParameterList.get(p); Parameter modelParameter = modelParameterList.get(p); Assert.assertEquals(name+" [param "+validParameter.getName()+" name]", validParameter.getName(), modelParameter.getName()); Assert.assertEquals(name+" [param "+validParameter.getName()+" declaredAnything]", validParameter.isDeclaredAnything(), modelParameter.isDeclaredAnything()); Assert.assertEquals(name+" [param "+validParameter.getName()+" sequenced]", validParameter.isSequenced(), modelParameter.isSequenced()); Assert.assertEquals(name+" [param "+validParameter.getName()+" defaulted]", validParameter.isDefaulted(), modelParameter.isDefaulted()); // make sure they have the same name and type compareDeclarations(name+" [param "+i+", "+p+"]", validParameter.getModel(), modelParameter.getModel(), i > 0); } } protected void compareMethodDeclarations(Function validDeclaration, Function modelDeclaration) { String name = validDeclaration.getQualifiedNameString(); Assert.assertEquals(name+" [formal]", validDeclaration.isFormal(), modelDeclaration.isFormal()); Assert.assertEquals(name+" [actual]", validDeclaration.isActual(), modelDeclaration.isActual()); Assert.assertEquals(name+" [default]", validDeclaration.isDefault(), modelDeclaration.isDefault()); List<ParameterList> validParameterLists = validDeclaration.getParameterLists(); List<ParameterList> modelParameterLists = modelDeclaration.getParameterLists(); // only check for void for non-MPL, since those actually return Callable if(validParameterLists.size() == 1){ Assert.assertEquals(name+" [declaredVoid]", validDeclaration.isDeclaredVoid(), modelDeclaration.isDeclaredVoid()); } // make sure it has every parameter list required compareParameterLists(name, validParameterLists, modelParameterLists); // now same for return type compareDeclarations(name + " [return type]", validDeclaration.getType().getDeclaration(), modelDeclaration.getType().getDeclaration()); // work on type parameters compareTypeParameters(name, validDeclaration.getTypeParameters(), modelDeclaration.getTypeParameters()); } protected void compareTypeParameters(String name, List<TypeParameter> validTypeParameters, List<TypeParameter> modelTypeParameters) { Assert.assertEquals(name+" [type parameter count]", validTypeParameters.size(), modelTypeParameters.size()); for(int i=0;i<validTypeParameters.size();i++){ TypeParameter validTypeParameter = validTypeParameters.get(i); TypeParameter modelTypeParameter = modelTypeParameters.get(i); compareDeclarations(name+" [type param "+i+"]", validTypeParameter, modelTypeParameter); } } protected void compareAttributeDeclarations(FunctionOrValue validDeclaration, Value modelDeclaration) { // let's not check Setters since their corresponding Getter is checked already if(validDeclaration instanceof Setter) return; // make sure the flags are the same String name = validDeclaration.getQualifiedNameString(); Assert.assertEquals(name+" [variable]", validDeclaration.isVariable(), modelDeclaration.isVariable()); Assert.assertEquals(name+" [formal]", validDeclaration.isFormal(), modelDeclaration.isFormal()); Assert.assertEquals(name+" [actual]", validDeclaration.isActual(), modelDeclaration.isActual()); Assert.assertEquals(name+" [default]", validDeclaration.isDefault(), modelDeclaration.isDefault()); Assert.assertEquals(name+" [late]", validDeclaration.isLate(), modelDeclaration.isLate()); if (compareTransientness(validDeclaration)) { Assert.assertEquals(name+" [transient]", validDeclaration.isTransient(), modelDeclaration.isTransient()); } // compare the types compareDeclarations(name+" [type]", validDeclaration.getType().getDeclaration(), modelDeclaration.getType().getDeclaration()); } protected boolean compareTransientness(FunctionOrValue validDeclaration) { return true; } }// class ModelComparison @Test public void loadClass(){ verifyCompilerClassLoading("Klass.ceylon"); } @Test public void loadClassWithMethods(){ verifyCompilerClassLoading("KlassWithMethods.ceylon"); } @Test public void loadVariadic(){ compile("Variadic.ceylon"); assertErrors("variadictest", new CompilerError(7, "missing argument to required parameter 'String+ seq' of 'VariadicPlus'") ); } @Test public void loadMultipleParameterList(){ verifyCompilerClassLoading("MultipleParameterList.ceylon"); } @Test public void loadFunctionalParameter(){ verifyCompilerClassLoading("FunctionalParameter.ceylon"); } @Test public void functionalParameterParameterNames(){ compile("FunctionalParameterParameterNames.ceylon"); try { verifyCompilerClassLoading("functionalparameterparameternamestest.ceylon", new RunnableTest() { @Override public void test(ModelLoader loader) { Module mod = loader.getLoadedModule(moduleForJavaModelLoading(), moduleVersionForJavaModelLoading()); Assert.assertNotNull(mod); Package p = mod.getDirectPackage(packageForJavaModelLoading()); Assert.assertNotNull(p); Declaration fpClass = p.getDirectMember("FunctionalParameterParameterNames", Collections.<Type>emptyList(), false); Assert.assertNotNull(fpClass); { // functionalParameter Function fp = (Function)fpClass.getDirectMember("functionalParameter", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Assert.assertEquals("Anything(Anything(String))", typeName(fp)); Parameter paramF = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertTrue(paramF.isDeclaredAnything()); Assert.assertEquals("f", paramF.getName()); Assert.assertTrue(paramF.getModel() instanceof Function); Function modelF = (Function)paramF.getModel(); Assert.assertTrue(modelF.isDeclaredVoid()); Assert.assertEquals("Anything(String)", typeName(modelF)); Assert.assertEquals("f", modelF.getName()); Assert.assertEquals(1, modelF.getParameterLists().size()); Assert.assertEquals(1, modelF.getParameterLists().get(0).getParameters().size()); Parameter paramS = modelF.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("s", paramS.getName()); Assert.assertTrue(paramS.getModel() instanceof Value); Value modelS = (Value)paramS.getModel(); Assert.assertEquals("s", modelS.getName()); Assert.assertEquals("String", typeName(modelS)); } { // callableValueParameter Function fp = (Function)fpClass.getDirectMember("callableValueParameter", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Assert.assertEquals("Anything(Anything(String))", typeName(fp)); Parameter paramF = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("f", paramF.getName()); Assert.assertFalse(paramF.isDeclaredAnything()); Assert.assertTrue(paramF.getModel() instanceof Value); Value modelF = (Value)paramF.getModel(); Assert.assertEquals("f", modelF.getName()); Assert.assertEquals("Anything(String)", typeName(modelF)); } { // functionalParameterNested Function fp = (Function)fpClass.getDirectMember("functionalParameterNested", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Assert.assertEquals("Anything(Anything(Anything(String)))", typeName(fp)); Parameter paramF = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("f", paramF.getName()); Assert.assertTrue(paramF.isDeclaredAnything()); Assert.assertTrue(paramF.getModel() instanceof Function); Function modelF = (Function)paramF.getModel(); Assert.assertEquals("Anything(Anything(String))", typeName(modelF)); Assert.assertEquals("f", modelF.getName()); Assert.assertTrue(modelF.isDeclaredVoid()); Assert.assertEquals(1, modelF.getParameterLists().size()); Assert.assertEquals(1, modelF.getParameterLists().get(0).getParameters().size()); Parameter paramF2 = modelF.getParameterLists().get(0).getParameters().get(0); Assert.assertTrue(paramF2.isDeclaredAnything()); Assert.assertEquals("f2", paramF2.getName()); Assert.assertTrue(paramF2.getModel() instanceof Function); Function modelF2 = (Function)paramF2.getModel(); Assert.assertEquals("Anything(String)", typeName(modelF2)); Assert.assertEquals("f2", modelF2.getName()); Assert.assertTrue(modelF2.isDeclaredVoid()); Assert.assertEquals(1, modelF2.getParameterLists().size()); Assert.assertEquals(1, modelF2.getParameterLists().get(0).getParameters().size()); Parameter paramS = modelF2.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("s", paramS.getName()); Assert.assertTrue(paramS.getModel() instanceof Value); Value modelS = (Value)paramS.getModel(); Assert.assertEquals("s", modelS.getName()); Assert.assertEquals("String", typeName(modelS)); } { // functionalParameterNested2 Function fp = (Function)fpClass.getDirectMember("functionalParameterNested2", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Assert.assertEquals("Anything(Anything(Anything(String, Anything(Boolean, Integer))))", typeName(fp)); Parameter paramF = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("f", paramF.getName()); Assert.assertTrue(paramF.getModel() instanceof Function); Function modelF = (Function)paramF.getModel(); Assert.assertEquals("f", modelF.getName()); Assert.assertEquals("Anything(Anything(String, Anything(Boolean, Integer)))", typeName(modelF)); Assert.assertEquals(1, modelF.getParameterLists().size()); Assert.assertEquals(1, modelF.getParameterLists().get(0).getParameters().size()); Parameter paramF2 = modelF.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("f2", paramF2.getName()); Assert.assertTrue(paramF2.getModel() instanceof Function); Function modelF2 = (Function)paramF2.getModel(); Assert.assertEquals("Anything(String, Anything(Boolean, Integer))", typeName(modelF2)); Assert.assertEquals("f2", modelF2.getName()); Assert.assertEquals(1, modelF2.getParameterLists().size()); Assert.assertEquals(2, modelF2.getParameterLists().get(0).getParameters().size()); Parameter paramS = modelF2.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("s", paramS.getName()); Assert.assertTrue(paramS.getModel() instanceof Value); Value modelS = (Value)paramS.getModel(); Assert.assertEquals("String", typeName(modelS)); Assert.assertEquals("s", modelS.getName()); Parameter paramF3 = modelF2.getParameterLists().get(0).getParameters().get(1); Assert.assertEquals("f3", paramF3.getName()); Assert.assertTrue(paramF3.getModel() instanceof Function); Function modelF3 = (Function)paramF3.getModel(); Assert.assertEquals("Anything(Boolean, Integer)", typeName(modelF3)); Assert.assertEquals("f3", modelF3.getName()); Assert.assertEquals(1, modelF3.getParameterLists().size()); Assert.assertEquals(2, modelF3.getParameterLists().get(0).getParameters().size()); Parameter paramB1 = modelF3.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("b1", paramB1.getName()); Assert.assertTrue(paramB1.getModel() instanceof Value); Value modelB1 = (Value)paramB1.getModel(); Assert.assertEquals("Boolean", typeName(modelB1)); Assert.assertEquals("b1", modelB1.getName()); Parameter paramI2 = modelF3.getParameterLists().get(0).getParameters().get(1); Assert.assertEquals("i2", paramI2.getName()); Assert.assertTrue(paramI2.getModel() instanceof Value); Value modelI2 = (Value)paramI2.getModel(); Assert.assertEquals("i2", modelI2.getName()); Assert.assertEquals("Integer", typeName(modelI2)); } { // functionalParameterMpl Function fp = (Function)fpClass.getDirectMember("functionalParameterMpl", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Assert.assertEquals("Anything(Anything(Integer)(String))", typeName(fp)); Parameter paramF = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertTrue(paramF.isDeclaredAnything()); Assert.assertEquals("mpl", paramF.getName()); Assert.assertTrue(paramF.getModel() instanceof Function); Function modelF = (Function)paramF.getModel(); Assert.assertTrue(modelF.isDeclaredVoid()); Assert.assertEquals("Anything(Integer)(String)", typeName(modelF)); Assert.assertEquals("mpl", modelF.getName()); Assert.assertEquals(2, modelF.getParameterLists().size()); Assert.assertEquals(1, modelF.getParameterLists().get(0).getParameters().size()); Assert.assertEquals(1, modelF.getParameterLists().get(1).getParameters().size()); Parameter paramS = modelF.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("s", paramS.getName()); Assert.assertTrue(paramS.getModel() instanceof Value); Value modelS = (Value)paramS.getModel(); Assert.assertEquals("s", modelS.getName()); Assert.assertEquals("String", typeName(modelS)); Parameter paramS2 = modelF.getParameterLists().get(1).getParameters().get(0); Assert.assertEquals("i2", paramS2.getName()); Assert.assertTrue(paramS2.getModel() instanceof Value); Value modelS2 = (Value)paramS2.getModel(); Assert.assertEquals("i2", modelS2.getName()); Assert.assertEquals("Integer", typeName(modelS2)); } { // functionalParameterMpl2 Function fp = (Function)fpClass.getDirectMember("functionalParameterMpl2", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Parameter paramMpl = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("mpl", paramMpl.getName()); Assert.assertTrue(paramMpl.getModel() instanceof Function); Function modelMpl = (Function)paramMpl.getModel(); Assert.assertEquals("mpl", modelMpl.getName()); Assert.assertEquals(2, modelMpl.getParameterLists().size()); Assert.assertEquals(1, modelMpl.getParameterLists().get(0).getParameters().size()); Assert.assertEquals(1, modelMpl.getParameterLists().get(1).getParameters().size()); Parameter paramS = modelMpl.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("s", paramS.getName()); Assert.assertTrue(paramS.getModel() instanceof Value); Value modelS = (Value)paramS.getModel(); Assert.assertEquals("s", modelS.getName()); Assert.assertEquals("String", typeName(modelS)); Parameter paramF = modelMpl.getParameterLists().get(1).getParameters().get(0); Assert.assertEquals("f", paramF.getName()); Assert.assertTrue(paramF.getModel() instanceof Function); Function modelF = (Function)paramF.getModel(); Assert.assertEquals("f", modelF.getName()); Assert.assertEquals(1, modelF.getParameterLists().size()); Assert.assertEquals(2, modelF.getParameterLists().get(0).getParameters().size()); Parameter paramB1 = modelF.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("b1", paramB1.getName()); Assert.assertTrue(paramB1.getModel() instanceof Value); Value modelB1 = (Value)paramB1.getModel(); Assert.assertEquals("b1", modelB1.getName()); Assert.assertEquals("Boolean", typeName(modelB1)); Parameter paramI2 = modelF.getParameterLists().get(0).getParameters().get(1); Assert.assertEquals("i2", paramI2.getName()); Assert.assertTrue(paramI2.getModel() instanceof Value); Value modelI2 = (Value)paramI2.getModel(); Assert.assertEquals("i2", modelI2.getName()); Assert.assertEquals("Integer", typeName(modelI2)); } { // functionalParameterMpl3 Function fp = (Function)fpClass.getDirectMember("functionalParameterMpl3", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Parameter paramMpl = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("mpl", paramMpl.getName()); Assert.assertTrue(paramMpl.getModel() instanceof Function); Function modelMpl = (Function)paramMpl.getModel(); Assert.assertEquals("mpl", modelMpl.getName()); Assert.assertEquals(2, modelMpl.getParameterLists().size()); Assert.assertEquals(1, modelMpl.getParameterLists().get(0).getParameters().size()); Assert.assertEquals(1, modelMpl.getParameterLists().get(1).getParameters().size()); Parameter paramF = modelMpl.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("f", paramF.getName()); Assert.assertTrue(paramF.getModel() instanceof Function); Function modelF = (Function)paramF.getModel(); Assert.assertEquals("f", modelF.getName()); Assert.assertEquals(1, modelF.getParameterLists().size()); Assert.assertEquals(2, modelF.getParameterLists().get(0).getParameters().size()); Parameter paramB1 = modelF.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("b1", paramB1.getName()); Assert.assertTrue(paramB1.getModel() instanceof Value); Value modelB1 = (Value)paramB1.getModel(); Assert.assertEquals("b1", modelB1.getName()); Assert.assertEquals("Boolean", typeName(modelB1)); Parameter paramI2 = modelF.getParameterLists().get(0).getParameters().get(1); Assert.assertEquals("i2", paramI2.getName()); Assert.assertTrue(paramI2.getModel() instanceof Value); Value modelI2 = (Value)paramI2.getModel(); Assert.assertEquals("i2", modelI2.getName()); Assert.assertEquals("Integer", typeName(modelI2)); Parameter paramS = modelMpl.getParameterLists().get(1).getParameters().get(0); Assert.assertEquals("s", paramS.getName()); Assert.assertTrue(paramS.getModel() instanceof Value); Value modelS = (Value)paramS.getModel(); Assert.assertEquals("s", modelS.getName()); Assert.assertEquals("String", typeName(modelS)); } { // functionalParameterReturningCallable Function fp = (Function)fpClass.getDirectMember("functionalParameterReturningCallable", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Parameter paramF = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("f", paramF.getName()); Assert.assertTrue(paramF.getModel() instanceof Function); Function modelF = (Function)paramF.getModel(); Assert.assertEquals("f", modelF.getName()); Assert.assertEquals("Anything()", modelF.getType().asString()); Assert.assertEquals(1, modelF.getParameterLists().size()); Assert.assertEquals(1, modelF.getParameterLists().get(0).getParameters().size()); Parameter paramS = modelF.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("s", paramS.getName()); Assert.assertTrue(paramS.getModel() instanceof Value); Value modelS = (Value)paramS.getModel(); Assert.assertEquals("s", modelS.getName()); Assert.assertEquals("String", modelS.getType().asString()); } { // functionalParameterReturningCallable Function fp = (Function)fpClass.getDirectMember("functionalParameterTakingCallable", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Parameter paramF = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("f", paramF.getName()); Assert.assertTrue(paramF.getModel() instanceof Function); Function modelF = (Function)paramF.getModel(); Assert.assertEquals("f", modelF.getName()); Assert.assertEquals("Anything", modelF.getType().asString()); Assert.assertEquals(1, modelF.getParameterLists().size()); Assert.assertEquals(1, modelF.getParameterLists().get(0).getParameters().size()); Parameter paramF2 = modelF.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("f2", paramF2.getName()); Assert.assertTrue(paramF2.getModel() instanceof Value); Value modelF2 = (Value)paramF2.getModel(); Assert.assertEquals("f2", modelF2.getName()); Assert.assertEquals("Anything(String)", modelF2.getType().asString()); } { // functionalParameterVariadicStar Function fp = (Function)fpClass.getDirectMember("functionalParameterVariadicStar", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Assert.assertEquals("Anything(Anything(String*))", typeName(fp)); Parameter paramF = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertTrue(paramF.isDeclaredAnything()); Assert.assertEquals("f", paramF.getName()); Assert.assertTrue(paramF.getModel() instanceof Function); Function modelF = (Function)paramF.getModel(); Assert.assertTrue(modelF.isDeclaredVoid()); Assert.assertEquals("Anything(String*)", typeName(modelF)); Assert.assertEquals("f", modelF.getName()); Assert.assertEquals(1, modelF.getParameterLists().size()); Assert.assertEquals(1, modelF.getParameterLists().get(0).getParameters().size()); Parameter paramS = modelF.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("s", paramS.getName()); Assert.assertTrue(paramS.isSequenced()); Assert.assertFalse(paramS.isAtLeastOne()); Assert.assertTrue(paramS.getModel() instanceof Value); Value modelS = (Value)paramS.getModel(); Assert.assertEquals("s", modelS.getName()); Assert.assertEquals("String[]", typeName(modelS)); } { // functionalParameterVariadicPlus Function fp = (Function)fpClass.getDirectMember("functionalParameterVariadicPlus", null, false); Assert.assertNotNull(fp); Assert.assertEquals(1, fp.getParameterLists().size()); Assert.assertEquals(1, fp.getParameterLists().get(0).getParameters().size()); Assert.assertEquals("Anything(Anything(String+))", typeName(fp)); Parameter paramF = fp.getParameterLists().get(0).getParameters().get(0); Assert.assertTrue(paramF.isDeclaredAnything()); Assert.assertEquals("f", paramF.getName()); Assert.assertTrue(paramF.getModel() instanceof Function); Function modelF = (Function)paramF.getModel(); Assert.assertTrue(modelF.isDeclaredVoid()); Assert.assertEquals("Anything(String+)", typeName(modelF)); Assert.assertEquals("f", modelF.getName()); Assert.assertEquals(1, modelF.getParameterLists().size()); Assert.assertEquals(1, modelF.getParameterLists().get(0).getParameters().size()); Parameter paramS = modelF.getParameterLists().get(0).getParameters().get(0); Assert.assertEquals("s", paramS.getName()); Assert.assertTrue(paramS.isSequenced()); Assert.assertTrue(paramS.isAtLeastOne()); Assert.assertTrue(paramS.getModel() instanceof Value); Value modelS = (Value)paramS.getModel(); Assert.assertEquals("s", modelS.getName()); Assert.assertEquals("[String+]", typeName(modelS)); } } private String typeName(FunctionOrValue fp) { if (fp instanceof Function) { return fp.appliedTypedReference(null, Collections.<Type>emptyList()).getFullType().asString(); } else if (fp instanceof Value) { return fp.getType().asString(); } return null; } }); } catch (RuntimeException e) { if (e.getCause() instanceof org.junit.ComparisonFailure) { throw (org.junit.ComparisonFailure)e.getCause(); } else if (e.getCause() instanceof java.lang.AssertionError) { throw (java.lang.AssertionError)e.getCause(); } throw e; } } @Test public void loadInnerClass(){ verifyCompilerClassLoading("InnerClass.ceylon"); } @Test public void loadInnerInterface(){ verifyCompilerClassLoading("InnerInterface.ceylon"); } @Test public void loadClassWithAttributes(){ verifyCompilerClassLoading("KlassWithAttributes.ceylon"); } @Test public void loadClassWithAttributeAndConflictingMethods(){ verifyCompilerClassLoading("KlassWithAttributeAndConflictingMethods.ceylon"); } @Test public void loadClassSingletonConstructors(){ verifyCompilerClassLoading("SingletonConstructors.ceylon"); } @Test public void loadTypeParameters(){ verifyCompilerClassLoading("TypeParameters.ceylon"); } @Test public void loadTypeParameterResolving(){ verifyCompilerClassLoading("TypeParameterResolving.ceylon"); } @Test public void loadToplevelMethods(){ verifyCompilerClassLoading("ToplevelMethods.ceylon"); } @Test public void loadToplevelAttributes(){ verifyCompilerClassLoading("ToplevelAttributes.ceylon"); } @Test public void loadToplevelObjects(){ verifyCompilerClassLoading("ToplevelObjects.ceylon"); } @Test public void loadErasedTypes(){ verifyCompilerClassLoading("ErasedTypes.ceylon"); } @Test public void loadDocAnnotations(){ verifyCompilerClassLoading("DocAnnotations.ceylon"); } @Test public void loadLocalDeclarations(){ verifyCompilerClassLoading("LocalDeclarations.ceylon"); } @Test public void loadDefaultValues(){ verifyCompilerClassLoading("DefaultValues.ceylon"); } @Test public void loadJavaKeywords(){ verifyCompilerClassLoading("JavaKeywords.ceylon"); } @Test public void loadAnnotations(){ verifyCompilerClassLoading("Annotations.ceylon"); } @Test public void loadGettersWithUnderscores(){ verifyCompilerClassLoading("GettersWithUnderscores.ceylon"); } @Test public void loadCaseTypes(){ verifyCompilerClassLoading("CaseTypes.ceylon"); } @Test public void loadSelfType(){ verifyCompilerClassLoading("SelfType.ceylon"); } @Test public void testTypeParserUsingSourceModel(){ compile("A.ceylon", "B.ceylon"); compile("A.ceylon"); } @Test public void loadFormalClasses(){ verifyCompilerClassLoading("FormalClasses.ceylon"); } @Test public void parallelLoader(){ // whatever test, doesn't matter verifyCompilerClassLoading("Any.ceylon", new RunnableTest(){ @Override public void test(final ModelLoader loader) { // now walk it in threads List<Callable<Object>> tasks = new ArrayList<Callable<Object>>(10); // make a runnable that walks the whole jdk model Callable<Object> runnable = new Callable<Object>(){ @Override public Object call() throws Exception { System.err.println("Starting work from thread " + Thread.currentThread().getName()); // walk every jdk package for(String moduleName : JDKUtils.getJDKModuleNames()) { // load the module Module mod = loader.getLoadedModule(moduleName, JDKUtils.jdk.version); Assert.assertNotNull(mod); for (String pkgName : JDKUtils.getJDKPackagesByModule(moduleName)) { Package p = mod.getDirectPackage(pkgName); Assert.assertNotNull(p); for(Declaration decl : p.getMembers()){ // that causes model loading decl.getQualifiedNameString(); } } } System.err.println("Done work from thread " + Thread.currentThread().getName()); return null; } }; // make ten tasks with the same runnable for(int i=0;i<10;i++){ tasks.add(runnable); } // create an executor ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 10, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(10)); try { // run them all List<Future<Object>> futures = executor.invokeAll(tasks); // and wait for them all to be done for(Future<Object> f : futures){ f.get(); } executor.shutdown(); } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { throw new RuntimeException(e); } // [Model loader: 4488(loaded)/4945(total) declarations] is what we expect if it works out // now print the stats if(loader instanceof AbstractModelLoader){ ((AbstractModelLoader)loader).printStats(); } } }, Arrays.asList("-verbose:loader")); } @Ignore("This is the single-threaded version of parallelLoader that loads the JDK entirely to benchmark the model loader") @Test public void jdkModelLoaderSpeedTest(){ // whatever test, doesn't matter verifyCompilerClassLoading("Any.ceylon", new RunnableTest(){ @Override public void test(ModelLoader loader) { // walk every jdk package for (String moduleName : JDKUtils.getJDKModuleNames()) { Module mod = loader.getLoadedModule(moduleName, JDKUtils.jdk.version); Assert.assertNotNull(mod); for(String pkgName : JDKUtils.getJDKPackagesByModule(moduleName)){ Package p = mod.getDirectPackage(pkgName); Assert.assertNotNull(p); for(Declaration decl : p.getMembers()){ // that causes model loading decl.getQualifiedNameString(); } } } // [Model loader: 4488(loaded)/4945(total) declarations] is what we expect if it works out // now print the stats if(loader instanceof AbstractModelLoader){ ((AbstractModelLoader)loader).printStats(); } } }, Arrays.asList("-verbose:loader")); } protected String moduleForJavaModelLoading() { return packageForJavaModelLoading(); } protected String moduleVersionForJavaModelLoading(){ return "1"; } protected String packageForJavaModelLoading() { return "com.redhat.ceylon.compiler.java.test.model"; } @Test public void javaModelLoading(){ compile("JavaType.java"); verifyCompilerClassLoading("Java.ceylon", new RunnableTest(){ @Override public void test(ModelLoader loader) { Module mod = loader.getLoadedModule(moduleForJavaModelLoading(), moduleVersionForJavaModelLoading()); Assert.assertNotNull(mod); Package p = mod.getDirectPackage(packageForJavaModelLoading()); Assert.assertNotNull(p); Declaration javaType = p.getDirectMember("JavaType", null, false); Assert.assertNotNull(javaType); // check the method which returns a java list Function javaListMethod = (Function) javaType.getDirectMember("javaList", null, false); Assert.assertNotNull(javaListMethod); Assert.assertEquals("List<out Object>", javaListMethod.getType().asString()); Parameter javaListParam = javaListMethod.getParameterLists().get(0).getParameters().get(0); Assert.assertNotNull(javaListParam); Assert.assertEquals("List<out Object>?", javaListParam.getType().asString()); // check the method which returns a Ceylon list Function ceylonListMethod = (Function) javaType.getDirectMember("ceylonList", null, false); Assert.assertNotNull(ceylonListMethod); Assert.assertEquals("List<Object>", ceylonListMethod.getType().asString()); Parameter ceylonListParam = ceylonListMethod.getParameterLists().get(0).getParameters().get(0); Assert.assertNotNull(ceylonListParam); Assert.assertEquals("List<Object>?", ceylonListParam.getType().asString()); Function equalsMethod = (Function) javaType.getDirectMember("equals", null, false); Assert.assertNotNull(equalsMethod); Assert.assertTrue(equalsMethod.isActual()); Assert.assertTrue(equalsMethod.getRefinedDeclaration() != equalsMethod); Value hashAttribute = (Value) javaType.getDirectMember("hash", null, false); Assert.assertNotNull(hashAttribute); Assert.assertTrue(hashAttribute.isActual()); Assert.assertTrue(hashAttribute.getRefinedDeclaration() != hashAttribute); Value stringAttribute = (Value) javaType.getDirectMember("string", null, false); Assert.assertNotNull(stringAttribute); Assert.assertTrue(stringAttribute.isActual()); Assert.assertTrue(stringAttribute.getRefinedDeclaration() != stringAttribute); Function cloneMethod = (Function) javaType.getDirectMember("clone", null, false); Assert.assertNotNull(cloneMethod); Assert.assertFalse(cloneMethod.isActual()); Assert.assertTrue(cloneMethod.getRefinedDeclaration() == cloneMethod); Function finalizeMethod = (Function) javaType.getDirectMember("finalize", null, false); Assert.assertNotNull(finalizeMethod); Assert.assertFalse(finalizeMethod.isActual()); Assert.assertTrue(finalizeMethod.getRefinedDeclaration() == finalizeMethod); } }); } @Test public void javaDeprecated(){ compile("JavaDeprecated.java"); verifyCompilerClassLoading("JavaDeprecated.ceylon", new RunnableTest(){ @Override public void test(ModelLoader loader) { Module mod = loader.getLoadedModule(moduleForJavaModelLoading(), moduleVersionForJavaModelLoading()); Assert.assertNotNull(mod); Package p = mod.getDirectPackage(packageForJavaModelLoading()); Assert.assertNotNull(p); Declaration javaDep = p.getDirectMember("JavaDeprecated", null, false); Assert.assertNotNull(javaDep); Assert.assertEquals(javaDep.toString(), 1, numDeprecated(javaDep)); Function javaMethod = (Function) javaDep.getDirectMember("m", null, false); Assert.assertNotNull(javaMethod); Assert.assertEquals(javaMethod.toString(), 1, numDeprecated(javaMethod)); Parameter javaParameter = javaMethod.getParameterLists().get(0).getParameters().get(0); Assert.assertNotNull(javaParameter); Assert.assertEquals(javaParameter.toString(), 1, numDeprecated(javaParameter.getModel())); Value javaField = (Value) javaDep.getDirectMember("s", null, false); Assert.assertNotNull(javaField); Assert.assertEquals(javaField.toString(), 1, numDeprecated(javaField)); // Check there is only 1 model Annotation, when annotation with ceylon's deprecated... javaMethod = (Function) javaDep.getDirectMember("ceylonDeprecation", null, false); Assert.assertNotNull(javaMethod); Assert.assertEquals(javaMethod.toString(), 1, numDeprecated(javaMethod)); // ... or both the ceylon and java deprecated javaMethod = (Function) javaDep.getDirectMember("bothDeprecation", null, false); Assert.assertNotNull(javaMethod); Assert.assertEquals(javaMethod.toString(), 1, numDeprecated(javaMethod)); } private int numDeprecated(Declaration javaDep) { int num = 0; for (Annotation a : javaDep.getAnnotations()) { if ("deprecated".equals(a.getName())) { num++; } } return num; } }); } @Test public void ceylonDeprecated(){ compile("CeylonDeprecated.ceylon"); assertErrors("ceylondeprecatedtest", true, CompilerError.warning(3, "type is deprecated: 'CeylonDeprecated'"), CompilerError.warning(4, "declaration is deprecated: 'CeylonDeprecated'"), CompilerError.warning(6, "type is deprecated: 'CeylonDeprecated2'"), CompilerError.warning(7, "declaration is deprecated: 'CeylonDeprecated2'"), CompilerError.warning(10, "declaration is deprecated: default constructor of 'CeylonDeprecated3'"), CompilerError.warning(11, "declaration is deprecated: 'other'"), CompilerError.warning(11, "declaration is deprecated: default constructor of 'CeylonDeprecated3'"), CompilerError.warning(12, "declaration is deprecated: 'val'"), CompilerError.warning(14, "declaration is deprecated: 'a'"), CompilerError.warning(15, "declaration is deprecated: 'm'"), CompilerError.warning(17, "declaration is deprecated: 'a'"), CompilerError.warning(18, "declaration is deprecated: 'm'"), CompilerError.warning(20, "type is deprecated: 'CeylonDeprecated6'"), CompilerError.warning(22, "declaration is deprecated: 'ceylonDeprecated7'"), CompilerError.warning(23, "declaration is deprecated: 'ceylonDeprecated8'"), CompilerError.warning(25, "declaration is deprecated: 'ceylonDeprecated9'"), CompilerError.warning(26, "declaration is deprecated: 'ceylonDeprecated10'"), CompilerError.warning(28, "declaration is deprecated: 'ceylonDeprecated11'") ); } @Test public void bogusModelAnnotationsTopLevelAttribute(){ compile("bogusTopLevelAttributeNoGetter_.java", "bogusTopLevelAttributeMissingType_.java", "bogusTopLevelAttributeInvalidType_.java"); assertErrors("bogusTopLevelAttributeUser", new CompilerError(2, "Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n" +" Error while resolving toplevel attribute com.redhat.ceylon.compiler.java.test.model::bogusTopLevelAttributeNoGetter: getter method missing"), new CompilerError(-1, "Error while resolving type of toplevel attribute for com.redhat.ceylon.compiler.java.test.model::bogusTopLevelAttributeMissingType: Could not find type 'com.redhat.ceylon.compiler.java.test.model.MissingType'"), new CompilerError(-1, "Error while parsing type of toplevel attribute for com.redhat.ceylon.compiler.java.test.model::bogusTopLevelAttributeInvalidType: Expecting word but got AND"), new CompilerError(3, "could not determine type of function or value reference: 'bogusTopLevelAttributeNoGetter': Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n"+ " Error while resolving toplevel attribute com.redhat.ceylon.compiler.java.test.model::bogusTopLevelAttributeNoGetter: getter method missing"), new CompilerError(4, "could not determine type of function or value reference: 'bogusTopLevelAttributeMissingType': Error while resolving type of toplevel attribute for com.redhat.ceylon.compiler.java.test.model::bogusTopLevelAttributeMissingType: Could not find type 'com.redhat.ceylon.compiler.java.test.model.MissingType'"), new CompilerError(5, "could not determine type of function or value reference: 'bogusTopLevelAttributeInvalidType': Error while parsing type of toplevel attribute for com.redhat.ceylon.compiler.java.test.model::bogusTopLevelAttributeInvalidType: Expecting word but got AND") ); } @Test public void bogusModelAnnotationsTopLevelMethod(){ compile("bogusTopLevelMethodNoMethod_.java", "bogusTopLevelMethodMissingType_.java", "bogusTopLevelMethodInvalidType_.java", "bogusTopLevelMethodNotStatic_.java"); assertErrors("bogusTopLevelMethodUser", new CompilerError(2, "Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n" +" Error while resolving toplevel method com.redhat.ceylon.compiler.java.test.model::bogusTopLevelMethodNoMethod: static method missing"), new CompilerError(2, "Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n" +" Error while resolving toplevel method com.redhat.ceylon.compiler.java.test.model::bogusTopLevelMethodNotStatic: method is not static"), new CompilerError(2, "Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n" +" Error while resolving type of toplevel method for com.redhat.ceylon.compiler.java.test.model::bogusTopLevelMethodMissingType:\n" +" Could not find type 'com.redhat.ceylon.compiler.java.test.model.MissingType'"), new CompilerError(2, "Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n" +" Error while parsing type of toplevel method for com.redhat.ceylon.compiler.java.test.model::bogusTopLevelMethodInvalidType:\n" +" Expecting word but got AND"), new CompilerError(3, "could not determine type of function or value reference: 'bogusTopLevelMethodNoMethod': Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n" + " Error while resolving toplevel method com.redhat.ceylon.compiler.java.test.model::bogusTopLevelMethodNoMethod: static method missing"), new CompilerError(4, "could not determine type of function or value reference: 'bogusTopLevelMethodNotStatic': Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n"+ " Error while resolving toplevel method com.redhat.ceylon.compiler.java.test.model::bogusTopLevelMethodNotStatic: method is not static"), new CompilerError(5, "could not determine type of function or value reference: 'bogusTopLevelMethodMissingType': Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n"+ " Error while resolving type of toplevel method for com.redhat.ceylon.compiler.java.test.model::bogusTopLevelMethodMissingType:\n"+ " Could not find type 'com.redhat.ceylon.compiler.java.test.model.MissingType'"), new CompilerError(6, "could not determine type of function or value reference: 'bogusTopLevelMethodInvalidType': Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n" + " Error while parsing type of toplevel method for com.redhat.ceylon.compiler.java.test.model::bogusTopLevelMethodInvalidType:\n" + " Expecting word but got AND") ); } @Test public void bogusModelAnnotationsTopLevelClass(){ compile("BogusTopLevelClass.java", "BogusTopLevelClass2.java"); assertErrors("bogusTopLevelClassUser", new CompilerError(-1, "Constructor for 'com.redhat.ceylon.compiler.java.test.model.BogusTopLevelClass' should take 1 reified type arguments (TypeDescriptor) but has '0': skipping constructor."), new CompilerError(-1, "Invalid type signature for self type of com.redhat.ceylon.compiler.java.test.model::BogusTopLevelClass: com.redhat.ceylon.compiler.java.test.model::MissingType is not a type parameter"), new CompilerError(2, "Error while loading the com.redhat.ceylon.compiler.java.test.model/1 module:\n Error while resolving type of extended type for com.redhat.ceylon.compiler.java.test.model::BogusTopLevelClass:\n Could not find type 'com.redhat.ceylon.compiler.java.test.model.MissingType'"), new CompilerError(3, "class cannot be instantiated: 'BogusTopLevelClass' does not have a default constructor") ); } interface I<T,X,B extends Number> { void foo(); void params(int i); void parameterised(T t); void parameterised(T t, String s); void parameterised2(X t); <M> void mparameterised(); void parameterisedB(B b); } interface I2<B extends Number> { void parameterisedB(B b); } class RawC implements I2 { @Override public void parameterisedB(Number b) {} } class C<T,B extends Number> implements I<Integer,T,B> { @Override public void foo() {} // this one does not override anything public void bar() {} @Override public void params(int i){} // overrides a generic method @Override public void parameterised(Integer t) {} // overrides a generic method @Override public void parameterised(Integer t, String s) {} // overrides a generic method @Override public void parameterised2(T t) {} // this one does not override anything public void parameterised(String t) {} @Override public void mparameterised() {} // overrides a generic method with bounded type @Override public void parameterisedB(B b) {} } class C2 extends C<String, Integer> { public void params(){} public void parameterised(Integer t, int i) {} } class Container<O> { class Inner<I> { public void method(O o, I i){} } } class ContainerSubClass extends Container<Integer> { class Inner extends Container<Integer>.Inner<String> { @Override public void method(Integer o, String i) {} } } class Visibility { protected void prot(){} void pkg(){} private void priv(){} } class VisibilitySubClass extends Visibility { protected void prot(){} void pkg(){} private void priv(){} } interface Channel {} interface WebSocketChannel extends Channel {} public abstract class AbstractReceiveListener implements ChannelListener<WebSocketChannel> { @Override public void handleEvent(WebSocketChannel channel) {} } public interface ChannelListener<T extends Channel> { void handleEvent(T channel); } class HiddenObjectMethods { @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } @Override protected void finalize() throws Throwable { super.finalize(); } @Override public boolean equals(Object obj) { return super.equals(obj); } @Override public int hashCode() { return super.hashCode(); } @Override public String toString() { return super.toString(); } } @Test public void testReflectionOverriding() throws NoSuchMethodException, SecurityException{ Assert.assertTrue(ReflectionUtils.isOverridingMethod(C.class.getDeclaredMethod("foo"))); Assert.assertFalse(ReflectionUtils.isOverridingMethod(C.class.getDeclaredMethod("bar"))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(C.class.getDeclaredMethod("params", int.class))); Assert.assertFalse(ReflectionUtils.isOverridingMethod(C2.class.getDeclaredMethod("params"))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(C.class.getDeclaredMethod("parameterised", Integer.class))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(C.class.getDeclaredMethod("parameterised", Integer.class, String.class))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(C.class.getDeclaredMethod("parameterised2", Object.class))); Assert.assertFalse(ReflectionUtils.isOverridingMethod(C2.class.getDeclaredMethod("parameterised", Integer.class, int.class))); Assert.assertFalse(ReflectionUtils.isOverridingMethod(C.class.getDeclaredMethod("parameterised", String.class))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(C.class.getDeclaredMethod("mparameterised"))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(C.class.getDeclaredMethod("parameterisedB", Number.class))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(RawC.class.getDeclaredMethod("parameterisedB", Number.class))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(ContainerSubClass.Inner.class.getDeclaredMethod("method", Integer.class, String.class))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(VisibilitySubClass.class.getDeclaredMethod("prot"))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(VisibilitySubClass.class.getDeclaredMethod("pkg"))); Assert.assertFalse(ReflectionUtils.isOverridingMethod(VisibilitySubClass.class.getDeclaredMethod("priv"))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(AbstractReceiveListener.class.getDeclaredMethod("handleEvent", WebSocketChannel.class))); Assert.assertFalse(ReflectionUtils.isOverridingMethod(HiddenObjectMethods.class.getDeclaredMethod("finalize"))); Assert.assertFalse(ReflectionUtils.isOverridingMethod(HiddenObjectMethods.class.getDeclaredMethod("clone"))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(HiddenObjectMethods.class.getDeclaredMethod("toString"))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(HiddenObjectMethods.class.getDeclaredMethod("hashCode"))); Assert.assertTrue(ReflectionUtils.isOverridingMethod(HiddenObjectMethods.class.getDeclaredMethod("equals", Object.class))); } @Test public void loadPublicJavaClassWithPackageConstructor(){ compile("PublicJavaClassWithPackageConstructor.java"); compile("publicjavaclasswithpackageconstructortest.ceylon"); } @Test public void loadJavaContainer(){ compile("JavaContainer1.java", "JavaContainer2.java"); compile("JavaContainerTest.ceylon"); } private static final ClosableVirtualFile getLatestZippedLanguageSourceFile() { VFS vfs = new VFS(); File langDir = new File("../ceylon-dist/dist/repo/ceylon/language"); if (!langDir.exists()) { System.err.println("Unable to test language module, not found in repository: " + langDir); System.exit(-1); } String[] versions = langDir.list(); Arrays.sort(versions); String version = versions[versions.length-1]; //last return vfs.getFromZipFile( new File(langDir, version + "/ceylon.language-" + version + ".src") ); } /** * When testing the annotations on the native declarations in the language module * we need to wory around a few bugs */ class OtherModelCompare extends ModelComparison { @Override protected void compareAnnotations(Declaration validDeclaration, Declaration modelDeclaration) { // do nothing, until ceylon/ceylon-compiler#1231 is fixed } } @Test public void compareNativeRuntimeWithJavaRuntime() { // parse the ceylon sources from the language module and // build a map of all the native declarations final Map<String, Declaration> nativeFromSource = new HashMap<String, Declaration>(); ClosableVirtualFile latestZippedLanguageSourceFile = getLatestZippedLanguageSourceFile(); try { TypeCheckerBuilder typeCheckerBuilder = new TypeCheckerBuilder() .verbose(false) .addSrcDirectory(latestZippedLanguageSourceFile); TypeChecker typeChecker = typeCheckerBuilder.getTypeChecker(); typeChecker.process(); for (PhasedUnit pu : typeChecker.getPhasedUnits().getPhasedUnits()) { for (Declaration d : pu.getDeclarations()) { if (d.isNativeHeader() && d.isToplevel()) { String qualifiedNameString = d.getQualifiedNameString(); String key = d.getDeclarationKind()+":"+qualifiedNameString; Declaration prev = nativeFromSource.put(key, d); if (prev != null) { Assert.fail("Two declarations with the same key " + key + ": " + d + " and: " + prev); } } } } } finally { latestZippedLanguageSourceFile.close(); } System.out.println(nativeFromSource); // now compile something (it doesn't matter what, we just need // to get our hands on from-binary models for the language module) RunnableTest tester = new RunnableTest() { @Override public void test(ModelLoader loader) { OtherModelCompare comparer = new OtherModelCompare(); Module binaryLangMod = loader.getLoadedModule(AbstractModelLoader.CEYLON_LANGUAGE, Versions.CEYLON_VERSION_NUMBER); for (Map.Entry<String, Declaration> entry : nativeFromSource.entrySet()) { System.out.println(entry.getKey()); Declaration source = entry.getValue(); ModelLoader.DeclarationType dt = null; switch (source.getDeclarationKind()) { case TYPE: case TYPE_PARAMETER: dt = DeclarationType.TYPE; break; case MEMBER: case SETTER: dt = DeclarationType.VALUE; break; } // Ensure the package is loaded binaryLangMod.getDirectPackage(source.getQualifiedNameString().replaceAll("::.*", "")); Declaration binary = loader.getDeclaration(binaryLangMod, source.getQualifiedNameString().replace("::", "."), dt); comparer.compareDeclarations(source.getQualifiedNameString(), source, binary); } } }; verifyCompilerClassLoading("Any.ceylon", tester, defaultOptions); verifyRuntimeClassLoading(tester); } }