/// <summary>
        /// Creates a field that holds <see cref="QueryTypeProperties{T}"/> for the module.
        /// </summary>
        protected FieldDeclarationSyntax CreatePropertiesField(
            Module module, string resultClassName, FieldDeclarationSyntax propsField, SortType?sortType)
        {
            var queryTypePropertiesType = SyntaxEx.GenericName("QueryTypeProperties", resultClassName);

            var propertiesInitializer = SyntaxEx.ObjectCreation(
                queryTypePropertiesType,
                SyntaxEx.Literal(module.Name),
                SyntaxEx.Literal(module.Prefix),
                module.QueryType == null
                    ? (ExpressionSyntax)SyntaxEx.NullLiteral()
                    : SyntaxEx.MemberAccess("QueryType", module.QueryType.ToString()),
                sortType == null
                    ? (ExpressionSyntax)SyntaxEx.NullLiteral()
                    : SyntaxEx.MemberAccess("SortType", sortType.ToString()),
                CreateTupleListExpression(GetBaseParameters(module)),
                propsField == null ? (ExpressionSyntax)SyntaxEx.NullLiteral() : (NamedNode)propsField,
                resultClassName == "object"
                    ? (ExpressionSyntax)SyntaxEx.LambdaExpression("_", SyntaxEx.NullLiteral())
                    : SyntaxEx.MemberAccess(resultClassName, "Parse"));

            return(SyntaxEx.FieldDeclaration(
                       new[] { SyntaxKind.PrivateKeyword, SyntaxKind.StaticKeyword, SyntaxKind.ReadOnlyKeyword },
                       queryTypePropertiesType, ClassNameBase + "Properties", propertiesInitializer));
        }
Пример #2
0
        protected override void GenerateInternal(Module module)
        {
            ResultClassName = ClassNameBase + "Result";

            var resultType = GenerateResultClass(GetPropertyGroups(module));

            if (resultType == null)
            {
                ResultClassName = "object";
                m_voidResult    = true;
            }
            else
            {
                var codeUnit = SyntaxEx.CompilationUnit(
                    SyntaxEx.NamespaceDeclaration(Wiki.EntitiesNamespace, resultType),
                    "System", "System.Linq", "System.Globalization", "System.Xml.Linq", "LinqToWiki",
                    "LinqToWiki.Internals");

                Wiki.Files.Add(ClassNameBase, codeUnit);
            }

            m_listResult = module.ListResult;

            GenerateMethod(module);
        }
        /// <summary>
        /// Creates class that is used in the <c>where</c> clause.
        /// </summary>
        private ClassDeclarationSyntax GenerateWhere(IEnumerable <Parameter> parameters)
        {
            var propertyDeclarations =
                parameters.Select(p => GenerateProperty(p.Name, p.Type, multi: p.Multi, description: p.Description));

            return(SyntaxEx.ClassDeclaration(m_whereClassName, propertyDeclarations)
                   .AddPrivateConstructor());
        }
Пример #4
0
        /// <summary>
        /// Creates the property that can used to access the information from the given module.
        /// </summary>
        private PropertyDeclarationSyntax CreateProperty(Module module)
        {
            var summary = SyntaxEx.DocumentationSummary(module.Description);

            return(SyntaxEx.AutoPropertyDeclaration(
                       new[] { SyntaxKind.PublicKeyword, SyntaxKind.AbstractKeyword }, GenerateMethodResultType(),
                       ClassNameBase, isAbstract: true, setModifier: SyntaxKind.PrivateKeyword)
                   .WithLeadingTrivia(Syntax.Trivia(SyntaxEx.DocumentationComment(summary))));
        }
        /// <summary>
        /// Creates a class for a set of properties.
        /// </summary>
        protected ClassDeclarationSyntax GenerateClassForProperties(string className, IEnumerable <Property> properties, string baseType = null)
        {
            var propertiesArray = properties.ToArray();

            return(SyntaxEx.ClassDeclaration(
                       className, baseType == null ? null : SyntaxFactory.ParseTypeName(baseType),
                       propertiesArray.Select(p => GenerateProperty(p.Name, p.Type, p.Nullable)))
                   .AddPrivateConstructor()
                   .AddMembers(
                       GenerateParseMethod(className, propertiesArray), GenerateToStringMethod(propertiesArray)));
        }
