private static IEnumerable<TypeDeclaration> GetTypeDeclarations(NamespaceDeclaration namespaceDeclaration)
		{
			var collector = new TypeCollector();
			return namespaceDeclaration.SyntaxNodes
				.Select(info =>
				{
					Func<TypeDeclarationSyntax, TypeDeclarationSyntaxInfo> selector =
						x => new TypeDeclarationSyntaxInfo(info.CodeFile, x.SyntaxTree == null ? x.Identifier.ValueText : x.GetName(x.SyntaxTree.GetRoot()), x);
					return new { info, selector };
				})
				.SelectMany(x => collector.GetTypes(x.info.Syntax).Select(x.selector))
				.GroupBy(x => x.Name)
				.Select(x => new TypeDeclaration { Name = x.Key, SyntaxNodes = x });
		}
		private async Task<Tuple<Compilation, IEnumerable<ITypeMetric>>> CalculateTypeMetrics(Compilation compilation, NamespaceDeclaration namespaceNodes, Solution solution)
		{
			var comp = compilation;
			var tasks = GetTypeDeclarations(namespaceNodes)
				.Select(async typeNodes =>
				{
					var tuple = await CalculateMemberMetrics(comp, typeNodes, solution).ConfigureAwait(false);
					var metrics = tuple.Item2;
					comp = tuple.Item1;
					return new
					{
						comp,
						typeNodes,
						solution,
						memberMetrics = metrics
					};
				})
					.AsArray();
			var data = await Task.WhenAll(tasks).ConfigureAwait(false);
			var typeMetricsTasks = data
				.Select(async item =>
				{
					var tuple = await CalculateTypeMetrics(item.solution, item.comp, item.typeNodes, item.memberMetrics).ConfigureAwait(false);
					if (tuple == null)
					{
						return null;
					}

					comp = tuple.Item1;
					return tuple.Item2;
				})
				.AsArray();

			var typeMetrics = await Task.WhenAll(typeMetricsTasks).ConfigureAwait(false);
			var array = typeMetrics.Where(x => x != null).AsArray();
			return new Tuple<Compilation, IEnumerable<ITypeMetric>>(comp, array);
		}
		private static async Task<INamespaceMetric> CalculateNamespaceMetrics(Compilation compilation, NamespaceDeclaration namespaceNodes, IEnumerable<ITypeMetric> typeMetrics)
		{
			var namespaceNode = namespaceNodes.SyntaxNodes.FirstOrDefault();
			if (namespaceNode == null)
			{
				return null;
			}

			var tuple = await VerifyCompilation(compilation, namespaceNode).ConfigureAwait(false);
			compilation = tuple.Item1;
			var semanticModel = compilation.GetSemanticModel(tuple.Item3);
			var calculator = new NamespaceMetricsCalculator(semanticModel);
			return calculator.CalculateFrom(namespaceNode, typeMetrics);
		}