Ejemplo n.º 1
0
        public static void cloneTypes(Iterable <TypeInfo> types, Library targetTypeSystem)
        {
            var t0 = System.nanoTime();

            foreach (var type in types)
            {
                defineType(type, targetTypeSystem, null);
            }
            foreach (var type in types)
            {
                declareType(type, targetTypeSystem, (TypeBuilder)targetTypeSystem.getType(type.FullName), new Scope <String, TypeInfo>());
            }

            Environment.trace(targetTypeSystem, types.count() + " types cloned in " + ((System.nanoTime() - t0) / 1e6) + "ms");
        }
Ejemplo n.º 2
0
        static void declareGenericTypeBindings(GenericParameterBindings genericsScope, Iterable <TypeInfo> keys, Iterable <TypeInfo> values)
        {
            if (keys.count() != values.count())
            {
                throw new IllegalStateException();
            }
            var it1 = keys.iterator();
            var it2 = values.iterator();

            while (it1.hasNext())
            {
                var t1 = it1.next();
                var t2 = it2.next();
                if (t1.IsGenericParameter)
                {
                    genericsScope.declareBinding(t1, t2);
                }
            }
        }
 private static String[] getTypeNames(Iterable<TypeInfo> types) {
     if (types.any()) {
         String[] result = new String[types.count()];
         int i = 0;
         foreach (var t in types) {
             result[i++] = t.FullName;
         }
         return result;
     } else {
         return null;
     }
 }
