Ejemplo n.º 1
0
        public void AddAnnotation(IRewriteSession rewriteSession, IdentifierReference reference, IAnnotation annotationInfo, IReadOnlyList <string> values = null)
        {
            var annotationValues = values ?? new List <string>();

            if (reference == null)
            {
                _logger.Warn("Tried to add an annotation to an identifier reference that is null.");
                _logger.Trace($"Tried to add annotation {annotationInfo.Name} with values {AnnotationValuesText(annotationValues)} to an identifier reference that is null.");
                return;
            }

            if (!annotationInfo.Target.HasFlag(AnnotationTarget.Identifier))
            {
                _logger.Warn("Tried to add an annotation without the identifier reference annotation flag to an identifier reference.");
                _logger.Trace($"Tried to add annotation {annotationInfo.Name} with values {AnnotationValuesText(annotationValues)} to the identifier reference to {reference.Declaration.QualifiedName} at {reference.Selection} in module {reference.QualifiedModuleName}.");
                return;
            }

            if (rewriteSession.TargetCodeKind != CodeKind.CodePaneCode)
            {
                _logger.Warn($"Tried to add an annotation to an identifier reference with a rewriter not suitable for annotations to references. (target code kind = {rewriteSession.TargetCodeKind})");
                _logger.Trace($"Tried to add annotation {annotationInfo.Name} with values {AnnotationValuesText(annotationValues)} to the the identifier reference {reference.IdentifierName} at {reference.Selection} in module {reference.QualifiedModuleName} using a rewriter not suitable for annotations.");
                return;
            }

            AddAnnotation(rewriteSession, new QualifiedContext(reference.QualifiedModuleName, reference.Context), annotationInfo, annotationValues);
        }
Ejemplo n.º 2
0
        protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder)
        {
            // prefilter to reduce search space
            if (reference.IsIgnoringInspectionResultFor(AnnotationName))
            {
                return(false);
            }

            var usageContext = UsageContext(reference);

            var setter = usageContext is VBAParser.LExprContext lexpr &&
                         lexpr.Parent is VBAParser.SetStmtContext
                ? lexpr.Parent
                : null;

            if (setter is null)
            {
                return(usageContext is VBAParser.MemberAccessExprContext ||
                       !(usageContext is VBAParser.CallStmtContext) &&
                       !ContextIsNothing(usageContext));
            }

            var assignedTo = AssignmentTarget(reference, finder, setter);

            return(assignedTo != null &&
                   IsUsedBeforeCheckingForNothing(assignedTo));
        }
        private void AddUnboundDefaultMemberReference(
            DictionaryAccessExpression expression,
            QualifiedModuleName module,
            Declaration scope,
            Declaration parent,
            bool isAssignmentTarget,
            bool hasExplicitLetStatement,
            bool isSetAssignment)
        {
            var callSiteContext = expression.DefaultMemberContext;
            var identifier      = expression.Context.GetText();
            var selection       = callSiteContext.GetSelection();
            var callee          = expression.ReferencedDeclaration;
            var reference       = new IdentifierReference(
                module,
                scope,
                parent,
                identifier,
                selection,
                callSiteContext,
                callee,
                isAssignmentTarget,
                hasExplicitLetStatement,
                FindIdentifierAnnotations(module, selection.StartLine),
                isSetAssignment,
                isIndexedDefaultMemberAccess: true,
                defaultMemberRecursionDepth: expression.DefaultMemberRecursionDepth);

            _declarationFinder.AddUnboundDefaultMemberAccess(reference);
        }
        private void AddFailedIndexedDefaultMemberReference(
            IndexExpression expression,
            QualifiedModuleName module,
            Declaration scope,
            Declaration parent,
            bool isAssignmentTarget,
            bool hasExplicitLetStatement,
            bool hasArguments)
        {
            var callSiteContext = expression.Context;
            var identifier      = callSiteContext.GetText();
            var selection       = callSiteContext.GetSelection();
            var callee          = expression.ReferencedDeclaration;
            var reference       = new IdentifierReference(
                module,
                scope,
                parent,
                identifier,
                selection,
                callSiteContext,
                callee,
                isAssignmentTarget,
                hasExplicitLetStatement,
                FindIdentifierAnnotations(module, selection.StartLine),
                false,
                isIndexedDefaultMemberAccess: hasArguments,
                isNonIndexedDefaultMemberAccess: !hasArguments,
                defaultMemberRecursionDepth: expression.DefaultMemberRecursionDepth);

            _declarationFinder.AddFailedIndexedDefaultMemberResolution(reference);
        }
