/// <summary> /// Returns an expression that converts to a <see cref="SimpleParameterType"/>, /// using <see cref="LinqToWiki.Internals.ValueParser"/>. /// </summary> private static ExpressionSyntax CreateSimpleConverter( SimpleParameterType simpleType, string propertyName, ExpressionSyntax value, ExpressionSyntax wiki) { if (simpleType.Name == "namespace") { return(SyntaxEx.Invocation(SyntaxEx.MemberAccess("ValueParser", "ParseNamespace"), value, wiki)); } string typeName; switch (simpleType.Name) { case "string": case "user": typeName = "String"; break; case "timestamp": typeName = "DateTime"; break; case "boolean": typeName = "Boolean"; break; case "integer": typeName = propertyName.EndsWith("id") ? "Int64" : "Int32"; break; default: throw new InvalidOperationException(string.Format("Unknown type {0}", simpleType.Name)); } return(SyntaxEx.Invocation(SyntaxEx.MemberAccess("ValueParser", "Parse" + typeName), value)); }
/// <summary> /// Creates file that holds all enums. /// </summary> private void CreateEnumsFile() { Files.Add( Names.Enums, SyntaxEx.CompilationUnit( SyntaxEx.NamespaceDeclaration(Namespace), "LinqToWiki.Internals")); }
/// <summary> /// Creates the <c>Wiki</c> class, that is used as an entry point for the whole API. /// It can be used to access non-query modules directly and non-prop query mdoules /// indirectly though its <c>Query</c> property. /// </summary> private void CreateWikiClass(string baseUri, string apiPath) { var wikiField = SyntaxEx.FieldDeclaration( new[] { SyntaxKind.PrivateKeyword, SyntaxKind.ReadOnlyKeyword }, Names.WikiInfo, "m_wiki"); var queryProperty = SyntaxEx.AutoPropertyDeclaration( new[] { SyntaxKind.PublicKeyword }, Names.QueryAction, "Query", SyntaxKind.PrivateKeyword); var pagesSourcePageSizePropertyName = "PagesSourcePageSize"; var wikiFieldPagesSourcePageSizeProperty = SyntaxEx.MemberAccess(wikiField, pagesSourcePageSizePropertyName); var pagesSourcePageSizeProperty = SyntaxEx.PropertyDeclaration( new[] { SyntaxKind.PublicKeyword }, SyntaxFactory.ParseTypeName("int"), pagesSourcePageSizePropertyName, getStatements: new[] { SyntaxEx.Return(wikiFieldPagesSourcePageSizeProperty) }, setStatements: new[] { SyntaxEx.Assignment(wikiFieldPagesSourcePageSizeProperty, SyntaxFactory.IdentifierName("value")) }); var userAgentParameter = SyntaxEx.Parameter("string", "userAgent"); var baseUriParameter = SyntaxEx.Parameter("string", "baseUri", SyntaxEx.NullLiteral()); var apiPathParameter = SyntaxEx.Parameter("string", "apiPath", SyntaxEx.NullLiteral()); var wikiAssignment = SyntaxEx.Assignment( wikiField, SyntaxEx.ObjectCreation( Names.WikiInfo, (NamedNode)userAgentParameter, SyntaxEx.Coalesce((NamedNode)baseUriParameter, SyntaxEx.Literal(baseUri)), SyntaxEx.Coalesce((NamedNode)apiPathParameter, SyntaxEx.Literal(apiPath)))); var queryAssignment = SyntaxEx.Assignment( queryProperty, SyntaxEx.ObjectCreation(Names.QueryAction, (NamedNode)wikiField)); var ctor = SyntaxEx.ConstructorDeclaration( new[] { SyntaxKind.PublicKeyword }, Names.Wiki, new[] { userAgentParameter, baseUriParameter, apiPathParameter }, new StatementSyntax[] { wikiAssignment, queryAssignment }); var members = new List <MemberDeclarationSyntax> { wikiField, queryProperty, pagesSourcePageSizeProperty, ctor }; members.AddRange(CreatePageSourceMethods(wikiField)); var wikiClass = SyntaxEx.ClassDeclaration(Names.Wiki, members); Files.Add( Names.Wiki, SyntaxEx.CompilationUnit( SyntaxEx.NamespaceDeclaration(Namespace, wikiClass), "System", "System.Collections.Generic", "LinqToWiki", "LinqToWiki.Collections", "LinqToWiki.Internals", "LinqToWiki.Parameters", EntitiesNamespace)); }
/// <summary> /// Creates the <c>Page</c> class that used to access prop query modules. /// </summary> private void CreatePageClass() { var pageClass = SyntaxEx.ClassDeclaration(SyntaxKind.AbstractKeyword, Names.Page) .AddPrivateConstructor(); Files.Add( Names.Page, SyntaxEx.CompilationUnit( SyntaxEx.NamespaceDeclaration(Namespace, pageClass), "System", "System.Collections.Generic", "LinqToWiki", "LinqToWiki.Collections", "LinqToWiki.Internals", EntitiesNamespace)); }
/// <summary> /// Creates the <c>PageResult</c> class that can be used as a named (non-anonymous) type /// for the result of PageSource queries. /// </summary> private void CreatePageResultClass() { var infoResultClassName = Files["info"].SingleDescendant <ClassDeclarationSyntax>().Identifier.ValueText; var typeParameterName = "TData"; var dataPropertyType = SyntaxEx.GenericName("IEnumerable", typeParameterName); var infoProperty = SyntaxEx.AutoPropertyDeclaration( new[] { SyntaxKind.PublicKeyword }, infoResultClassName, "Info", SyntaxKind.PrivateKeyword); var dataProperty = SyntaxEx.AutoPropertyDeclaration( new[] { SyntaxKind.PublicKeyword }, dataPropertyType, "Data", SyntaxKind.PrivateKeyword); var infoParameter = SyntaxEx.Parameter(infoResultClassName, "info"); var dataParameter = SyntaxEx.Parameter(dataPropertyType, "data"); var ctorBody = new StatementSyntax[] { SyntaxEx.Assignment(infoProperty, infoParameter), SyntaxEx.Assignment(dataProperty, dataParameter) }; var ctor = SyntaxEx.ConstructorDeclaration( new[] { SyntaxKind.PublicKeyword }, Names.PageResult, new[] { infoParameter, dataParameter }, ctorBody); var pageResultClass = SyntaxEx.ClassDeclaration( Names.PageResult, new[] { SyntaxEx.TypeParameter(typeParameterName) }, null, new MemberDeclarationSyntax[] { infoProperty, dataProperty, ctor }); var pageResultType = SyntaxEx.GenericName(Names.PageResult, typeParameterName); var createMethodBody = SyntaxEx.Return( SyntaxEx.ObjectCreation(pageResultType, (NamedNode)infoParameter, (NamedNode)dataParameter)); var createMethod = SyntaxEx.MethodDeclaration( new[] { SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword }, pageResultType, "Create", new[] { SyntaxEx.TypeParameter(typeParameterName) }, new[] { infoParameter, dataParameter }, createMethodBody); var pageResultHelperClass = SyntaxEx.ClassDeclaration(SyntaxKind.StaticKeyword, Names.PageResult, createMethod); Files.Add( Names.PageResult, SyntaxEx.CompilationUnit( SyntaxEx.NamespaceDeclaration(Namespace, pageResultClass, pageResultHelperClass), "System.Collections.Generic", EntitiesNamespace)); }
/// <summary> /// Creates the <c>QueryAction</c> class that is used to access non-prop query modules. /// </summary> private void CreateQueryActionClass() { var wikiField = SyntaxEx.FieldDeclaration( new[] { SyntaxKind.PrivateKeyword, SyntaxKind.ReadOnlyKeyword }, Names.WikiInfo, "m_wiki"); var wikiParameter = SyntaxEx.Parameter(Names.WikiInfo, "wiki"); var ctor = SyntaxEx.ConstructorDeclaration( new[] { SyntaxKind.InternalKeyword }, Names.QueryAction, new[] { wikiParameter }, new StatementSyntax[] { SyntaxEx.Assignment(wikiField, wikiParameter) }); var queryActionClass = SyntaxEx.ClassDeclaration(Names.QueryAction, wikiField, ctor); Files.Add( Names.QueryAction, SyntaxEx.CompilationUnit( SyntaxEx.NamespaceDeclaration(Namespace, queryActionClass), "System", "System.Collections.Generic", "LinqToWiki", "LinqToWiki.Collections", "LinqToWiki.Parameters", "LinqToWiki.Internals", EntitiesNamespace)); }
/// <summary> /// Creates methods to create <see cref="ListSourceBase{TPage}"/> page sources /// for the <c>Wiki</c> class. /// </summary> private static IEnumerable <MethodDeclarationSyntax> CreatePageSourceMethods(FieldDeclarationSyntax wikiField) { var pageSources = new[] { new { type = "string", name = "titles", sourceType = typeof(TitlesSource <>) }, new { type = "long", name = "pageIds", sourceType = typeof(PageIdsSource <>) }, new { type = "long", name = "revIds", sourceType = typeof(RevIdsSource <>) } }; foreach (var pageSource in pageSources) { string sourceTypeName = pageSource.sourceType.Name; sourceTypeName = sourceTypeName.Substring(0, sourceTypeName.IndexOf('`')); var parameterVersions = new[] { SyntaxEx.Parameter(SyntaxEx.GenericName("IEnumerable", pageSource.type), pageSource.name), SyntaxEx.Parameter( pageSource.type + "[]", pageSource.name, modifiers: new[] { SyntaxKind.ParamsKeyword }) }; foreach (var parameter in parameterVersions) { var returnStatement = SyntaxEx.Return( SyntaxEx.ObjectCreation( SyntaxEx.GenericName(sourceTypeName, Names.Page), (NamedNode)wikiField, (NamedNode)parameter)); yield return(SyntaxEx.MethodDeclaration( new[] { SyntaxKind.PublicKeyword }, SyntaxEx.GenericName("PagesSource", Names.Page), "Create" + sourceTypeName, new[] { parameter }, returnStatement)); } } }
/// <summary> /// Returns the given class with a private parameterless constructor added. /// </summary> public static ClassDeclarationSyntax AddPrivateConstructor(this ClassDeclarationSyntax classDeclaration) { return(classDeclaration.AddMembers( SyntaxEx.ConstructorDeclaration( new[] { SyntaxKind.PrivateKeyword }, classDeclaration.Identifier.ValueText))); }
public static TNode WithDocumentationSummary <TNode>(this TNode node, string summary) where TNode : SyntaxNode { return(node.WithLeadingTrivia(Syntax.Trivia(SyntaxEx.DocumentationComment(SyntaxEx.DocumentationSummary(summary))))); }
/// <summary> /// Returns an expression that converts to an <see cref="EnumParameterType"/>. /// </summary> private ExpressionSyntax CreateEnumConverter(EnumParameterType type, string moduleName, ExpressionSyntax value) { var typeName = m_enumTypeNames[moduleName, type]; return(SyntaxEx.ObjectCreation(typeName, value)); }
/// <summary> /// Creates a type representing the given <see cref="EnumParameterType"/>. /// </summary> private string GenerateType(EnumParameterType enumType, string propertyName, string moduleName) { string typeName = moduleName + propertyName; Dictionary <EnumParameterType, string> moduleTypes; if (m_enumTypeNames.TryGetValue(moduleName, out moduleTypes)) { int i = 2; while (moduleTypes.Values.Contains(typeName)) { typeName = moduleName + propertyName + i++; } } var fixedMemberNameMapping = new TupleList <string, string>(); var memberNames = new List <string>(); foreach (var name in enumType.Values) { var fixedName = FixEnumMemberName(name); if (name != fixedName.TrimStart('@')) { fixedMemberNameMapping.Add(fixedName, name); } memberNames.Add(fixedName); } var members = enumType.Values.Select( memberName => SyntaxEx.FieldDeclaration( new[] { SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword, SyntaxKind.ReadOnlyKeyword }, typeName, FixEnumMemberName(memberName), SyntaxEx.ObjectCreation(typeName, SyntaxEx.Literal(memberName)))); var constructorParameter = SyntaxEx.Parameter("string", "value"); var contructor = SyntaxEx.ConstructorDeclaration( new[] { SyntaxKind.InternalKeyword }, typeName, new[] { constructorParameter }, constructorInitializer: SyntaxEx.BaseConstructorInitializer((NamedNode)constructorParameter)); var firstParameter = SyntaxEx.Parameter(typeName, "first"); var secondParameter = SyntaxEx.Parameter(typeName, "second"); Func <SyntaxKind, ExpressionSyntax, OperatorDeclarationSyntax> createOperator = (op, result) => SyntaxEx.OperatorDeclaration( Syntax.ParseTypeName("bool"), op, new[] { firstParameter, secondParameter }, new[] { SyntaxEx.Return(result) }); var equalsExpression = SyntaxEx.Invocation( Syntax.IdentifierName("Equals"), (NamedNode)firstParameter, (NamedNode)secondParameter); var notEqualsExpression = SyntaxEx.Not(equalsExpression); var equalsOperator = createOperator(SyntaxKind.EqualsEqualsToken, equalsExpression); var notEqualsOPerator = createOperator(SyntaxKind.ExclamationEqualsToken, notEqualsExpression); var equalsParameter = SyntaxEx.Parameter("object", "obj"); var equalsMethod = SyntaxEx.MethodDeclaration( new[] { SyntaxKind.PublicKeyword, SyntaxKind.OverrideKeyword }, "bool", "Equals", new[] { equalsParameter }, SyntaxEx.Return( SyntaxEx.Invocation(SyntaxEx.MemberAccess("base", "Equals"), (NamedNode)equalsParameter))); var getHashCodeMethod = SyntaxEx.MethodDeclaration( new[] { SyntaxKind.PublicKeyword, SyntaxKind.OverrideKeyword }, "int", "GetHashCode", new ParameterSyntax[0], SyntaxEx.Return(SyntaxEx.Invocation(SyntaxEx.MemberAccess("base", "GetHashCode")))); var classDeclaration = SyntaxEx.ClassDeclaration(typeName, Syntax.ParseTypeName("StringValue"), contructor) .AddMembers(equalsOperator, notEqualsOPerator, equalsMethod, getHashCodeMethod) .AddMembers(members.ToArray <MemberDeclarationSyntax>()); var namespaceDeclaration = m_wiki.Files[Wiki.Names.Enums].SingleDescendant <NamespaceDeclarationSyntax>(); m_wiki.Files[Wiki.Names.Enums] = m_wiki.Files[Wiki.Names.Enums].ReplaceNode( namespaceDeclaration, namespaceDeclaration.AddMembers(classDeclaration)); m_enumTypeNames.Add(moduleName, enumType, typeName); return(typeName); }