Ejemplo n.º 4
0
        private void replaceCref(Element element, bool exception, Iterable <MemberInfo> members, String suffix, String arguments)
        {
            if (members.count() > 1 && !members.all(p => p.MemberKind == MemberKind.Method))
            {
                context.addWarning(CompileErrorId.UnresolvedCref, node, element.getAttribute("cref"));
                element.setAttribute("cref", "!" + element.getAttribute("cref"));
                return;
            }
            var member = members.first();

            switch (member.MemberKind)
            {
            case Type:
                replaceCref(element, exception, member.Type, suffix, arguments);
                break;

            case Field:
                if (exception)
                {
                    context.addWarning(CompileErrorId.ExpectedExceptionInCref, node, element.getAttribute("cref"));
                    element.setAttribute("cref", "!" + element.getAttribute("cref"));
                    return;
                }
                if (suffix != null || arguments != null)
                {
                    context.addWarning(CompileErrorId.UnresolvedCref, node, element.getAttribute("cref"));
                    element.setAttribute("cref", "!" + element.getAttribute("cref"));
                    return;
                }
                element.setAttribute("cref", getIdString(member.Field));
                break;

            case Property:
                if (exception)
                {
                    context.addWarning(CompileErrorId.ExpectedExceptionInCref, node, element.getAttribute("cref"));
                    element.setAttribute("cref", "!" + element.getAttribute("cref"));
                    return;
                }
                if (suffix != null || arguments != null)
                {
                    context.addWarning(CompileErrorId.UnresolvedCref, node, element.getAttribute("cref"));
                    element.setAttribute("cref", "!" + element.getAttribute("cref"));
                    return;
                }
                element.setAttribute("cref", getIdString(member.GetAccessor ?? member.SetAccessor));
                break;

            case Method:
                if (!exception && suffix == null)
                {
                    if (arguments == null && members.count() == 1)
                    {
                        element.setAttribute("cref", getIdString(member.Method));
                        return;
                    }
                    else if (arguments != null && arguments.endsWith(")"))
                    {
                        var args = new ArrayList <TypeInfo>();
                        if (arguments.length() > 2)
                        {
                            arguments = arguments.substring(1, arguments.length() - 1);
                            int idx;
                            while ((idx = arguments.indexOf(',')) != -1)
                            {
                                var name = arguments.substring(0, idx);
                                arguments = arguments.substring(idx + 1);
                                var type = getType(name);
                                if (type == null)
                                {
                                    goto failed;
                                }
                                args.add(type);
                            }
                            if (arguments.length() == 0)
                            {
                                goto failed;
                            }
                            var type = getType(arguments);
                            if (type == null)
                            {
                                goto failed;
                            }
                            args.add(type);
                        }
                        foreach (var m in members)
                        {
                            if (m.Method.Parameters.select(p => p.Type).sequenceEqual(args))
                            {
                                element.setAttribute("cref", getIdString(m.Method));
                                return;
                            }
                        }
                    }
                }
failed:
                context.addWarning(CompileErrorId.UnresolvedCref, node, element.getAttribute("cref"));
                element.setAttribute("cref", "!" + element.getAttribute("cref"));
                break;

            default:
                break;
            }
        }
 private void replaceCref(Element element, bool exception, Iterable<MemberInfo> members, String suffix, String arguments) {
     if (members.count() > 1 && !members.all(p => p.MemberKind == MemberKind.Method)) {
         context.addWarning(CompileErrorId.UnresolvedCref, node, element.getAttribute("cref"));
         element.setAttribute("cref", "!" + element.getAttribute("cref"));
         return;
     }
     var member = members.first();
     switch (member.MemberKind) {
     case Type:
         replaceCref(element, exception, member.Type, suffix, arguments);
         break;
     case Field:
         if (exception) {
             context.addWarning(CompileErrorId.ExpectedExceptionInCref, node, element.getAttribute("cref"));
             element.setAttribute("cref", "!" + element.getAttribute("cref"));
             return;
         }
         if (suffix != null || arguments != null) {
             context.addWarning(CompileErrorId.UnresolvedCref, node, element.getAttribute("cref"));
             element.setAttribute("cref", "!" + element.getAttribute("cref"));
             return;
         }
         element.setAttribute("cref", getIdString(member.Field));
         break;
     
     case Property:
         if (exception) {
             context.addWarning(CompileErrorId.ExpectedExceptionInCref, node, element.getAttribute("cref"));
             element.setAttribute("cref", "!" + element.getAttribute("cref"));
             return;
         }
         if (suffix != null || arguments != null) {
             context.addWarning(CompileErrorId.UnresolvedCref, node, element.getAttribute("cref"));
             element.setAttribute("cref", "!" + element.getAttribute("cref"));
             return;
         }
         element.setAttribute("cref", getIdString(member.GetAccessor ?? member.SetAccessor));
         break;
     
     case Method:
         if (!exception && suffix == null) {
             if (arguments == null && members.count() == 1) {
                 element.setAttribute("cref", getIdString(member.Method));
                 return;
             } else if (arguments != null && arguments.endsWith(")")) {
                 var args = new ArrayList<TypeInfo>();
                 if (arguments.length() > 2) {
                     arguments = arguments.substring(1, arguments.length() - 1);
                     int idx;
                     while ((idx = arguments.indexOf(',')) != -1) {
                         var name = arguments.substring(0, idx);
                         arguments = arguments.substring(idx + 1);
                         var type = getType(name);
                         if (type == null) {
                             goto failed;
                         }
                         args.add(type);
                     }
                     if (arguments.length() == 0) {
                         goto failed;
                     }
                     var type = getType(arguments);
                     if (type == null) {
                         goto failed;
                     }
                     args.add(type);
                 }
                 foreach (var m in members) {
                     if (m.Method.Parameters.select(p => p.Type).sequenceEqual(args)) {
                         element.setAttribute("cref", getIdString(m.Method));
                         return;
                     }
                 }
             }
         }
     failed:
         context.addWarning(CompileErrorId.UnresolvedCref, node, element.getAttribute("cref"));
         element.setAttribute("cref", "!" + element.getAttribute("cref"));
         break;
         
     default:
         break;
     }
 }