Ejemplo n.º 5
0
        public static void ReplaceIdentifierReferenceName(this ICodeModule module, IdentifierReference identifierReference, string replacement)
        {
            var original = module.GetLines(identifierReference.Selection.StartLine, 1);
            var result   = ReplaceStringAtIndex(original, identifierReference.IdentifierName, replacement, identifierReference.Context.Start.Column);

            module.ReplaceLine(identifierReference.Selection.StartLine, result);
        }
Ejemplo n.º 6
0
        public static void Remove(this ICodeModule module, IdentifierReference target)
        {
            var parent = (ParserRuleContext)target.Context.Parent;

            if (target.IsAssignment)
            {
                // target is LHS of assignment; need to know if there's a procedure call in RHS
                var letStmt = parent as VBAParser.LetStmtContext;
                var setStmt = parent as VBAParser.SetStmtContext;

                string argList;
                if (HasProcedureCall(letStmt, out argList) || HasProcedureCall(setStmt, out argList))
                {
                    // need to remove LHS only; RHS expression may have side-effects
                    var original    = parent.GetText();
                    var replacement = ReplaceStringAtIndex(original, target.IdentifierName + " = ", string.Empty, 0);
                    if (argList != null)
                    {
                        var atIndex   = replacement.IndexOf(argList, StringComparison.OrdinalIgnoreCase);
                        var plainArgs = " " + argList.Substring(1, argList.Length - 2);
                        replacement = ReplaceStringAtIndex(replacement, argList, plainArgs, atIndex);
                    }
                    module.ReplaceLine(parent.Start.Line, replacement);
                    return;
                }
            }

            module.Remove(parent.GetSelection(), parent);
        }
        private void AddFailedProcedureCoercionReference(
            ProcedureCoercionExpression expression,
            QualifiedModuleName module,
            Declaration scope,
            Declaration parent)
        {
            var callSiteContext = expression.Context;
            var identifier      = callSiteContext.GetText();
            var selection       = callSiteContext.GetSelection();
            var callee          = expression.ReferencedDeclaration;
            var reference       = new IdentifierReference(
                module,
                scope,
                parent,
                identifier,
                selection,
                callSiteContext,
                callee,
                false,
                false,
                FindIdentifierAnnotations(module, selection.StartLine),
                false,
                isNonIndexedDefaultMemberAccess: true,
                defaultMemberRecursionDepth: expression.DefaultMemberRecursionDepth);

            _declarationFinder.AddFailedProcedureCoercionReference(reference);
        }
        protected override string ResultDescription(IdentifierReference reference, string assignedTypeName)
        {
            var declarationName  = reference.Declaration.IdentifierName;
            var variableTypeName = reference.Declaration.FullAsTypeName;

            return(string.Format(InspectionResults.SetAssignmentWithIncompatibleObjectTypeInspection, declarationName, variableTypeName, assignedTypeName));
        }
        protected override string ResultDescription(IdentifierReference failedCoercion)
        {
            var expression = failedCoercion.IdentifierName;
            var typeName   = failedCoercion.Declaration?.FullAsTypeName;

            return(string.Format(InspectionResults.ProcedureRequiredInspection, expression, typeName));
        }
        protected override string ResultDescription(IdentifierReference failedIndexedDefaultMemberAccess)
        {
            var expression = failedIndexedDefaultMemberAccess.IdentifierName;
            var typeName   = failedIndexedDefaultMemberAccess.Declaration?.FullAsTypeName;

            return(string.Format(InspectionResults.DefaultMemberRequiredInspection, expression, typeName));
        }
        private void MakeReferenceUnqualified(Declaration target, IdentifierReference reference, IModuleRewriter rewriter)
        {
            var memberAccessContext = reference.Context.GetAncestor <VBAParser.MemberAccessExprContext>();

            if (memberAccessContext == null)
            {
                return;
            }

            // member access might be to something unrelated to the rewritten target.
            // check we're not accidentally overwriting some other member-access who just happens to be a parent context
            if (memberAccessContext.unrestrictedIdentifier()?.GetText() != target.IdentifierName)
            {
                return;
            }
            var qualification = memberAccessContext.lExpression().GetText();

            if (!qualification.Equals(target.ComponentName, StringComparison.InvariantCultureIgnoreCase) &&
                !qualification.Equals(target.ProjectName, StringComparison.InvariantCultureIgnoreCase) &&
                !qualification.Equals($"{target.QualifiedModuleName.ProjectName}.{target.ComponentName}", StringComparison.InvariantCultureIgnoreCase))
            {
                return;
            }

            rewriter.Replace(memberAccessContext, reference.IdentifierName);
        }
        private bool IsCallStmt(IdentifierReference usage)
        {
            var callStmt = usage.Context.GetAncestor <VBAParser.CallStmtContext>();

            if (callStmt == null)
            {
                return(false);
            }

            var indexExpr = usage.Context.GetAncestor <VBAParser.IndexExprContext>();

            if (indexExpr != null)
            {
                var memberAccessStmt = usage.Context.GetAncestor <VBAParser.MemberAccessExprContext>();
                if (memberAccessStmt != null &&
                    callStmt.SourceInterval.ProperlyContains(memberAccessStmt.SourceInterval) &&
                    memberAccessStmt.SourceInterval.ProperlyContains(indexExpr.SourceInterval))
                {
                    return(false);
                }
            }

            var argumentList = CallStatement.GetArgumentList(callStmt);

            if (argumentList == null)
            {
                return(true);
            }
            return(!usage.Context.IsDescendentOf(argumentList));
        }
        protected override string ResultDescription(IdentifierReference reference)
        {
            var expression    = reference.IdentifierName;
            var defaultMember = reference.Declaration.QualifiedName.ToString();

            return(string.Format(InspectionResults.IndexedRecursiveDefaultMemberAccessInspection, expression, defaultMember));
        }
