Mercurial > pub > ImplabNet
diff Implab.ServiceHost/Unity/TypeReferenceParser.cs @ 278:6691aff01de1 v3
Implab: added XmlDefaultSeializer (SerializersPool is now obsolete)
Implab.ServiceHost: rewritten TypeReference (added support for nested types), stable API
author | cin |
---|---|
date | Thu, 03 May 2018 09:59:44 +0300 |
parents | 963b17c275be |
children |
line wrap: on
line diff
--- a/Implab.ServiceHost/Unity/TypeReferenceParser.cs Sat Apr 28 18:48:09 2018 +0300 +++ b/Implab.ServiceHost/Unity/TypeReferenceParser.cs Thu May 03 09:59:44 2018 +0300 @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; namespace Implab.ServiceHost.Unity { @@ -21,10 +22,12 @@ CloseArray, + Plus, + Eof } - readonly Regex _tokens = new Regex(@"([\w\+]+)|\s*([\.{},\[\]])\s*"); + readonly Regex _tokens = new Regex(@"\G(?:([\w]+)|\s*([\+\.{},\[\]])\s*)", RegexOptions.Compiled); TokenType m_token; @@ -83,6 +86,9 @@ case "]": m_token = TokenType.CloseArray; break; + case "+": + m_token = TokenType.Plus; + break; } } return true; @@ -97,7 +103,7 @@ return result; } - string[] ReadTypeName() { + string[] ReadQTypeName() { var parts = new List<string>(); string current = null; @@ -129,31 +135,95 @@ return parts.ToArray(); } + string ReadNQTypeName() { + ReadToken(); + if (Token != TokenType.Word) + ThrowUnexpectedToken(); + return TokenValue; + } + TypeReference ReadTypeReference() { - var parts = ReadTypeName(); + var parts = ReadQTypeName(); if (parts == null) return null; - var typeReference = new TypeReference { - Namespace = string.Join(".", parts, 0, parts.Length - 1), - TypeName = parts[parts.Length - 1] - }; + var genericParameters = ReadGenericParams(); + + var typeReference = TypeReference.Create( + string.Join(".", parts, 0, parts.Length - 1), + parts[parts.Length - 1], + genericParameters.Length + ); + + if (genericParameters.Length > 0 && genericParameters.All(x => x != null)) + typeReference = typeReference.MakeGenericType(genericParameters); + + typeReference = ReadArraySpec(typeReference); + + if(Token == TokenType.Plus) + return ReadNestedType(typeReference); + + return typeReference; + } + + TypeReference ReadNestedType(TypeReference declaringType) { + var name = ReadNQTypeName(); + if(string.IsNullOrEmpty(name)) + throw new FormatException("Nested type name can't be empty"); + ReadToken(); + + var genericParameters = ReadGenericParams(); + + var typeReference = declaringType.Create( + name, + genericParameters.Length + ); - switch (Token) { - case TokenType.OpenList: - typeReference.GenericParameters = ReadTypeReferenceList(); - if (Token != TokenType.CloseList) - ThrowUnexpectedToken(); - ReadToken(); - break; + if (genericParameters.Length > 0 && genericParameters.All(x => x != null)) + typeReference = typeReference.MakeGenericType(genericParameters); + + typeReference = ReadArraySpec(typeReference); + + if(Token == TokenType.Plus) + return ReadNestedType(typeReference); + + return typeReference; + } + + TypeReference[] ReadGenericParams() { + if (Token == TokenType.OpenList) { + var genericParameters = ReadTypeReferenceList(); + if (Token != TokenType.CloseList) + ThrowUnexpectedToken(); + ReadToken(); + + return genericParameters; + } + + return Array.Empty<TypeReference>(); + } + + TypeReference ReadArraySpec(TypeReference typeReference) { + while (Token == TokenType.OpenArray) { + var rank = CountRank(); + if (Token != TokenType.CloseArray) + ThrowUnexpectedToken(); + + typeReference = typeReference.MakeArrayType(rank); + + ReadToken(); } return typeReference; } - int CountDimentions() { - return 0; + int CountRank() { + int rank = 0; + do { + rank++; + } while(ReadToken() && Token == TokenType.Comma); + return rank; } TypeReference[] ReadTypeReferenceList() {