Ejemplo n.º 6
0
        private static Iterable <MemberInfo> getMembers(Library typeSystem, TypeInfo type, String name,
                                                        Iterable <TypeInfo> typeArguments, bool useCache, LookupContext context)
        {
            var nTypeArgs = typeArguments.count();

            foreach (var mi in (useCache) ? getCachedMembers(typeSystem, type, name) : getMembers(typeSystem, type, name))
            {
                switch (mi.MemberKind)
                {
                case Field:
                    if (nTypeArgs == 0 && context.lookupField)
                    {
                        context.lookupField = false;
                        yield return(mi);
                    }
                    break;

                case Property:
                    if (nTypeArgs == 0 && context.lookupProperty)
                    {
                        context.lookupProperty = false;
                        yield return(mi);
                    }
                    break;

                case Method:
                    if (nTypeArgs > 0)
                    {
                        if (nTypeArgs == mi.Method.GenericArguments.count())
                        {
                            yield return(MemberInfo.getInfo(typeSystem.getGenericMethod(mi.Method, typeArguments)));
                        }
                    }
                    else
                    {
                        yield return(mi);
                    }
                    break;

                case Type:
                    if (context.lookupClass)
                    {
                        context.lookupClass = false;
                        if (nTypeArgs > 0)
                        {
                            if (nTypeArgs == mi.Type.GenericArguments.count())
                            {
                                yield return(mi);
                            }
                        }
                        else
                        {
                            if (mi.MemberKind == MemberKind.Type && mi.Type.GenericArguments.count() > 0)
                            {
                                mi = MemberInfo.getInfo(mi.Type.RawType);
                            }
                            yield return(mi);
                        }
                    }
                    break;
                }
            }
        }