Ejemplo n.º 14
0
 protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder)
 {
     return(reference.IsNonIndexedDefaultMemberAccess &&
            !reference.IsProcedureCoercion &&
            !reference.IsInnerRecursiveDefaultMemberAccess &&
            !reference.IsIgnoringInspectionResultFor(AnnotationName));
 }
 protected override bool IsResultReference(IdentifierReference reference)
 {
     return(reference.IsIndexedDefaultMemberAccess &&
            reference.DefaultMemberRecursionDepth > 1 &&
            !(reference.Context is VBAParser.DictionaryAccessContext) &&
            !reference.IsIgnoringInspectionResultFor(AnnotationName));
 }
Ejemplo n.º 16
0
        private static string BoundResultDescription(IdentifierReference reference)
        {
            var expression    = reference.IdentifierName;
            var defaultMember = reference.Declaration.QualifiedName.ToString();

            return(string.Format(InspectionResults.ObjectWhereProcedureIsRequiredInspection, expression, defaultMember));
        }
Ejemplo n.º 17
0
        private string ResultDescription(IdentifierReference lhsReference, IdentifierReference rhsReference)
        {
            var lhsExpression = lhsReference.IdentifierName;
            var rhsExpression = rhsReference.IdentifierName;

            return(string.Format(InspectionResults.SuspiciousLetAssignmentInspection, lhsExpression, rhsExpression));
        }
Ejemplo n.º 18
0
        public static bool RequiresSetAssignment(IdentifierReference reference, RubberduckParserState state)
        {
            //Not an assignment...definitely does not require a 'Set' assignment
            if (!reference.IsAssignment)
            {
                return(false);
            }

            //We know for sure it DOES NOT use 'Set'
            if (!MayRequireAssignmentUsingSet(reference.Declaration))
            {
                return(false);
            }

            //We know for sure that it DOES use 'Set'
            if (RequiresAssignmentUsingSet(reference.Declaration))
            {
                return(true);
            }

            //We need to look everything to understand the RHS - the assigned reference is probably a Variant
            var allInterestingDeclarations = GetDeclarationsPotentiallyRequiringSetAssignment(state.AllUserDeclarations);

            return(ObjectOrVariantRequiresSetAssignment(reference, allInterestingDeclarations));
        }