Пример #6
0
        protected override IList <StatementSyntax> GenerateMethodBody(
            ExpressionSyntax queryProcessor, ExpressionSyntax queryParameters, IList <StatementSyntax> statements)
        {
            var invocation = SyntaxEx.Invocation(
                SyntaxEx.MemberAccess(queryProcessor, m_listResult ? "ExecuteList" : "ExecuteSingle"), queryParameters);

            var statement =
                m_voidResult
                    ? (StatementSyntax)Syntax.ExpressionStatement(invocation)
                    : SyntaxEx.Return(invocation);

            statements.Add(statement);
            return(statements);
        }
        /// <summary>
        /// Generates a single property.
        /// </summary>
        protected PropertyDeclarationSyntax GenerateProperty(
            string name, ParameterType type, bool nullable = false, string description = null, bool multi = false)
        {
            var result = SyntaxEx.AutoPropertyDeclaration(
                new[] { SyntaxKind.PublicKeyword },
                Wiki.TypeManager.GetTypeName(type, FixPropertyName(name), ClassNameBase, multi, nullable),
                GetPropertyName(name), SyntaxKind.PrivateKeyword);

            if (description != null)
            {
                result = result.WithDocumentationSummary(description);
            }

            return(result);
        }
Пример #8
0
        protected override TypeSyntax GenerateMethodResultType()
        {
            if (m_voidResult)
            {
                return(Syntax.ParseTypeName("void"));
            }

            var resultType = Syntax.ParseTypeName(ResultClassName);

            if (m_listResult)
            {
                resultType = SyntaxEx.GenericName("IEnumerable", resultType);
            }

            return(resultType);
        }
        /// <summary>
        /// Creates an overide of the <see cref="object.ToString"/> method for given properties.
        /// </summary>
        private static MethodDeclarationSyntax GenerateToStringMethod(IEnumerable <Property> properties)
        {
            var formatString = string.Join(
                "; ", properties.Select((p, i) => string.Format("{0}: {{{1}}}", GetPropertyName(p.Name, false), i)));

            var parameters = new List <ExpressionSyntax> {
                SyntaxEx.Literal(formatString)
            };

            parameters.AddRange(properties.Select(p => SyntaxFactory.IdentifierName(GetPropertyName(p.Name))));

            var returnStatement = SyntaxEx.Return(SyntaxEx.Invocation(SyntaxEx.MemberAccess("string", "Format"), parameters));

            return(SyntaxEx.MethodDeclaration(
                       new[] { SyntaxKind.PublicKeyword, SyntaxKind.OverrideKeyword }, "string", "ToString", null,
                       returnStatement));
        }
Пример #10
0
        /// <summary>
        /// Creates a field that holds information about property groups for the given module.
        /// </summary>
        protected FieldDeclarationSyntax CreatePropsField(IEnumerable <PropertyGroup> propertyGroups)
        {
            var initializers =
                from pg in propertyGroups
                from p in pg.Properties
                group pg.Name by p.Name
                into g
                select new[] { SyntaxEx.Literal(g.Key), SyntaxEx.ArrayCreation(null, g.Select(SyntaxEx.Literal)) };

            var propsInitializer = SyntaxEx.ObjectCreation("Dictionary<string, string[]>", null, initializers);

            var propsField =
                SyntaxEx.FieldDeclaration(
                    new[] { SyntaxKind.PrivateKeyword, SyntaxKind.StaticKeyword, SyntaxKind.ReadOnlyKeyword },
                    "IDictionary<string, string[]>", ClassNameBase + "Props", propsInitializer);

            return(propsField);
        }
        /// <summary>
        /// Creates class that is ised in the <c>orderby</c> clause.
        /// Returns <c>null</c>, if the module doesn't support sorting.
        /// </summary>
        private ClassDeclarationSyntax GenerateOrderBy(IEnumerable <Parameter> parameters, IEnumerable <Property> properties)
        {
            var propertyTypes = properties.Distinct().ToDictionary(p => p.Name, p => p.Type);

            var sortParameter = parameters.SingleOrDefault(p => p.Name == "sort");

            if (!parameters.Any(p => p.Name == "dir"))
            {
                return(null);
            }

            IEnumerable <PropertyDeclarationSyntax> propertyDeclarations = null;

            if (sortParameter != null)
            {
                propertyDeclarations =
                    ((EnumParameterType)sortParameter.Type).Values.Select(v => GenerateProperty(v, propertyTypes[v]));
            }

            return(SyntaxEx.ClassDeclaration(m_orderByClassName, propertyDeclarations)
                   .AddPrivateConstructor());
        }
