/// <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 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); }