Ejemplo n.º 19
0
        protected override string ResultDescription(IdentifierReference reference, string argumentTypeName)
        {
            var parameterName      = reference.Declaration.IdentifierName;
            var parameterTypeName  = reference.Declaration.FullAsTypeName;
            var argumentExpression = reference.Context.GetText();

            return(string.Format(InspectionResults.SetAssignmentWithIncompatibleObjectTypeInspection, parameterName, parameterTypeName, argumentExpression, argumentTypeName));
        }
Ejemplo n.º 20
0
 protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider)
 {
     return(new IdentifierReferenceInspectionResult(
                this,
                ResultDescription(reference),
                declarationFinderProvider,
                reference));
 }
Ejemplo n.º 21
0
 private static bool IsProcedureCallReference(IdentifierReference reference)
 {
     return(reference?.Declaration != null &&
            !reference.IsAssignment &&
            !reference.IsArrayAccess &&
            !reference.IsInnerRecursiveDefaultMemberAccess &&
            IsCalledAsProcedure(reference.Context));
 }
 private IInspectionResult InspectionResult(IdentifierReference reference, DeclarationFinder finder)
 {
     return(new IdentifierReferenceInspectionResult(
                this,
                ResultDescription(reference),
                finder,
                reference));
 }
 private static bool TryGetRelevantJumpContext <T>(IdentifierReference resultCandidate, out T ctxt) where T : ParserRuleContext
 {
     ctxt = resultCandidate.ParentScoping.Context.GetDescendents <T>()
            .Where(descendent => descendent.GetSelection() > resultCandidate.Selection)
            .OrderBy(descendent => descendent.GetSelection())
            .FirstOrDefault();
     return(ctxt != null);
 }
        protected override string ResultDescription(IdentifierReference reference)
        {
            var identifierName = reference.IdentifierName;

            return(string.Format(
                       InspectionResults.UnassignedVariableUsageInspection,
                       identifierName));
        }
Ejemplo n.º 25
0
        protected override string ResultDescription(IdentifierReference reference)
        {
            var referenceText = reference.Context.GetText();

            return(string.Format(
                       InspectionResults.ImplicitContainingWorkbookReferenceInspection,
                       referenceText));
        }
Ejemplo n.º 26
0
        protected override string ResultDescription(IdentifierReference reference)
        {
            var declarationName = reference.Declaration.IdentifierName;

            return(string.Format(
                       InspectionResults.UntypedFunctionUsageInspection,
                       declarationName));
        }
Ejemplo n.º 27
0
 private IInspectionResult Result(IdentifierReference reference)
 {
     return(new IdentifierReferenceInspectionResult(
                this,
                ResultDescription(reference),
                State,
                reference));
 }
        private static bool IsArraySubscriptAssignment(IdentifierReference reference)
        {
            var isLetAssignment = reference.Context.TryGetAncestor <VBAParser.LetStmtContext>(out var letStmt);
            var isSetAssignment = reference.Context.TryGetAncestor <VBAParser.SetStmtContext>(out var setStmt);

            return(isLetAssignment && letStmt.lExpression() is VBAParser.IndexExprContext ||
                   isSetAssignment && setStmt.lExpression() is VBAParser.IndexExprContext);
        }
        private Declaration ParentDeclaration(IdentifierReference reference)
        {
            var declarationTypes = new[] { DeclarationType.Function, DeclarationType.Procedure, DeclarationType.Property };

            return(UserDeclarations.SingleOrDefault(d =>
                                                    reference.ParentScoping.Equals(d) && declarationTypes.Contains(d.DeclarationType) &&
                                                    d.QualifiedName.QualifiedModuleName.Equals(reference.QualifiedModuleName)));
        }