Пример #12
0
        protected override ClassDeclarationSyntax GenerateResultClass(IEnumerable <PropertyGroup> propertyGroups)
        {
            var resultClass = GenerateClassForProperties(ResultClassName, propertyGroups.SelectMany(g => g.Properties));

            var parseMethodBody = resultClass.DescendantNodes()
                                  .OfType <MethodDeclarationSyntax>()
                                  .Single(m => m.Identifier.ValueText == "Parse")
                                  .Body;

            var statements = parseMethodBody.Statements;

            var newStatement = SyntaxEx.Assignment(
                SyntaxFactory.IdentifierName("element"),
                SyntaxEx.Invocation(
                    SyntaxEx.MemberAccess(SyntaxEx.Invocation(SyntaxEx.MemberAccess("element", "Elements")), "Single")));

            var newStatements = new[] { newStatement }.Concat(statements);

            var newBody = SyntaxEx.Block(newStatements);

            return(resultClass.ReplaceNode(parseMethodBody, newBody));
        }
Пример #13
0
 /// <summary>
 /// Creates an expression that creates the <see cref="LinqToWiki.Collections.TupleList{T1,T2}"/>
 /// that is passed as a parameter.
 /// </summary>
 private static ObjectCreationExpressionSyntax CreateTupleListExpression(IEnumerable <Tuple <string, string> > tupleList)
 {
     return(SyntaxEx.ObjectCreation(
                "TupleList<string, string>", null,
                tupleList.Select(t => new[] { t.Item1, t.Item2 }.Select(SyntaxEx.Literal))));
 }
 protected override IList <StatementSyntax> GenerateMethodBody(
     ExpressionSyntax queryProcessor, ExpressionSyntax queryParameters, IList <StatementSyntax> statements)
 {
     statements.Add(SyntaxEx.Return(SyntaxEx.ObjectCreation(m_queryType, queryProcessor, queryParameters)));
     return(statements);
 }
