/******************************************************************************* * Copyright (c) 2010 xored software, Inc. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * xored software, Inc. - initial API and Implementation (Alex Panchenko) *******************************************************************************/ package org.eclipse.dltk.javascript.core.tests.typeinference; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashSet; import java.util.Set; import org.eclipse.dltk.compiler.CharOperation; import org.eclipse.dltk.compiler.env.ModuleSource; import org.eclipse.dltk.internal.javascript.ti.TypeInferencer2; import org.eclipse.dltk.javascript.ast.Script; import org.eclipse.dltk.javascript.parser.JavaScriptParser; import org.eclipse.dltk.javascript.typeinfo.ITypeInfoContext; import org.eclipse.dltk.javascript.typeinfo.ITypeNames; import org.eclipse.dltk.javascript.typeinfo.ITypeProvider; import org.eclipse.dltk.javascript.typeinfo.TypeCache; import org.eclipse.dltk.javascript.typeinfo.TypeMode; import org.eclipse.dltk.javascript.typeinfo.TypeUtil; import org.eclipse.dltk.javascript.typeinfo.model.Member; import org.eclipse.dltk.javascript.typeinfo.model.Method; import org.eclipse.dltk.javascript.typeinfo.model.Parameter; import org.eclipse.dltk.javascript.typeinfo.model.Property; import org.eclipse.dltk.javascript.typeinfo.model.Type; import org.eclipse.dltk.javascript.typeinfo.model.TypeInfoModelFactory; import org.eclipse.dltk.javascript.typeinfo.model.TypeKind; import org.eclipse.emf.common.util.EList; @SuppressWarnings("nls") public class ExampleTypeProvider implements ITypeProvider { static final String TYPE_SERVICE = "ExampleService"; private static final String TYPE_RESPONSE = "ExampleResponse"; private static final String TYPE_SERVICE2 = "ExampleService2"; static final String TYPE_EXAMPLE_FORMS = "ExampleForms"; static final String TYPE_WITH_COLLECTION = "ExampleTypeWithCollection"; static final String TYPE_GENERIC_ARRAY_METHOD = "ExampleArrayMethod"; public boolean initialize(ITypeInfoContext context) { return true; } private static final TypeCache CACHE = new TypeCache("dltk", "javascript.examples") { @Override protected Type createType(String context, String typeName) { if ("Continuation".equals(typeName)) { Type type = TypeInfoModelFactory.eINSTANCE.createType(); type.setName(typeName); type.setKind(TypeKind.JAVASCRIPT); type.setSuperType(getType(context, ITypeNames.FUNCTION)); return addType(CACHE_BUCKET, type); } else if (TYPE_SERVICE.equals(typeName)) { Type type = TypeInfoModelFactory.eINSTANCE.createType(); type.setName(typeName); type.setKind(TypeKind.JAVA); Method method1 = TypeInfoModelFactory.eINSTANCE.createMethod(); method1.setName("execute"); method1.setType(getTypeRef(context, TYPE_RESPONSE)); type.getMembers().add(method1); Method method2 = TypeInfoModelFactory.eINSTANCE.createMethod(); method2.setName("executeCompatible"); method2.setType(getTypeRef(context, TYPE_RESPONSE)); method2.setDeprecated(true); type.getMembers().add(method2); Property prop1 = TypeInfoModelFactory.eINSTANCE .createProperty(); prop1.setName("name"); prop1.setType(getTypeRef(context, ITypeNames.STRING)); type.getMembers().add(prop1); Property prop2 = TypeInfoModelFactory.eINSTANCE .createProperty(); prop2.setName("nameCompatible"); prop2.setType(getTypeRef(context, ITypeNames.STRING)); prop2.setDeprecated(true); type.getMembers().add(prop2); { Method method5 = TypeInfoModelFactory.eINSTANCE .createMethod(); method5.setName("run"); method5.setDescription("description for run(language,code)"); Parameter p = TypeInfoModelFactory.eINSTANCE .createParameter(); p.setName("language"); p.setType(getTypeRef(context, ITypeNames.STRING)); method5.getParameters().add(p); p = TypeInfoModelFactory.eINSTANCE.createParameter(); p.setName("code"); p.setType(getTypeRef(context, ITypeNames.STRING)); method5.getParameters().add(p); type.getMembers().add(method5); } { Method method3 = TypeInfoModelFactory.eINSTANCE .createMethod(); method3.setName("run"); method3.setDescription("description for run()"); type.getMembers().add(method3); } { Method method4 = TypeInfoModelFactory.eINSTANCE .createMethod(); method4.setName("run"); method4.setDescription("description for run(code)"); Parameter p = TypeInfoModelFactory.eINSTANCE .createParameter(); p.setName("code"); p.setType(getTypeRef(context, ITypeNames.STRING)); method4.getParameters().add(p); type.getMembers().add(method4); } return addType(CACHE_BUCKET, type); } else if (TYPE_RESPONSE.equals(typeName)) { Type type = TypeInfoModelFactory.eINSTANCE.createType(); type.setName(typeName); type.setKind(TypeKind.JAVA); Property prop1 = TypeInfoModelFactory.eINSTANCE .createProperty(); prop1.setName("status"); prop1.setType(getTypeRef(context, ITypeNames.NUMBER)); type.getMembers().add(prop1); Property prop2 = TypeInfoModelFactory.eINSTANCE .createProperty(); prop2.setName("service"); prop2.setType(getTypeRef(context, TYPE_SERVICE)); type.getMembers().add(prop2); return addType(CACHE_BUCKET, type); } else if ("ArrayTest".equals(typeName)) { Type type = TypeInfoModelFactory.eINSTANCE.createType(); type.setName(typeName); type.setKind(TypeKind.JAVA); Method method1 = TypeInfoModelFactory.eINSTANCE.createMethod(); method1.setName("execute"); method1.setType(TypeUtil.arrayOf("ArrayTest")); type.getMembers().add(method1); return addType(CACHE_BUCKET, type); } else return null; } }; private static final String CACHE_BUCKET = "tests"; public Type getType(ITypeInfoContext context, TypeMode mode, String typeName) { final Type cached = CACHE.findType("", typeName); if (cached != null) { return cached; } else if (TYPE_SERVICE2.equals(typeName)) { Type type = TypeInfoModelFactory.eINSTANCE.createType(); type.setName(typeName); type.setKind(TypeKind.JAVA); type.setDeprecated(true); Method method1 = TypeInfoModelFactory.eINSTANCE.createMethod(); method1.setName("execute"); method1.setType(context.getTypeRef(TYPE_RESPONSE + "Garbage")); type.getMembers().add(method1); Property prop1 = TypeInfoModelFactory.eINSTANCE.createProperty(); prop1.setName("name"); prop1.setType(TypeUtil.ref(ITypeNames.STRING)); type.getMembers().add(prop1); return type; } else if (TYPE_EXAMPLE_FORMS.equals(typeName)) { Type type = TypeInfoModelFactory.eINSTANCE.createType(); type.setName(typeName); type.setKind(TypeKind.JAVA); Property prop1 = TypeInfoModelFactory.eINSTANCE.createProperty(); prop1.setName("service"); prop1.setType(context.getTypeRef(TYPE_SERVICE)); type.getMembers().add(prop1); Property prop2 = TypeInfoModelFactory.eINSTANCE.createProperty(); prop2.setName("deprecatedName"); prop2.setType(TypeUtil.ref(ITypeNames.STRING)); prop2.setDeprecated(true); type.getMembers().add(prop2); Method method = TypeInfoModelFactory.eINSTANCE.createMethod(); method.setName("anyReturn"); method.setType( TypeInfoModelFactory.eINSTANCE.createAnyType()); type.getMembers().add(method); return type; } else if (TYPE_WITH_COLLECTION.equals(typeName)) { Type type = TypeInfoModelFactory.eINSTANCE.createType(); type.setName(typeName); type.setKind(TypeKind.JAVA); Property prop1 = TypeInfoModelFactory.eINSTANCE.createProperty(); prop1.setName("service"); prop1.setType(context.getTypeRef(TYPE_SERVICE)); type.getMembers().add(prop1); final Script script = new JavaScriptParser() .parse(new ModuleSource( "/** @return {Array<String>}*/function test() { return new Array();}"), null); if (script != null) { TypeInferencer2 inferencer = new TypeInferencer2(); inferencer.doInferencing(script); type.setAttribute(ExampleElementResolver.MEMBER_VALUE, inferencer.getCollection()); } return type; } else if (TYPE_GENERIC_ARRAY_METHOD.equals(typeName)) { Type type = TypeInfoModelFactory.eINSTANCE.createType(); type.setName(typeName); type.setKind(TypeKind.JAVA); Property property = TypeInfoModelFactory.eINSTANCE.createProperty(); property.setName("genericArrayProperty"); property.setType(TypeUtil.arrayOf(TypeUtil.ref(ITypeNames.STRING))); type.getMembers().add(property); Method method1 = TypeInfoModelFactory.eINSTANCE.createMethod(); method1.setName("execute"); method1.setType(TypeUtil.arrayOf(TypeUtil.ref(ITypeNames.STRING))); type.getMembers().add(method1); return type; } else if ("WithUntypedProperty".equals(typeName)) { final Type type = TypeInfoModelFactory.eINSTANCE.createType(); type.setName(typeName); final Property untyped = TypeInfoModelFactory.eINSTANCE .createProperty(); untyped.setName("untyped"); untyped.setDeprecated(true); type.getMembers().add(untyped); return type; } else if (typeName.startsWith("Packages.")) { String name = typeName.substring("Packages.".length()); try { Class<?> clz = Class.forName(name, false, Thread .currentThread().getContextClassLoader()); return getClassType(clz, name, context); } catch (ClassNotFoundException e) { } } return null; } private static Type getClassType(Class<?> clz, String name, ITypeInfoContext context) { Type type = TypeInfoModelFactory.eINSTANCE.createType(); type.setName(name); type.setKind(TypeKind.JAVA); java.lang.reflect.Method[] methods = clz.getMethods(); Field[] fields = clz.getFields(); EList<Member> members = type.getMembers(); for (Field field : fields) { Property property = TypeInfoModelFactory.eINSTANCE.createProperty(); property.setName(field.getName()); Class<?> fieldType = field.getType(); if (fieldType != null) property.setType(TypeUtil.ref(context.getType("Packages." + fieldType.getName()))); if (Modifier.isStatic(field.getModifiers())) { property.setStatic(true); } members.add(property); } for (java.lang.reflect.Method method : methods) { org.eclipse.dltk.javascript.typeinfo.model.Method m = TypeInfoModelFactory.eINSTANCE .createMethod(); m.setName(method.getName()); Class<?> methodType = method.getReturnType(); if (methodType != null) m.setType(TypeUtil.ref(context.getType("Packages." + methodType.getName()))); EList<Parameter> parameters = m.getParameters(); Class<?>[] parameterTypes = method.getParameterTypes(); for (int i = 0; i < parameterTypes.length; i++) { Parameter parameter = TypeInfoModelFactory.eINSTANCE .createParameter(); parameter.setName(parameterTypes[i].getSimpleName() + " arg" + i); parameter.setType(TypeUtil.ref(context.getType("Packages." + parameterTypes[i].getName()))); parameters.add(parameter); } if (Modifier.isStatic(method.getModifiers())) { m.setStatic(true); } members.add(m); } return type; } public Set<String> listTypes(ITypeInfoContext context, TypeMode mode, String prefix) { final Set<String> result = new HashSet<String>(); final String[] names = new String[] { TYPE_SERVICE, TYPE_SERVICE2, TYPE_RESPONSE, TYPE_EXAMPLE_FORMS, TYPE_GENERIC_ARRAY_METHOD }; for (String name : names) { if (CharOperation.prefixEquals(prefix, name)) { result.add(name); } } return result; } }