Ejemplo n.º 7
0
        private SourceCompilerResults compileCore(IProgressMonitor monitor)
        {
            var t0 = System.nanoTime();

            var results      = new SourceCompilerResults();
            var hasErrors    = false;
            var errorManager = new CodeErrorManager();
            var allFiles     = parameters.AllFiles;
            Iterable <IFile> filesToCompile = null;

            try {
                monitor.beginTask("", 11);

                var deletedFiles = parameters.FilesToCompile
                                   .select(p => allFiles.getResource(p))
                                   .where (p => p == null || !p.exists())
                                   .select(p => allFiles.getProjectRelativeName(p)).toSet();
                var typesToCopy = Query.empty <TypeInfo>();

                // Get the files to compile
                if (parameters.FullBuild)
                {
                    filesToCompile = allFiles.getAllResources().where (p => p.exists()).toList();
                }
                else
                {
                    bool filteringDone    = false;
                    var  referencingFiles = parameters.getDependencyInfo().getAllReferencingFiles(parameters.getFilesToCompile());
                    if (parameters.ProgressiveBuild && deletedFiles.isEmpty())
                    {
                        var referencedFiles = parameters.getDependencyInfo().getAllReferencedFiles(parameters.getFilesToCompile());
                        referencedFiles = referencedFiles.except(parameters.getFilesToCompile());
                        referencedFiles = referencedFiles.intersect(referencingFiles);

                        // Progressive build only if referenced and referencing files do not intersect
                        if (!referencedFiles.any())
                        {
                            filesToCompile = parameters.FilesToCompile.select(p => allFiles.getResource(p)).where (p => p.exists()).toList();
                            filteringDone  = true;
                        }
                    }
                    if (!filteringDone)
                    {
                        // Incremental build with dependencies
                        filesToCompile = referencingFiles.select(p => allFiles.getResource(p)).where (p => p.exists()).toList();
                    }

                    var filesToKeep = allFiles.getAllProjectRelativeNames().except(referencingFiles);
                    typesToCopy = filesToKeep.selectMany(p => parameters.DependencyInfo.getFileContents(p))
                                  .where (p => p.indexOf('$') == -1).select(p => parameters.TypeSystem.getType(p));

                    Environment.trace(this, "keeping " + filesToKeep.count() + " files");
                    Environment.trace(this, "ignoring " +
                                      (allFiles.getAllResources().count() - filesToCompile.count() - filesToKeep.count()) + " files");
                }
                Environment.trace(this, "compiling " + filesToCompile.count() + " files");
                monitor.worked(1);
                if (monitor.isCanceled())
                {
                    throw new InterruptedException();
                }

                var compilationUnits = new HashMap <String, CompilationUnitNode>();

                // Parsing
                foreach (var file in filesToCompile)
                {
                    var text = getText(file);
                    if (text != null)
                    {
                        parse(file, text, errorManager, compilationUnits);
                    }
                }
                monitor.worked(1);
                if (monitor.isCanceled())
                {
                    throw new InterruptedException();
                }

                // Compiling
                var t1 = System.nanoTime();

                var typeSystem = new Library(parameters.ClassPath);
                JvmTypeSystemHelper.cloneTypes(typesToCopy, typeSystem);

                var annotatedTypeSystem = new Library(new[] { Environment.getLibraryPath("stabal.jar") }, typeSystem);

                var cparams = new CompilerParameters();
                cparams.TypeSystem          = typeSystem;
                cparams.AnnotatedTypeSystem = annotatedTypeSystem;
                cparams.GenerateClassFiles  = parameters.GenerateClassFiles;
                cparams.ProgressTracker     = new CompilationProgressTracker(monitor);

                var cunits   = compilationUnits.values().toArray(new CompilationUnitNode[compilationUnits.size()]);
                var cresults = new StabCompiler().compileFromCompilationUnits(cparams, cunits);

                Environment.trace(this, "compilation of " + sizeof(cunits) + " files done in " + ((System.nanoTime() - t1) / 1e6) + "ms");

                foreach (var error in cresults.Errors)
                {
                    if (error.Level == 0)
                    {
                        hasErrors = true;
                    }
                    results.CodeErrors.add(error);
                    Environment.trace(this, "error (" + error.Line + ", " + error.Column + ") " + error.Filename + ": " + error.Message);
                }

                if (!hasErrors)
                {
                    var dependencyInfo = new DependencyInfo();
                    results.DependencyInfo = dependencyInfo;
                    var allTypes = new HashSet <String>();

                    // Copy informations from unbuilt files
                    if (parameters.DependencyInfo != null)
                    {
                        var unbuiltFiles = allFiles.getAllProjectRelativeNames();
                        unbuiltFiles = unbuiltFiles.except(filesToCompile.select(p => allFiles.getProjectRelativeName(p)));
                        unbuiltFiles = unbuiltFiles.except(deletedFiles);
                        foreach (var file in unbuiltFiles)
                        {
                            foreach (var type in parameters.DependencyInfo.getFileContents(file))
                            {
                                allTypes.add(type);
                                dependencyInfo.addFileToTypeRelation(file, type);
                                foreach (var refType in parameters.DependencyInfo.getReferencedTypes(type))
                                {
                                    dependencyInfo.addTypeToTypeRelation(type, refType);
                                }
                            }
                        }
                    }

                    // Collect the types and update the dependencies.
                    var typeMembers = new HashMap <IFile, Iterable <TypeMemberNode> >();
                    foreach (var file in filesToCompile)
                    {
                        var fileName        = allFiles.getProjectRelativeName(file);
                        var compilationUnit = compilationUnits[fileName];
                        if (compilationUnit == null)
                        {
                            continue;
                        }
                        var members = SyntaxTreeHelper.getTypeMembers(compilationUnit);
                        typeMembers.put(file, members);
                        foreach (var member in members)
                        {
                            var typeName = member.getUserData(typeof(TypeInfo)).FullName;
                            dependencyInfo.addFileToTypeRelation(fileName, typeName);
                            allTypes.add(typeName);
                        }
                    }

                    if (parameters.DependencyInfo != null)
                    {
                        // Copy the types ignored by this compilation
                        var missingTypes = new HashSet <TypeInfo>();
                        foreach (var t in allTypes.where (p => p.indexOf('$') == -1 && !typeSystem.typeExists(p)))
                        {
                            if (hasErrors = !parameters.DependencyInfo.getReferencedTypes(t).all(p => allTypes.contains(p)))
                            {
                                Environment.trace(this, "Incremental build failed: a type was deleted");
                                break;
                            }
                            missingTypes.add(parameters.TypeSystem.getType(t));
                        }
                        if (!hasErrors)
                        {
                            JvmTypeSystemHelper.cloneTypes(missingTypes, typeSystem);
                        }
                    }

                    if (!hasErrors)
                    {
                        // Compute the dependencies in the compiled files
                        foreach (var member in filesToCompile.select(p => typeMembers[p]).where (p => p != null).selectMany(p => p))
                        {
                            foreach (var t in SyntaxTreeHelper.getTypeMemberDependencies(member)
                                     .intersect(allTypes.select(p => JvmTypeSystemHelper.getType(typeSystem, p))))
                            {
                                dependencyInfo.addTypeToTypeRelation(member.getUserData(typeof(TypeInfo)).FullName, t.FullName);
                            }
                        }

                        results.TypeSystem          = typeSystem;
                        results.AnnotatedTypeSystem = annotatedTypeSystem;
                        foreach (var e in compilationUnits.entrySet())
                        {
                            results.CompilationUnits[e.Key] = e.Value;
                        }
                        foreach (var e in cresults.ClassFiles.entrySet())
                        {
                            results.ClassFiles[e.Key] = e.Value;
                        }
                    }
                }
                monitor.worked(1);
            } catch (CodeErrorException e) {
                monitor.worked(10);
            } catch (TypeLoadException e) {
                results.MissingType = e.TypeName;
                hasErrors           = true;
                monitor.worked(6);
            } finally {
                monitor.done();
            }

            foreach (var file in filesToCompile)
            {
                results.CompiledFiles.add(allFiles.getProjectRelativeName(file));
            }
            foreach (var error in errorManager.Errors)
            {
                if (error.Level == 0)
                {
                    hasErrors = true;
                }
                results.CodeErrors.add(error);
                Environment.trace(this, "error (" + error.Line + ", " + error.Column + ") " + error.Filename + ": " + error.Message);
            }
            results.Failed = hasErrors;

            Environment.trace(this, "compilation done in " + ((System.nanoTime() - t0) / 1e6) + "ms");
            return(results);
        }
        private static Iterable<MemberInfo> getMembers(Library typeSystem, TypeInfo type, String name,
            Iterable<TypeInfo> typeArguments, bool useCache, LookupContext context) {
            var nTypeArgs = typeArguments.count();
            foreach (var mi in (useCache) ? getCachedMembers(typeSystem, type, name) : getMembers(typeSystem, type, name)) {
                switch (mi.MemberKind) {
                case Field:
                    if (nTypeArgs == 0 && context.lookupField) {
                        context.lookupField = false;
                        yield return mi;
                    }
                    break;
                    
                case Property:
                    if (nTypeArgs == 0  && context.lookupProperty) {
                        context.lookupProperty = false;
                        yield return mi;
                    }
                    break;
                    
                case Method:
                    if (nTypeArgs > 0) {
                        if (nTypeArgs == mi.Method.GenericArguments.count()) {
                            yield return MemberInfo.getInfo(typeSystem.getGenericMethod(mi.Method, typeArguments));
                        }
                    } else {
                        yield return mi;
                    }
                    break;

                case Type:
                    if (context.lookupClass) {
                        context.lookupClass = false;
                        if (nTypeArgs > 0) {
                            if (nTypeArgs == mi.Type.GenericArguments.count()) {
                                yield return mi;
                            }
                        } else {
                            if (mi.MemberKind == MemberKind.Type && mi.Type.GenericArguments.count() > 0) {
                                mi = MemberInfo.getInfo(mi.Type.RawType);
                            }
                            yield return mi;
                        }
                    }
                    break;
                }
            }
        }
		public static void cloneTypes(Iterable<TypeInfo> types, Library targetTypeSystem) {
			var t0 = System.nanoTime();
			
			foreach (var type in types) {
				defineType(type, targetTypeSystem, null);
			}
			foreach (var type in types) {
				declareType(type, targetTypeSystem, (TypeBuilder)targetTypeSystem.getType(type.FullName), new Scope<String, TypeInfo>());
			}
			
			Environment.trace(targetTypeSystem, types.count() + " types cloned in " + ((System.nanoTime() - t0) / 1e6) + "ms");
		}
        MethodInfo resolveMethod(Iterable<MethodInfo> methods, Iterable<ExpressionNode> arguments,
                TypeInfo returnType, bool extensionMethods) {
            var candidates = new ArrayList<CandidateMethodInfo>();
            var hasLambda = false;
            
            foreach (var method in methods) {
                var parameterCount = method.Parameters.count();
                var argumentCount = arguments.count();
                if (method.IsVarargs) {
                    if (argumentCount < parameterCount - 1) {
                        continue;
                    }
                } else if (argumentCount != parameterCount) {
                    continue;
                }
                var fixedArgumentCount = (method.IsVarargs) ? parameterCount - 1 : parameterCount;
                var isCompatible = true;
                var parameterTypes = new TypeInfo[argumentCount];
                var expandedForm = method.IsVarargs;

                if (!method.IsClosed) {
                    var typeVariableInfos = new HashMap<TypeInfo, TypeVariableInfo>();
                    foreach (var t in method.GenericArguments) {
                        typeVariableInfos[t] = new TypeVariableInfo(t);
                    }
                    
                    // Inference phase 1
                    var nit = arguments.iterator();
                    var pit = method.Parameters.iterator();
                    bool closedParams = true;
                    for (int i = 0; i < fixedArgumentCount; i++) {
                        var paramType = pit.next().Type;
                        var argNode = nit.next();
                        if (paramType.IsClosed) {
                            if (!isArgumentCompatible(argNode, paramType)) {
                                goto continueLookup;
                            }
                        } else {
                            closedParams = false;
                            if (argNode.ExpressionKind == ExpressionKind.Lambda) {
                                hasLambda = true;
                                makeExplicitParameterTypeInference(argNode, paramType, typeVariableInfos);
                            } else {
                                var argInfo = argNode.getUserData(typeof(ExpressionInfo));
                                if (argInfo == null) {
                                    continue;
                                }
                                if (BytecodeHelper.isDelegateType(paramType) || BytecodeHelper.isExpressionTreeType(paramType)) {
                                    makeExplicitParameterTypeInference(argNode, paramType, typeVariableInfos);
                                } else {
                                    ValidationHelper.getType(context, argNode);
                                    makeOutputTypeInference(argNode, paramType, typeVariableInfos);
                                }
                            }
                        }
                    }
                    if (method.IsVarargs) {
                        var paramType = pit.next().Type.ElementType;
                        var isClosedParam = paramType.IsClosed;
                        var first = true;
                        while (nit.hasNext()) {
                            var argNode = nit.next();
                            if (isClosedParam) {
                                switch (isVarargCompatible(argNode, paramType, first)) {
                                case False:
                                    goto continueLookup;
                                case True:
                                    expandedForm = false;
                                    if (nit.hasNext()) {
                                        goto continueLookup;
                                    }
                                    break;
                                }
                            } else {
                                closedParams = false;
                                if (argNode.ExpressionKind == ExpressionKind.Lambda) {
                                    hasLambda = true;
                                    makeExplicitParameterTypeInference(argNode, paramType, typeVariableInfos);
                                } else {
                                    var argInfo = argNode.getUserData(typeof(ExpressionInfo));
                                    if (argInfo == null) {
                                        continue;
                                    }
                                    if (BytecodeHelper.isDelegateType(paramType) || BytecodeHelper.isExpressionTreeType(paramType)) {
                                        makeExplicitParameterTypeInference(argNode, paramType, typeVariableInfos);
                                    } else if (paramType != ValidationHelper.getType(context, argNode)
                                            && !ValidationHelper.isAssignable(context, paramType, argNode)
                                            && first
                                            && ValidationHelper.isAssignable(context, paramType.getArrayType(), argNode)) {
                                        expandedForm = false;
                                        makeOutputTypeInference(argNode, paramType.getArrayType(), typeVariableInfos);
                                    } else {
                                        makeOutputTypeInference(argNode, paramType, typeVariableInfos);
                                    }
                                }
                            }
                            first = false;
                        }
                    }

                    if (closedParams && returnType != null && returnType != context.TypeSystem.VoidType) {
                        makeLowerBoundInference(returnType, method.ReturnType, typeVariableInfos);
                    }
                    
                    // Inference phase 2
                    for (;;) {
                        var varFixed = false;
                        var hasUnfixed = false;
                        foreach (var e in typeVariableInfos.entrySet()) {
                            if (e.Value.fixedType != null) {
                                continue;
                            }
                            if (!containsUnfixedVariables(e.getValue().dependencies, typeVariableInfos)) {
                                if (fixTypeVariable(e.getValue())) {
                                    varFixed = true;
                                    continue;
                                }
                            }
                            hasUnfixed = true;
                        }
                        if (!varFixed) {
                            varFixed = false;
                            foreach (var e in typeVariableInfos.entrySet()) {
                                if (e.Value.fixedType != null) {
                                    continue;
                                }
                                if (hasUnfixedTypeVariablesDependingOn(e.Key, typeVariableInfos, new HashSet<TypeInfo>())) {
                                    if (!e.Value.bounds.isEmpty()) {
                                        if (fixTypeVariable(e.Value)) {
                                            varFixed = true;
                                            continue;
                                        }
                                    }
                                }
                                hasUnfixed = true;
                            }
                        }
                        if (!varFixed && hasUnfixed) {
                            goto continueLookup;
                        }
                        if (!hasUnfixed) {
                            break;
                        }
                        var mit = method.Parameters.iterator();
                        TypeInfo paramType = null;
                        foreach (var e in arguments) {
                            if (mit.hasNext()) {
                                paramType = mit.next().Type;
                            }
                            if (e.ExpressionKind != ExpressionKind.Lambda) {
                                if (!BytecodeHelper.isDelegateType(paramType) && !BytecodeHelper.isExpressionTreeType(paramType)) {
                                    continue;
                                }
                            }
                            var m = getInvokeMethod(paramType);
                            if (hasUnfixedTypeVariables(m.ReturnType, typeVariableInfos)) {
                                hasUnfixed = false;
                                foreach (var p in m.Parameters) {
                                    if (hasUnfixedTypeVariables(p.Type, typeVariableInfos)) {
                                        hasUnfixed = true;
                                        break;
                                    }
                                }
                                if (!hasUnfixed) {
                                    makeOutputTypeInference(e, paramType, typeVariableInfos);
                                }
                            }
                        }
                    }

                    var typeArguments = new ArrayList<TypeInfo>();
                    foreach (var t in method.GenericArguments) {
                        typeArguments.add(typeVariableInfos[t].fixedType);
                    }
                    method = context.TypeSystem.getGenericMethod(method, typeArguments);
                }

                var it1 = arguments.iterator();
                var it2 = method.Parameters.iterator();
                int i;
                for (i = 0; i < fixedArgumentCount; i++) {
                    var argNode = it1.next();
                    var paramType = it2.next().Type;
                    parameterTypes[i] = paramType;
                    if (!isArgumentCompatible(argNode, paramType)) {
                        isCompatible = false;
                        break;
                    } else if (argNode.ExpressionKind == ExpressionKind.Lambda) {
                        hasLambda = true;
                    }
                }
                if (isCompatible && method.IsVarargs) {
                    var paramType = it2.next().Type.ElementType;
                    var first = true;
                    while (isCompatible && it1.hasNext()) {
                        var argNode = it1.next();
                        parameterTypes[i++] = paramType;
                        switch (isVarargCompatible(argNode, paramType, first)) {
                        case False:
                            isCompatible = false;
                            break;
                        case True:
                            expandedForm = false;
                            if (it1.hasNext()) {
                                isCompatible = false;
                                break;
                            } else if (argNode.ExpressionKind == ExpressionKind.Lambda) {
                                hasLambda = true;
                            }
                            break;
                        }
                        first = false;
                    }
                }
                if (isCompatible) {
                    candidates.add(new CandidateMethodInfo(method, parameterTypes, arguments, expandedForm));
                }
            continueLookup:
                ;
            }

            if (candidates.size() == 0) {
                return null;
            }

            CandidateMethodInfo result;
            if (candidates.size() > 1) {
                result = resolveOverloading(candidates, extensionMethods);
                if (result == null) {
                    return null;
                }
            } else {
                result = candidates[0];
            }
            if (hasLambda) {
                int parameterCount = result.method.Parameters.count();
                int argumentCount = arguments.count();
                int fixedArgumentCount = (result.method.IsVarargs) ? parameterCount - 1 : parameterCount;

                var parameterTypes = new TypeInfo[argumentCount];
                var pit = result.method.getParameters().iterator();
                int i;
                for (i = 0; i < fixedArgumentCount; i++) {
                    parameterTypes[i] = pit.next().Type;
                }
                if (result.method.IsVarargs) {
                    if (result.expandedForm) {
                        var paramType = pit.next().Type.ElementType;
                        while (i < argumentCount) {
                            parameterTypes[i++] = paramType;
                        }
                    } else {
                        parameterTypes[i] = pit.next().Type;
                    }
                }
                i = 0;
                foreach (var argNode in arguments) {
					expressionValidator.handleExpression(argNode, parameterTypes[i], true);
                    i++;
                }
            }
            return result.method;
        }