Пример #15
0
        /// <summary>
        /// Creates an entry method, that is used to execute query for normal modules
        /// or that can be used as a base for a query for query modules.
        /// </summary>
        protected void GenerateMethod(
            Module module, IEnumerable <Parameter> methodParameters, string resultClassName,
            FieldDeclarationSyntax propsField, string fileName, bool nullableParameters, SortType?sortType)
        {
            var propertiesField = CreatePropertiesField(module, resultClassName, propsField, sortType);

            ExpressionSyntax queryParameters = SyntaxEx.Invocation(
                SyntaxEx.MemberAccess("QueryParameters", SyntaxEx.GenericName("Create", resultClassName)));

            var queryParametersLocal = SyntaxEx.LocalDeclaration("var", "queryParameters", queryParameters);

            var documentationElements = new List <XmlElementSyntax>();

            var summary = SyntaxEx.DocumentationSummary(module.Description);

            documentationElements.Add(summary);

            var parameters = new List <ParameterSyntax>();
            IList <StatementSyntax> statements = new List <StatementSyntax>();

            statements.Add(queryParametersLocal);

            methodParameters = methodParameters
                               .Where(p => !p.Deprecated)
                               .Where(p => p.Name != "continue")
                               .OrderByDescending(p => p.Required);

            foreach (var methodParameter in methodParameters)
            {
                var nullable      = nullableParameters && !methodParameter.Required;
                var typeName      = Wiki.TypeManager.GetTypeName(methodParameter, ClassNameBase, nullable, false);
                var parameterName = GetPropertyName(methodParameter.Name);

                // this type cannot be processed
                if (typeName == null)
                {
                    continue;
                }

                var parameter = SyntaxEx.Parameter(typeName, parameterName, nullable ? SyntaxEx.NullLiteral() : null);

                parameters.Add(parameter);

                ExpressionSyntax valueExpression = (NamedNode)parameter;

                if (nullable && typeName.EndsWith("?"))
                {
                    valueExpression = SyntaxEx.MemberAccess(valueExpression, "Value");
                }

                ExpressionSyntax newQueryParameters;
                if (typeName == "System.IO.Stream")
                {
                    newQueryParameters = SyntaxEx.Invocation(
                        SyntaxEx.MemberAccess(queryParametersLocal, "AddFile"),
                        SyntaxEx.Literal(methodParameter.Name),
                        valueExpression);
                }
                else
                {
                    newQueryParameters = SyntaxEx.Invocation(
                        SyntaxEx.MemberAccess(queryParametersLocal, "AddSingleValue"),
                        SyntaxEx.Literal(methodParameter.Name),
                        SyntaxEx.Invocation(SyntaxEx.MemberAccess(valueExpression, "ToQueryString")));
                }
                var queryParametersAssignment = SyntaxEx.Assignment(queryParametersLocal, newQueryParameters);

                if (nullable)
                {
                    var assignmentWithCheck = SyntaxEx.If(
                        SyntaxEx.NotEquals((NamedNode)parameter, SyntaxEx.NullLiteral()), queryParametersAssignment);

                    statements.Add(assignmentWithCheck);
                }
                else
                {
                    statements.Add(queryParametersAssignment);
                }

                var parameterDocumentation = SyntaxEx.DocumentationParameter(parameterName, methodParameter.Description);

                documentationElements.Add(parameterDocumentation);
            }

            statements = GenerateMethodBody(
                SyntaxEx.ObjectCreation(
                    SyntaxEx.GenericName("QueryProcessor", resultClassName),
                    SyntaxFactory.IdentifierName("m_wiki"),
                    (NamedNode)propertiesField), (NamedNode)queryParametersLocal, statements);

            var modifiers = new List <SyntaxKind> {
                SyntaxKind.PublicKeyword
            };

            if (statements == null)
            {
                modifiers.Add(SyntaxKind.AbstractKeyword);
            }

            var method = SyntaxEx.MethodDeclaration(
                modifiers, GenerateMethodResultType(), ClassNameBase, parameters, statements)
                         .WithLeadingTrivia(SyntaxFactory.Trivia(SyntaxEx.DocumentationComment(documentationElements)));

            AddMembersToClass(fileName, propertiesField, method);
        }
        protected override void GenerateInternal(Module module)
        {
            m_selectClassName  = ClassNameBase + "Select";
            m_whereClassName   = ClassNameBase + "Where";
            m_orderByClassName = ClassNameBase + "OrderBy";

            var parameters = module.Parameters.ToList();

            var sortParameters = RemoveAndReturnByNames(parameters, "sort", "dir");

            var methodParameters = parameters.RemoveAndReturn(p => p.Required);

            // don't belong anywhere, are used in a special way
            RemoveAndReturnByNames(parameters, "continue", "offset", "limit", "prop");

            var whereParameters = parameters;

            var selectClass  = GenerateSelect(module.PropertyGroups, module.Name == "revisions");
            var whereClass   = GenerateWhere(whereParameters);
            var orderByClass = GenerateOrderBy(sortParameters, module.PropertyGroups.SelectMany(g => g.Properties));

            var codeUnit = SyntaxEx.CompilationUnit(
                SyntaxEx.NamespaceDeclaration(Wiki.EntitiesNamespace, selectClass, whereClass, orderByClass),
                "System", "System.Globalization", "System.Xml.Linq", "LinqToWiki", "LinqToWiki.Collections",
                "LinqToWiki.Internals");

            Wiki.Files.Add(ClassNameBase, codeUnit);

            string queryTypeName = "WikiQuery";
            var    queryTypeGenericParameters = new List <string> {
                m_whereClassName, m_selectClassName
            };

            if (orderByClass != null)
            {
                queryTypeName += "Sortable";
                queryTypeGenericParameters.Insert(1, m_orderByClassName);
            }

            if (module.Generator)
            {
                queryTypeName += "Generator";
                queryTypeGenericParameters.Insert(0, Wiki.Names.Page);
            }

            m_queryType = SyntaxEx.GenericName(queryTypeName, queryTypeGenericParameters);

            SortType?sortType = null;

            var dirParameter = sortParameters.SingleOrDefault(p => p.Name == "dir");

            if (dirParameter != null)
            {
                var type = (EnumParameterType)dirParameter.Type;
                if (type.Values.Any(x => x == "ascending"))
                {
                    sortType = SortType.Ascending;
                }
                else if (type.Values.Any(x => x == "newer"))
                {
                    sortType = SortType.Newer;
                }
            }

            GenerateMethod(module, methodParameters, m_selectClassName, m_selectProps, MethodClassName, false, sortType);
        }
