/// <summary> /// If the member is generic, construct it with the CrefTypeParameterSymbols that should be in scope. /// </summary> private Symbol ConstructWithCrefTypeParameters(int arity, TypeArgumentListSyntax typeArgumentListSyntax, Symbol symbol) { if (arity > 0) { SeparatedSyntaxList <TypeSyntax> typeArgumentSyntaxes = typeArgumentListSyntax.Arguments; TypeSymbol[] typeArgumentSymbols = new TypeSymbol[arity]; DiagnosticBag unusedDiagnostics = DiagnosticBag.GetInstance(); for (int i = 0; i < arity; i++) { TypeSyntax typeArgumentSyntax = typeArgumentSyntaxes[i]; typeArgumentSymbols[i] = BindType(typeArgumentSyntax, unusedDiagnostics); // Should be in a WithCrefTypeParametersBinder. Debug.Assert(typeArgumentSyntax.ContainsDiagnostics || !typeArgumentSyntax.SyntaxTree.ReportDocumentationCommentDiagnostics() || (!unusedDiagnostics.HasAnyErrors() && typeArgumentSymbols[i] is CrefTypeParameterSymbol)); unusedDiagnostics.Clear(); } unusedDiagnostics.Free(); if (symbol.Kind == SymbolKind.Method) { symbol = ((MethodSymbol)symbol).Construct(typeArgumentSymbols); } else { Debug.Assert(symbol is NamedTypeSymbol); symbol = ((NamedTypeSymbol)symbol).Construct(typeArgumentSymbols); } } return(symbol); }
private static DiagnosticBag DiagnoseCompilation(Compilation compilation, DiagnosticFormatter diagnosticFormatter) { var diagnostics = new DiagnosticBag(); diagnostics.AddRange(compilation.GetParseDiagnostics()); ThrowIfAnyCompilationErrors(diagnostics, diagnosticFormatter); diagnostics.Clear(); return(diagnostics); }
internal static BoundBlock FixCodeBlockProblems(LambdaSymbol lambdaSymbol, Binder lambdaBodyBinder, BoundBlock block, DiagnosticBag diagnostics) { // check for a Lambda that returns a USUAL var usualType = lambdaBodyBinder.Compilation.UsualType(); if (lambdaSymbol.ReturnType != usualType) { return(block); } // handle 2 problems: // 1) no statements, then add a return statement // 2) last statement is a void expression. Then the conversion to USUAL fails var count = block.Statements.Length; List <BoundStatement> newlist = new List <BoundStatement>(); if (count == 0) { var result = new BoundDefaultExpression(block.Syntax, usualType); newlist.Add(new BoundReturnStatement(block.Syntax, RefKind.None, result)); block = block.Update(block.Locals, ImmutableArray <LocalFunctionSymbol> .Empty, newlist.ToImmutableArray <BoundStatement>()); } else { var stmt = block.Statements[count - 1]; if (stmt is BoundReturnStatement && stmt.HasErrors) { BoundExpression expr = (stmt as BoundReturnStatement).ExpressionOpt; // when the last expression is a conversion to USUAL // and there is an error, then this is most likely the conversion from // a void to USUAL. When that happens, then create an extra stmt in the body of the lambda // store the return expression in an expression statement // and return a NIL if (expr is BoundConversion) { var boundConv = expr as BoundConversion; var operand = boundConv.Operand; if (boundConv.Type == usualType && operand.Type.SpecialType == SpecialType.System_Void) { diagnostics.Clear(); for (int i = 0; i < block.Statements.Length - 1; i++) { newlist.Add(block.Statements[i]); } newlist.Add(new BoundExpressionStatement(stmt.Syntax, operand)); var result = new BoundDefaultExpression(stmt.Syntax, usualType); newlist.Add(new BoundReturnStatement(stmt.Syntax, RefKind.None, result)); block = new BoundBlock(block.Syntax, block.Locals, newlist.ToImmutableArray <BoundStatement>()); } } } } return(block); }
/// <summary> /// Removes all <see cref="Diagnostic"/>s that weren't logged using the <see cref="Push"/> method. /// </summary> public virtual void Clear() { _bag.Clear(); }
private bool Compile( string code, string path, DiagnosticBag diagnostics, Session session, Type delegateType, Type returnType, CancellationToken cancellationToken, bool isInteractive, bool isExecute, out CommonCompilation compilation, out Delegate factory) { Debug.Assert(delegateType != null); Debug.Assert(session != null); Debug.Assert(code != null); DiagnosticBag localDiagnostics = diagnostics ?? DiagnosticBag.GetInstance(); IText text = new StringText(code); try { CommonCompilation localCompilation = CreateCompilation(text, path, isInteractive, session, returnType, localDiagnostics); if (localCompilation == null) { Debug.Assert(localDiagnostics.HasAnyErrors()); CompilationError(localDiagnostics, diagnostics); factory = null; compilation = null; return(false); } // throw away all syntax warnings, they will be reported again by emit: localDiagnostics.Clear(); // If we compile just in time for execution the user doesn't have access to the submission compilation just created. // If the previous submission hasn't been executed yet the execution would blow up when invoking the submission factory, // and after that the session would become unusable since there is no way how the user can re-execute the current submission. // So throw here before we save the submission into the session. if (isExecute) { int slotIndex = localCompilation.GetSubmissionSlotIndex(); SessionHelpers.RequirePreviousSubmissionExecuted(session, slotIndex); } // TODO: (tomat) // Current CLR implementation of collectible assemblies doesn't support // references from uncollectible to collectible code. // // We can't emit collectible code if there is a possibility that we will // compile another submission in the session. // // A workaround might be to regenerate all collectible dependencies of an uncollectible // submission as uncollectible. // // For now we explicitly mark sessions as collectible in tests to keep test coverage. bool collectible = session.isCollectible; if (!TryEmitSubmission(localCompilation, localDiagnostics, delegateType, collectible, cancellationToken, out factory)) { Debug.Assert(localDiagnostics.HasAnyErrors()); CompilationError(localDiagnostics, diagnostics); factory = null; compilation = null; return(false); } session.SubmissionCompiled(localCompilation); compilation = localCompilation; return(true); } finally { if (localDiagnostics != diagnostics) { localDiagnostics.Free(); } } }