public async static Task <IImmutableList <SyntaxNode> > GenerateMocksAsync( ILogSink logSink, Language language, string solutionPath, string xmlPath) { if (!File.Exists(xmlPath)) { var message = $"XML input file '{xmlPath}' no found."; logSink.Error(logSource, message); throw new IOException(message); } logSink.Info(logSource, "Loading XML input file '{0}'.", xmlPath); var document = XDocument.Load(xmlPath); var configuration = Configuration.FromXDocument(logSink, document); return(await Generator.GenerateMocksAsync( logSink, language, solutionPath, configuration.GetInterfacePredicate(), configuration.GetNamespaceSelector(), configuration.GetNameSelector(), configuration.GetPlugins())); }
public static IImmutableList <SyntaxNode> GenerateMocks( ILogSink logSink, Language language, IImmutableList <Compilation> compilations, string xmlPath) { logSink = logSink .WithSource(typeof(XmlBasedGenerator)); if (!File.Exists(xmlPath)) { logSink.Error("XML input file '{0}' not found.", xmlPath); return(ImmutableList <SyntaxNode> .Empty); } logSink.Info("Loading XML input file '{0}'.", xmlPath); var document = XDocument.Load(xmlPath); var configuration = Configuration.FromXDocument(logSink, document); return(Generator.GenerateMocks( logSink, language, compilations, configuration.GetPlugins(), configuration.GetInterfacePredicate(), configuration.GetNamespaceSelector(), configuration.GetNameSelector())); }
override public void Error(string value, int verbosity = Int32.MinValue) { if (verbosity > Verbosity) { return; } Sink.Error(ApplyTags(value)); }
public void Log <TState>( MS.LogLevel logLevel, MS.EventId eventId, TState state, Exception exception, Func <TState, Exception, string> formatter) { if (logLevel == MS.LogLevel.Trace) { return; } var message = formatter(state, exception); // Very annoyingly, MSBuild appends new lines onto messages itself. if (message.EndsWith("\r\n")) { message = message.Substring(0, message.Length - 2); } switch (logLevel) { case MS.LogLevel.Debug: logSink.Debug(message); break; case MS.LogLevel.Information: logSink.Info(message); break; case MS.LogLevel.Warning: logSink.Warn(message); break; default: logSink.Error(message); break; } }
/// <inheritdoc /> public SyntaxNode GenerateConfigureBehavior( ILogSink logSink, SyntaxGenerator syntaxGenerator, SemanticModel semanticModel, ISymbol symbol) { logSink.Debug(logSource, "Considering symbol '{0}'.", symbol); var propertySymbol = symbol as IPropertySymbol; var methodSymbol = symbol as IMethodSymbol; INamedTypeSymbol returnType = null; if (propertySymbol != null) { if (propertySymbol.GetMethod == null) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a write-only property.", symbol); return(null); } returnType = propertySymbol.GetMethod.ReturnType as INamedTypeSymbol; } else if (methodSymbol != null) { if (methodSymbol.AssociatedSymbol != null) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a method with an associated symbol.", symbol); return(null); } if (methodSymbol.IsGenericMethod) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a generic method.", symbol); return(null); } returnType = methodSymbol.ReturnType as INamedTypeSymbol; } else { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is neither a property nor a method.", symbol); return(null); } if (returnType == null) { logSink.Warn(logSource, "Ignoring symbol '{0}' because its return type could not be determined (it's probably a generic).", symbol); return(null); } var taskBaseType = semanticModel .Compilation .GetTypeByMetadataName("System.Threading.Tasks.Task"); var genericTaskBaseType = semanticModel .Compilation .GetTypeByMetadataName("System.Threading.Tasks.Task`1"); if (taskBaseType == null || genericTaskBaseType == null) { logSink.Warn(logSource, "Failed to resolve Task classes."); return(null); } var itType = semanticModel .Compilation .GetTypeByMetadataName("PCLMock.It"); if (itType == null) { logSink.Error(logSource, "Failed to resolve It class."); return(null); } var isAnyMethod = itType .GetMembers("IsAny") .Single(); if (isAnyMethod == null) { logSink.Error(logSource, "Failed to resolve IsAny method."); return(null); } var isGenericTask = returnType.IsGenericType && returnType.ConstructedFrom == genericTaskBaseType; var isTask = returnType == taskBaseType; if (!isTask && !isGenericTask) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it does not return a Task or Task<T>.", symbol); return(null); } ITypeSymbol taskType = semanticModel .Compilation .GetSpecialType(SpecialType.System_Boolean); if (isGenericTask) { taskType = returnType.TypeArguments[0]; } var lambdaParameterName = symbol.GetUniqueName(); SyntaxNode lambdaExpression; if (propertySymbol != null) { if (!propertySymbol.IsIndexer) { // GENERATED CODE: // // this // .When(x => x.SymbolName) // .Return(Task.FromResult(default(T))); lambdaExpression = syntaxGenerator.MemberAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), propertySymbol.Name); } else { // GENERATED CODE: // // this // .When(x => x[It.IsAny<P1>(), It.IsAny<P2>() ...) // .Return(Task.FromResult(default(T))); var whenArguments = propertySymbol .Parameters .Select( parameter => syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(itType), syntaxGenerator.GenericName( "IsAny", typeArguments: new[] { parameter.Type })))); lambdaExpression = syntaxGenerator.ElementAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), arguments: whenArguments); } } else { // GENERATED CODE: // // this // .When(x => x.SymbolName(It.IsAny<P1>(), It.IsAny<P2>() ...) // .Return(Task.FromResult(default(T))); var whenArguments = methodSymbol .Parameters .Select( parameter => syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(itType), syntaxGenerator.GenericName( "IsAny", typeArguments: new[] { parameter.Type })))); lambdaExpression = syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), methodSymbol.Name), arguments: whenArguments); } var whenLambdaArgument = syntaxGenerator.ValueReturningLambdaExpression( lambdaParameterName, lambdaExpression); var whenInvocation = syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.ThisExpression(), syntaxGenerator.IdentifierName("When")), whenLambdaArgument); var fromResultInvocation = syntaxGenerator.InvocationExpression( syntaxGenerator.WithTypeArguments( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(taskBaseType), "FromResult"), syntaxGenerator.TypeExpression(taskType)), arguments: new[] { syntaxGenerator.DefaultExpression(taskType) }); var result = syntaxGenerator.ExpressionStatement( syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( whenInvocation, syntaxGenerator.IdentifierName("Return")), arguments: new[] { fromResultInvocation })); return(result); }
/// <inheritdoc /> public SyntaxNode GenerateConfigureBehavior( ILogSink logSink, SyntaxGenerator syntaxGenerator, SemanticModel semanticModel, ISymbol symbol) { logSink.Debug(logSource, "Considering symbol '{0}'.", symbol); var propertySymbol = symbol as IPropertySymbol; var methodSymbol = symbol as IMethodSymbol; INamedTypeSymbol returnType = null; if (propertySymbol != null) { if (propertySymbol.GetMethod == null) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a write-only property.", symbol); return(null); } returnType = propertySymbol.GetMethod.ReturnType as INamedTypeSymbol; } else if (methodSymbol != null) { if (methodSymbol.AssociatedSymbol != null) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a method with an associated symbol.", symbol); return(null); } if (methodSymbol.IsGenericMethod) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a generic method.", symbol); return(null); } returnType = methodSymbol.ReturnType as INamedTypeSymbol; } else { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is neither a property nor a method.", symbol); return(null); } if (returnType == null) { logSink.Warn(logSource, "Ignoring symbol '{0}' because its return type could not be determined (it's probably a generic).", symbol); return(null); } var disposableInterfaceType = semanticModel .Compilation .GetTypeByMetadataName("System.IDisposable"); if (disposableInterfaceType == null) { logSink.Warn(logSource, "Failed to resolve IDisposable type."); return(null); } if (returnType != disposableInterfaceType) { logSink.Debug(logSource, "Ignoring symbol '{0}' because its return type is not IDisposable."); return(null); } var disposableType = semanticModel .Compilation .GetTypeByMetadataName("System.Reactive.Disposables.Disposable"); if (disposableType == null) { logSink.Debug(logSource, "Ignoring symbol '{0}' because Disposable type could not be resolved (probably a missing reference to System.Reactive.Core)."); return(null); } var itType = semanticModel .Compilation .GetTypeByMetadataName("PCLMock.It"); if (itType == null) { logSink.Error(logSource, "Failed to resolve It class."); return(null); } var isAnyMethod = itType .GetMembers("IsAny") .Single(); if (isAnyMethod == null) { logSink.Error(logSource, "Failed to resolve IsAny method."); return(null); } var lambdaParameterName = symbol.GetUniqueName(); SyntaxNode lambdaExpression; if (propertySymbol != null) { if (!propertySymbol.IsIndexer) { // GENERATED CODE: // // this // .When(x => x.SymbolName) // .Return(Disposable.Empty); lambdaExpression = syntaxGenerator.MemberAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), propertySymbol.Name); } else { // GENERATED CODE: // // this // .When(x => x[It.IsAny<P1>(), It.IsAny<P2>() ...) // .Return(Disposable.Empty); var whenArguments = propertySymbol .Parameters .Select( parameter => syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(itType), syntaxGenerator.GenericName( "IsAny", typeArguments: new[] { parameter.Type })))); lambdaExpression = syntaxGenerator.ElementAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), arguments: whenArguments); } } else { // GENERATED CODE: // // this // .When(x => x.SymbolName(It.IsAny<P1>(), It.IsAny<P2>() ...) // .Return(Disposable.Empty); var whenArguments = methodSymbol .Parameters .Select( parameter => syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(itType), syntaxGenerator.GenericName( "IsAny", typeArguments: new[] { parameter.Type })))); lambdaExpression = syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), methodSymbol.Name), arguments: whenArguments); } var whenLambdaArgument = syntaxGenerator.ValueReturningLambdaExpression( lambdaParameterName, lambdaExpression); var whenInvocation = syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.ThisExpression(), syntaxGenerator.IdentifierName("When")), whenLambdaArgument); var result = syntaxGenerator.ExpressionStatement( syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( whenInvocation, syntaxGenerator.IdentifierName("Return")), arguments: new[] { syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(disposableType), syntaxGenerator.IdentifierName("Empty")) })); return(result); }
/// <inheritdoc /> public SyntaxNode GenerateConfigureBehavior( ILogSink logSink, SyntaxGenerator syntaxGenerator, SemanticModel semanticModel, ISymbol symbol) { logSink.Debug(logSource, "Considering symbol '{0}'.", symbol); var propertySymbol = symbol as IPropertySymbol; var methodSymbol = symbol as IMethodSymbol; INamedTypeSymbol returnType = null; if (propertySymbol != null) { if (propertySymbol.GetMethod == null) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a write-only property.", symbol); return(null); } returnType = propertySymbol.GetMethod.ReturnType as INamedTypeSymbol; } else if (methodSymbol != null) { if (methodSymbol.AssociatedSymbol != null) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a method with an associated symbol.", symbol); return(null); } if (methodSymbol.IsGenericMethod) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a generic method.", symbol); return(null); } returnType = methodSymbol.ReturnType as INamedTypeSymbol; } else { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is neither a property nor a method.", symbol); return(null); } if (returnType == null) { logSink.Warn(logSource, "Ignoring symbol '{0}' because its return type could not be determined (it's probably a sgeneric).", symbol); return(null); } var observableInterfaceType = semanticModel .Compilation .GetTypeByMetadataName("System.IObservable`1"); var observableType = semanticModel .Compilation .GetTypeByMetadataName("System.Reactive.Linq.Observable"); if (observableInterfaceType == null) { logSink.Warn(logSource, "Failed to resolve System.IObservable<T>."); return(null); } if (observableType == null) { logSink.Warn(logSource, "Failed to resolve System.Reactive.Linq.Observable."); return(null); } var itType = semanticModel .Compilation .GetTypeByMetadataName("PCLMock.It"); if (itType == null) { logSink.Error(logSource, "Failed to resolve It class."); return(null); } var isAnyMethod = itType .GetMembers("IsAny") .Single(); if (isAnyMethod == null) { logSink.Error(logSource, "Failed to resolve IsAny method."); return(null); } var isObservable = returnType.IsGenericType && returnType.ConstructedFrom == observableInterfaceType; if (!isObservable) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it does not return IObservable<T>.", symbol); return(null); } var observableInnerType = returnType.TypeArguments[0]; var lambdaParameterName = symbol.GetUniqueName(); SyntaxNode lambdaExpression; if (propertySymbol != null) { if (!propertySymbol.IsIndexer) { // GENERATED CODE: // // this // .When(x => x.SymbolName) // .Return(Observable.Empty<T>()); lambdaExpression = syntaxGenerator.MemberAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), propertySymbol.Name); } else { // GENERATED CODE: // // this // .When(x => x[It.IsAny<P1>(), It.IsAny<P2>() ...) // .Return(Observable.Empty<T>()); var whenArguments = propertySymbol .Parameters .Select( parameter => syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(itType), syntaxGenerator.GenericName( "IsAny", typeArguments: new[] { parameter.Type })))); lambdaExpression = syntaxGenerator.ElementAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), arguments: whenArguments); } } else { // GENERATED CODE: // // this // .When(x => x.SymbolName(It.IsAny<P1>(), It.IsAny<P2>() ...) // .Return(Observable.Return<T>(default(T))); var whenArguments = methodSymbol .Parameters .Select( parameter => syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(itType), syntaxGenerator.GenericName( "IsAny", typeArguments: new[] { parameter.Type })))); lambdaExpression = syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), methodSymbol.Name), arguments: whenArguments); } var whenLambdaArgument = syntaxGenerator.ValueReturningLambdaExpression( lambdaParameterName, lambdaExpression); var whenInvocation = syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.ThisExpression(), syntaxGenerator.IdentifierName("When")), whenLambdaArgument); SyntaxNode observableInvocation; if (propertySymbol != null) { // properties are given collection semantics by returning Observable.Empty<T>() observableInvocation = syntaxGenerator.InvocationExpression( syntaxGenerator.WithTypeArguments( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(observableType), "Empty"), syntaxGenerator.TypeExpression(observableInnerType))); } else { // methods are given async operation semantics by returning Observable.Return(default(T)) observableInvocation = syntaxGenerator.InvocationExpression( syntaxGenerator.WithTypeArguments( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(observableType), "Return"), syntaxGenerator.TypeExpression(observableInnerType)), arguments: new[] { syntaxGenerator.DefaultExpression(observableInnerType) }); } var result = syntaxGenerator.ExpressionStatement( syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( whenInvocation, syntaxGenerator.IdentifierName("Return")), arguments: new[] { observableInvocation })); return(result); }
public void Flush() { _sink.Error(_entry); }
/// <inheritdoc /> public SyntaxNode GenerateConfigureBehavior( ILogSink logSink, SyntaxGenerator syntaxGenerator, SemanticModel semanticModel, ISymbol symbol) { logSink.Debug(logSource, "Considering symbol '{0}'.", symbol); var propertySymbol = symbol as IPropertySymbol; var methodSymbol = symbol as IMethodSymbol; INamedTypeSymbol returnType = null; if (propertySymbol != null) { if (propertySymbol.GetMethod == null) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a write-only property.", symbol); return(null); } returnType = propertySymbol.GetMethod.ReturnType as INamedTypeSymbol; } else if (methodSymbol != null) { if (methodSymbol.AssociatedSymbol != null) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a method with an associated symbol.", symbol); return(null); } if (methodSymbol.IsGenericMethod) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is a generic method.", symbol); return(null); } returnType = methodSymbol.ReturnType as INamedTypeSymbol; } else { logSink.Debug(logSource, "Ignoring symbol '{0}' because it is neither a property nor a method.", symbol); return(null); } if (returnType == null) { logSink.Warn(logSource, "Ignoring symbol '{0}' because its return type could not be determined (it's probably a generic).", symbol); return(null); } if (!returnType.IsGenericType) { logSink.Debug(logSource, "Ignoring symbol '{0}' because its return type is not a generic type, so it cannot be one of the supported collection types."); return(null); } SyntaxNode returnValueSyntax; if (!TryGetReturnValueSyntaxForEnumerableReturnType(logSink, syntaxGenerator, semanticModel, returnType, out returnValueSyntax) && !TryGetReturnValueSyntaxForCollectionReturnType(logSink, syntaxGenerator, semanticModel, returnType, out returnValueSyntax) && !TryGetReturnValueSyntaxForDictionaryReturnType(logSink, syntaxGenerator, semanticModel, returnType, out returnValueSyntax) && !TryGetReturnValueSyntaxForSetReturnType(logSink, syntaxGenerator, semanticModel, returnType, out returnValueSyntax) && !TryGetReturnValueSyntaxForImmutableListReturnType(logSink, syntaxGenerator, semanticModel, returnType, out returnValueSyntax) && !TryGetReturnValueSyntaxForImmutableDictionaryReturnType(logSink, syntaxGenerator, semanticModel, returnType, out returnValueSyntax) && !TryGetReturnValueSyntaxForImmutableQueueReturnType(logSink, syntaxGenerator, semanticModel, returnType, out returnValueSyntax) && !TryGetReturnValueSyntaxForImmutableSetReturnType(logSink, syntaxGenerator, semanticModel, returnType, out returnValueSyntax) && !TryGetReturnValueSyntaxForImmutableStackReturnType(logSink, syntaxGenerator, semanticModel, returnType, out returnValueSyntax)) { logSink.Debug(logSource, "Ignoring symbol '{0}' because it does not return a supported collection type.", symbol); return(null); } var itType = semanticModel .Compilation .GetTypeByMetadataName("PCLMock.It"); if (itType == null) { logSink.Error(logSource, "Failed to resolve It class."); return(null); } var isAnyMethod = itType .GetMembers("IsAny") .Single(); if (isAnyMethod == null) { logSink.Error(logSource, "Failed to resolve IsAny method."); return(null); } var lambdaParameterName = symbol.GetUniqueName(); SyntaxNode lambdaExpression; if (propertySymbol != null) { if (!propertySymbol.IsIndexer) { // GENERATED CODE: // // this // .When(x => x.SymbolName) // .Return(returnValueSyntax); lambdaExpression = syntaxGenerator.MemberAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), propertySymbol.Name); } else { // GENERATED CODE: // // this // .When(x => x[It.IsAny<P1>(), It.IsAny<P2>() ...) // .Return(returnValueSyntax); var whenArguments = propertySymbol .Parameters .Select( parameter => syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(itType), syntaxGenerator.GenericName( "IsAny", typeArguments: new[] { parameter.Type })))); lambdaExpression = syntaxGenerator.ElementAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), arguments: whenArguments); } } else { // GENERATED CODE: // // this // .When(x => x.SymbolName(It.IsAny<P1>(), It.IsAny<P2>() ...) // .Return(returnValueSyntax); var whenArguments = methodSymbol .Parameters .Select( parameter => syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.TypeExpression(itType), syntaxGenerator.GenericName( "IsAny", typeArguments: new[] { parameter.Type })))); lambdaExpression = syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.IdentifierName(lambdaParameterName), methodSymbol.Name), arguments: whenArguments); } var whenLambdaArgument = syntaxGenerator.ValueReturningLambdaExpression( lambdaParameterName, lambdaExpression); var whenInvocation = syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( syntaxGenerator.ThisExpression(), syntaxGenerator.IdentifierName("When")), whenLambdaArgument); var result = syntaxGenerator.ExpressionStatement( syntaxGenerator.InvocationExpression( syntaxGenerator.MemberAccessExpression( whenInvocation, syntaxGenerator.IdentifierName("Return")), arguments: new[] { returnValueSyntax })); return(result); }