Ejemplo n.º 30
0
 private bool IsImplicitDefaultMemberAssignment(IdentifierReference reference)
 {
     return(reference.IsNonIndexedDefaultMemberAccess &&
            reference.IsAssignment &&
            !reference.IsSetAssignment &&
            !reference.HasExplicitLetStatement &&
            !reference.IsIgnoringInspectionResultFor(AnnotationName));
 }
        /// <summary>
        /// Create the specific finder Method, specify the query it will use, and define the input and output parameters associated with it.
        /// The specific finder Method returns exactly one row of data from the data source, given an identifier.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="table"></param>
        /// <param name="lobSystemName"></param>
        /// <param name="catalog"></param>
        /// <param name="entity"></param>
        private static void CreateReadItemMethod(string name, string table, string lobSystemName, List<ExternalColumnReference> referenceList, AdministrationMetadataCatalog catalog, Entity entity)
        {
            uint language = SPContext.Current.Web != null ? SPContext.Current.Web.Language : 1033;

            string itemMethodName = "Get" + name;
            string listMethodEntity = name + "List";
            string itemMethodEntity = name;

            ExternalColumnReference keyColumn = null;

            Method getItemMethod = entity.Methods.Create(itemMethodName, true, false, table);

            // Specify the query
            // "SELECT [CustomerId] , [FirstName] , [LastName] , [Phone] , [EmailAddress] , [CompanyName] FROM [Customers].[SalesLT].[Customer] WHERE [CustomerId] = @CustomerId"
            string querySingleItemString = "SELECT ";
            string whereClause = "";

            foreach (ExternalColumnReference reference in referenceList)
            {
                querySingleItemString += "[" + reference.SourceName + "], ";

                if(reference.IsKey)
                {
                    keyColumn = reference;
                    whereClause = "[" + reference.SourceName + "] = @" + reference.DestinationName;
                }
            }
            querySingleItemString = querySingleItemString.Substring(0, querySingleItemString.Length - 2);
            querySingleItemString += " FROM [" + table + "] WHERE " + whereClause;

            // Set the method properties
            getItemMethod.Properties.Add("RdbCommandText", querySingleItemString);
            getItemMethod.Properties.Add("RdbCommandType", "Text");
            getItemMethod.Properties.Add("BackEndObjectType", "SqlServerTable");
            getItemMethod.Properties.Add("BackEndObject", table);
            getItemMethod.Properties.Add("Schema", "dbo");

            // Create the EntityID input parameter
            if (keyColumn == null)
            {
                var message = SPUtility.GetLocalizedString("$Resources:ExternalLookup_Creator_KeyColumn", "Resources", language);
                throw new NullReferenceException(message);
            }

            string idParameter = "@" + keyColumn.DestinationName;
            Parameter entityIdParameter = getItemMethod.Parameters.Create(idParameter, true, DirectionType.In);

            // Create the TypeDescriptor for the EntityID parameter
            entityIdParameter.CreateRootTypeDescriptor(
                keyColumn.DestinationName,
                true,
                keyColumn.Type,
                keyColumn.SourceName,
                new IdentifierReference(keyColumn.DestinationName, new EntityReference("EFEXCON.ExternalLookup", itemMethodEntity, catalog), catalog),
                null,
                TypeDescriptorFlags.None,
                null,
                catalog);

            // Create the Entity return parameter
            Parameter modelParameter = getItemMethod.Parameters.Create(itemMethodEntity, true, DirectionType.Return);

            // Create the TypeDescriptors for the Entity return parameter
            TypeDescriptor returnRootCollectionTypeDescriptor =
                modelParameter.CreateRootTypeDescriptor(
                    listMethodEntity,
                    true,
                    "System.Data.IDataReader, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                    listMethodEntity,
                    null,
                    null,
                    TypeDescriptorFlags.IsCollection,
                    null,
                    catalog);

            TypeDescriptor returnRootElementTypeDescriptor =
                returnRootCollectionTypeDescriptor.ChildTypeDescriptors.Create(
                    itemMethodEntity,
                    true,
                    "System.Data.IDataRecord, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                    itemMethodEntity,
                    null,
                    null,
                    TypeDescriptorFlags.None,
                    null);

            foreach (ExternalColumnReference reference in referenceList)
            {
                IdentifierReference identityReference = null;

                if (reference.IsKey)
                {
                    identityReference = new IdentifierReference(reference.DestinationName, new EntityReference("EFEXCON.ExternalLookup", itemMethodEntity, catalog), catalog);
                }

                returnRootElementTypeDescriptor.ChildTypeDescriptors.Create(
                    reference.DestinationName,
                    true,
                    reference.Type,
                    reference.SourceName,
                    identityReference,
                    null,
                    TypeDescriptorFlags.None,
                    null
                );
            }

            // Create the specific finder method instance
            getItemMethod.MethodInstances.Create(itemMethodName, true, returnRootElementTypeDescriptor, MethodInstanceType.SpecificFinder, true);
        }
        /// <summary>
        /// Creates the finder Method, specify the query it will use, and define the output parameters associated with it.
        /// The finder Method returns all of the rows of data from the data source which its query defines.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="table"></param>
        /// <param name="lobSystemName"></param>
        /// <param name="referenceList"></param>
        /// <param name="catalog"></param>
        /// <param name="entity"></param>
        private static void CreateReadListMethod(string name, string table, string lobSystemName, List<ExternalColumnReference> referenceList, AdministrationMetadataCatalog catalog, Entity entity)
        {
            string listMethodName = String.Format("Get{0}List", name);
            string listMethodEntity = name + "List";
            string itemMethodEntity = name;

            var identifierField = referenceList.Where(x => x.IsKey).ToList().First();
            if (identifierField == null)
                throw new NullReferenceException("Could not get identifier field.");

            // Create the Finder method
            Method getListMethod = entity.Methods.Create(listMethodName, true, false, table); // itemMethodEntity

            // Specify the query
            // "SELECT [CustomerId] , [FirstName] , [LastName] , [Phone] , [EmailAddress] , [CompanyName] FROM [Customers].[SalesLT].[Customer]"
            string queryAllItemsString = "SELECT TOP(@RowLimit) ";

            foreach(ExternalColumnReference reference in referenceList)
            {
                queryAllItemsString += "[" + reference.SourceName + "], ";
            }
            queryAllItemsString = queryAllItemsString.Substring(0, queryAllItemsString.Length - 2);
            queryAllItemsString += " FROM [" + table + "]";

            var whereClause = " WHERE";
            foreach (ExternalColumnReference reference in referenceList)
            {
                if (reference.IsSearchField)
                {
                    if (reference.Type == "System.String")
                    {
                        whereClause += String.Format(" ((@{1} IS NULL) OR ((@{1} IS NULL AND [{0}] IS NULL) OR [{0}] LIKE @{1})) AND", reference.SourceName, reference.DestinationName);
                    }
                    else
                    {
                        whereClause += String.Format(" ((@{1} = N'0') OR ((@{1} IS NULL AND [{0}] IS NULL) OR [{0}] = @{1})) AND", reference.SourceName, reference.DestinationName);
                    }
                }
            }

            if (whereClause.Length == 7)
                whereClause = "";
            else
            {
                whereClause = whereClause.Substring(0, whereClause.Length - 4);
            }

            queryAllItemsString += whereClause;

            // Set method properties
            getListMethod.Properties.Add("RdbCommandText", queryAllItemsString);
            getListMethod.Properties.Add("RdbCommandType", "Text");
            getListMethod.Properties.Add("BackEndObjectType", "SqlServerTable");
            getListMethod.Properties.Add("BackEndObject", table);
            getListMethod.Properties.Add("Schema", "dbo");

            // Create the Entity return parameter
            Parameter modelParameter = getListMethod.Parameters.Create(name, true, DirectionType.Return);

            // Create the TypeDescriptors for the Entity return parameter
            TypeDescriptor returnRootCollectionTypeDescriptor =
                modelParameter.CreateRootTypeDescriptor(
                    listMethodEntity,
                    true,
                    "System.Data.IDataReader, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                    listMethodEntity,
                    null,
                    null, // filter descriptor
                    TypeDescriptorFlags.IsCollection,
                    null,
                    catalog);

            TypeDescriptor returnRootElementTypeDescriptor =
                returnRootCollectionTypeDescriptor.ChildTypeDescriptors.Create(
                    itemMethodEntity,
                    true,
                    "System.Data.IDataRecord, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                    itemMethodEntity,
                    null,
                    null,
                    TypeDescriptorFlags.None,
                    null);

            // Create a Filter so that we can limit the number
            // of rows returned;
            // otherwise we may exceed the list query size threshold.
            FilterDescriptor limitRowsReturnedFilter =
                getListMethod.FilterDescriptors.Create(
                    "RowLimitFilter", true, FilterType.Limit, identifierField.DestinationName);

            limitRowsReturnedFilter.Properties.Add("IsDefault", false);
            limitRowsReturnedFilter.Properties.Add("UsedForDisambiguation", false);

            // Create the RowsToRetrieve input parameter.
            Parameter identifierParameter =
                getListMethod.Parameters.Create(
                "@RowLimit", true, DirectionType.In);

            // Create the TypeDescriptor for the MaxRowsReturned parameter.
            // using the Filter we have created.
            TypeDescriptor maxRowsReturnedTypeDescriptor =
                identifierParameter.CreateRootTypeDescriptor(
                    "RowLimit",
                    true,
                    "System.Int64",
                    identifierField.SourceName,
                    null,
                    limitRowsReturnedFilter,
                    TypeDescriptorFlags.None,
                    null,
                    catalog);

            var stringTypeDescriptorList = new List<TypeDescriptor>();
            var counter = 0;
            foreach (ExternalColumnReference reference in referenceList)
            {
                IdentifierReference identityReference = null;
                if(reference.IsKey)
                    identityReference = new IdentifierReference(reference.DestinationName, new EntityReference("EFEXCON.ExternalLookup", itemMethodEntity, catalog), catalog);

                if (reference.IsSearchField)
                {
                    FilterType filterType = reference.Type == "System.String" ? FilterType.Wildcard : FilterType.Comparison;
                    FilterDescriptor filter = getListMethod.FilterDescriptors.Create(
                        reference.DestinationName + "Filter", true, filterType, reference.DestinationName);

                    filter.Properties.Add("CaseSensitive", false);
                    filter.Properties.Add("IsDefault", false);
                    filter.Properties.Add("UsedForDisambiguation", false);
                    filter.Properties.Add("UseValueAsDontCare", true);
                    filter.Properties.Add("DontCareValue", "");

                    // Create the filter input parameter.
                    Parameter filterParameter = getListMethod.Parameters.Create(
                            "@" + reference.DestinationName, true, DirectionType.In);

                    // Create the TypeDescriptor for the filter parameter.
                    TypeDescriptor filterParamTypeDescriptor =
                        filterParameter.CreateRootTypeDescriptor(
                        reference.DestinationName,
                        true,
                        reference.Type,
                        reference.SourceName,
                        null,
                        filter,
                        TypeDescriptorFlags.None,
                        null,
                        catalog);

                    if (reference.Type == "System.String")
                        stringTypeDescriptorList.Add(filterParamTypeDescriptor);

                    if (counter > 0)
                        filterParamTypeDescriptor.Properties.Add("LogicalOperatorWithPrevious", "And");

                    counter++;
                }

                var childTypeDescriptor = returnRootElementTypeDescriptor.ChildTypeDescriptors.Create(
                    reference.DestinationName,
                    true,
                    reference.Type,
                    reference.SourceName,
                    identityReference,
                    null,
                    TypeDescriptorFlags.None,
                    null
                );

                childTypeDescriptor.Properties.Add("ShowInPicker", true);
            }

            // Create the finder method instance
            MethodInstance readListMethodInstance =
                getListMethod.MethodInstances.Create(
                    listMethodName,
                    true,
                    returnRootCollectionTypeDescriptor,
                    MethodInstanceType.Finder,
                    true);

            readListMethodInstance.Properties.Add("RootFinder", "");

            // Set the default value for the number of rows
            // to be returned filter.
            // NOTE: The method instance needs to be created first
            // before we can set the default value.
            maxRowsReturnedTypeDescriptor.SetDefaultValue(
                readListMethodInstance.Id, Int64.Parse("30"));

            foreach(var typeDescriptor in stringTypeDescriptorList)
            {
                typeDescriptor.SetDefaultValue(
                    readListMethodInstance.Id, "");
            }
        }