Пример #17
0
        /// <summary>
        /// Creates a method that parses an XML element returned from the API by setting creating an instance
        /// of the given class and setting its properties.
        /// </summary>
        private MethodDeclarationSyntax GenerateParseMethod(string className, IEnumerable <Property> properties)
        {
            var elementParameter = SyntaxEx.Parameter("XElement", "element");
            var wikiParameter    = SyntaxEx.Parameter("WikiInfo", "wiki");
            var statements       = new List <StatementSyntax>();

            var resultLocal = SyntaxEx.LocalDeclaration("var", "result", SyntaxEx.ObjectCreation(className));

            statements.Add(resultLocal);

            foreach (var property in properties)
            {
                ExpressionSyntax propertyValueAccess;
                bool             checkForNull;

                if (property.Name == "*")
                {
                    propertyValueAccess = (NamedNode)elementParameter;
                    checkForNull        = false;
                }
                else
                {
                    propertyValueAccess = SyntaxEx.Invocation(
                        SyntaxEx.MemberAccess(elementParameter, "Attribute"), SyntaxEx.Literal(property.Name));
                    checkForNull = true;
                }
                var propertyValueLocal = SyntaxEx.LocalDeclaration(
                    "var", GetPropertyName(property.Name, false) + "Value", propertyValueAccess);

                statements.Add(propertyValueLocal);

                var valueValue = SyntaxEx.MemberAccess(propertyValueLocal, "Value");

                var assignment = SyntaxEx.Assignment(
                    SyntaxEx.MemberAccess(resultLocal, GetPropertyName(property.Name)),
                    Wiki.TypeManager.CreateConverter(
                        property, ClassNameBase, valueValue,
                        (NamedNode)wikiParameter));

                if (checkForNull)
                {
                    ExpressionSyntax condition = SyntaxEx.NotEquals((NamedNode)propertyValueLocal, SyntaxEx.NullLiteral());

                    var simpleType = property.Type as SimpleParameterType;
                    if (simpleType == null || (simpleType.Name != "string" && simpleType.Name != "boolean"))
                    {
                        condition = SyntaxEx.And(
                            condition, SyntaxEx.NotEquals(valueValue, SyntaxEx.Literal("")));
                    }

                    var ifStatement = SyntaxEx.If(condition, assignment);
                    statements.Add(ifStatement);
                }
                else
                {
                    statements.Add(assignment);
                }
            }

            statements.Add(SyntaxEx.Return(resultLocal));

            return(SyntaxEx.MethodDeclaration(
                       new[] { SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword }, className, "Parse",
                       new[] { elementParameter, wikiParameter }, statements));
        }