public static string?PrintProgram(ProgramSyntax programSyntax, PrettyPrintOptions options) { if (programSyntax.GetParseDiagnostics().Count > 0) { return(null); } Debug.Assert(options.IndentSize >= 1 && options.IndentSize <= 1000); string indent = options.IndentKindOption == IndentKindOption.Space ? new string(' ', options.IndentSize) : "\t"; string newline = options.NewlineOption switch { NewlineOption.LF => "\n", NewlineOption.CRLF => "\r\n", NewlineOption.CR => "\r", _ => InferNewline(programSyntax) }; var documentBuildVisitor = new DocumentBuildVisitor(); var sb = new StringBuilder(); var document = documentBuildVisitor.BuildDocument(programSyntax); document.Layout(sb, indent, newline); sb.TrimNewLines(); if (options.InsertFinalNewline) { sb.Append(newline); } return(sb.ToString()); }
private static TextSpan GetSpanForRow(ProgramSyntax programSyntax, SyntaxBase declaringSyntax) { // Find the first & last token in the statement var startToken = declaringSyntax.TryFindMostSpecificNodeInclusive(declaringSyntax.Span.Position, x => x is Token) as Token; var endToken = declaringSyntax.TryFindMostSpecificNodeInclusive(declaringSyntax.Span.Position + declaringSyntax.Span.Length, x => x is Token) as Token; // This shouldn't happen, but if it does - fall back to just replacing the statement only if (startToken is null || endToken is null) { return(declaringSyntax.Span); } // If we have leading or trailing trivia (whitespace or comments), take the outermost trivia var startPosSpan = startToken.LeadingTrivia.FirstOrDefault()?.Span ?? startToken.Span; var endPosSpan = endToken.TrailingTrivia.LastOrDefault()?.Span ?? endToken.Span; // If we have a trailing newline, include it in the calculation so that it is removed var followingToken = programSyntax.TryFindMostSpecificNodeInclusive(endPosSpan.Position + endPosSpan.Length, x => x is Token); if (followingToken is Token { Type : TokenType.NewLine } newLineToken) { endPosSpan = newLineToken.Span; } return(TextSpan.Between(startPosSpan, endPosSpan)); }
public Compilation(IResourceTypeProvider resourceTypeProvider, ProgramSyntax programSyntax) { this.resourceTypeProvider = resourceTypeProvider; this.ProgramSyntax = programSyntax; this.lazySemanticModel = new Lazy <SemanticModel>(this.GetSemanticModelInternal, LazyThreadSafetyMode.PublicationOnly); }
public FileSymbol(string name, ProgramSyntax syntax, ImmutableDictionary <string, NamespaceSymbol> importedNamespaces, IEnumerable <LocalScope> outermostScopes, IEnumerable <ParameterSymbol> parameterDeclarations, IEnumerable <VariableSymbol> variableDeclarations, IEnumerable <ResourceSymbol> resourceDeclarations, IEnumerable <ModuleSymbol> moduleDeclarations, IEnumerable <OutputSymbol> outputDeclarations, Uri fileUri) : base(name) { this.Syntax = syntax; this.ImportedNamespaces = importedNamespaces; FileUri = fileUri; this.LocalScopes = outermostScopes.ToImmutableArray(); this.ParameterDeclarations = parameterDeclarations.ToImmutableArray(); this.VariableDeclarations = variableDeclarations.ToImmutableArray(); this.ResourceDeclarations = resourceDeclarations.ToImmutableArray(); this.ModuleDeclarations = moduleDeclarations.ToImmutableArray(); this.OutputDeclarations = outputDeclarations.ToImmutableArray(); this.declarationsByName = this.Declarations.ToLookup(decl => decl.Name, LanguageConstants.IdentifierComparer); }
public static BicepCompletionContext Create(ProgramSyntax syntax, int offset) { var matchingNodes = FindNodesMatchingOffset(syntax, offset); var kind = IsDeclarationContext(matchingNodes, offset) ? BicepCompletionContextKind.Declaration : BicepCompletionContextKind.None; return(new BicepCompletionContext(kind)); }
public override Task <TextEditContainer?> Handle(DocumentFormattingParams request, CancellationToken cancellationToken) { CompilationContext?context = this.compilationManager.GetCompilation(request.TextDocument.Uri); if (context == null) { // we have not yet compiled this document, which shouldn't really happen this.logger.LogError("Document formatting request arrived before file {Uri} could be compiled.", request.TextDocument.Uri); return(Task.FromResult <TextEditContainer?>(null)); } long indentSize = request.Options.TabSize; IndentKindOption indentKindOption = request.Options.InsertSpaces ? IndentKindOption.Space : IndentKindOption.Tab; bool insertFinalNewline = request.Options.ContainsKey("insertFinalNewline") && request.Options.InsertFinalNewline; ProgramSyntax programSyntax = context.ProgramSyntax; PrettyPrintOptions options = new PrettyPrintOptions(NewlineOption.Auto, indentKindOption, indentSize, insertFinalNewline); string?output = PrettyPrinter.PrintProgram(programSyntax, options); if (output == null) { return(Task.FromResult <TextEditContainer?>(null)); } return(Task.FromResult <TextEditContainer?>(new TextEditContainer(new TextEdit { Range = programSyntax.Span.ToRange(context.LineStarts), NewText = output }))); }
public (string, string) GetDescriptionAndText(string?template) { string description = string.Empty; string text = string.Empty; if (!string.IsNullOrWhiteSpace(template)) { Parser parser = new Parser(template); ProgramSyntax programSyntax = parser.Program(); IEnumerable <SyntaxBase> declarations = programSyntax.Declarations; if (declarations.Any() && declarations.First() is StatementSyntax statementSyntax) { text = template.Substring(statementSyntax.Span.Position); ImmutableArray <SyntaxBase> children = programSyntax.Children; if (children.Length > 0 && children[0] is Token firstToken && firstToken is not null && firstToken.LeadingTrivia[0] is SyntaxTrivia syntaxTrivia && syntaxTrivia.Type is SyntaxTriviaType.SingleLineComment) { description = syntaxTrivia.Text.Substring("// ".Length); } } } return(description, text); }
public static string PrintProgram(ProgramSyntax programSyntax, PrettyPrintOptions options) { string indent = options.IndentKindOption == IndentKindOption.Space ? new string(' ', options.IndentSize) : "\t"; string newline = options.NewlineOption switch { NewlineOption.LF => "\n", NewlineOption.CRLF => "\r\n", NewlineOption.CR => "\r", _ => InferNewline(programSyntax) }; var documentBuildVisitor = new DocumentBuildVisitor(); var sb = new StringBuilder(); var document = documentBuildVisitor.BuildDocument(programSyntax); document.Layout(sb, indent, newline); if (options.InsertFinalNewline) { sb.Append(newline); } return(sb.ToString()); }
public static void Validate(ProgramSyntax programSyntax, IDiagnosticWriter diagnosticWriter) { var visitor = new IntegerValidatorVisitor(diagnosticWriter); // visiting writes diagnostics in some cases visitor.Visit(programSyntax); }
public DisabledDiagnosticsCache(ProgramSyntax programSyntax, ImmutableArray <int> lineStarts) { this.programSyntax = programSyntax; this.lineStarts = lineStarts; disableNextLineDiagnosticDirectivesCacheLazy = new Lazy <ImmutableDictionary <int, DisableNextLineDirectiveEndPositionAndCodes> >(() => GetDisableNextLineDiagnosticDirectivesCache()); }
public static ImmutableArray <SyntaxItem> Build(ProgramSyntax syntax) { var visitor = new SyntaxCollectorVisitor(); visitor.VisitProgramSyntax(syntax); return(visitor.syntaxList.ToImmutableArray()); }
public static BicepCompletionContext Create(ProgramSyntax syntax, int offset) { var matchingNodes = FindNodesMatchingOffset(syntax, offset); var kind = ConvertFlag(IsDeclarationStartContext(matchingNodes, offset), BicepCompletionContextKind.DeclarationStart) | GetDeclarationTypeFlags(matchingNodes, offset); return(new BicepCompletionContext(kind)); }
public BicepFile(Uri fileUri, ImmutableArray <int> lineStarts, ProgramSyntax programSyntax) { FileUri = fileUri; LineStarts = lineStarts; ProgramSyntax = programSyntax; Hierarchy = new SyntaxHierarchy(); Hierarchy.AddRoot(ProgramSyntax); }
public override void VisitProgramSyntax(ProgramSyntax syntax) => this.BuildWithConcat(() => { this.PushDocument(NoLine); this.VisitNodes(syntax.Children); this.PushDocument(NoLine); this.Visit(syntax.EndOfFile); });
public BicepFile(Uri fileUri, ImmutableArray <int> lineStarts, ProgramSyntax programSyntax) { FileUri = fileUri; LineStarts = lineStarts; ProgramSyntax = programSyntax; Hierarchy = new SyntaxHierarchy(); Hierarchy.AddRoot(ProgramSyntax); DisabledDiagnosticsCache = new DisabledDiagnosticsCache(ProgramSyntax, lineStarts); }
public override void VisitProgramSyntax(ProgramSyntax syntax) { base.VisitProgramSyntax(syntax); foreach (var diagnostic in syntax.LexerDiagnostics) { this.diagnostics.Add(diagnostic); } }
public IImmutableDictionary <string, FunctionDecl> WaddleProgram(ProgramSyntax program) { foreach (var function in program.FunctionDeclarations) { WaddleFunctionDeclaration(function); } return(_functions.ToImmutableDictionary()); }
public static string PrintAndCheckForParseErrors(ProgramSyntax programSyntax) { var asString = PrettyPrinter.PrintProgram(programSyntax, DefaultOptions); var parsed = ParserHelper.Parse(asString); parsed.GetParseDiagnostics().Should().BeEmpty(); return(asString); }
public static List <SyntaxBase> FindNodesMatchingOffsetExclusive(ProgramSyntax syntax, int offset) { var nodes = new List <SyntaxBase>(); syntax.TryFindMostSpecificNodeExclusive(offset, current => { nodes.Add(current); return(true); }); return(nodes); }
private static string InferNewline(ProgramSyntax programSyntax) { var firstNewLine = (Token?)programSyntax.Children .FirstOrDefault(child => child is Token token && token.Type == TokenType.NewLine); if (firstNewLine != null) { return(StringUtils.NewLineRegex.Match(firstNewLine.Text).Value); } return(Environment.NewLine); }
public override void VisitProgramSyntax(ProgramSyntax syntax) { base.VisitProgramSyntax(syntax); // create bindings for all of the declarations to their corresponding symbol // this is needed to make find all references work correctly // (doing this here to avoid side-effects in the constructor) foreach (DeclaredSymbol declaredSymbol in this.declarations.Values) { this.bindings.Add(declaredSymbol.DeclaringSyntax, declaredSymbol); } }
public override void VisitProgramSyntax(ProgramSyntax syntax) => this.BuildWithConcat(() => { this.documentBlockContexts.Push(new DocumentBlockContext( null, syntax.EndOfFile, syntax.Children.FirstOrDefault(), syntax.Children.LastOrDefault())); base.VisitProgramSyntax(syntax); this.documentBlockContexts.Pop(); });
public override void VisitProgramSyntax(ProgramSyntax syntax) => this.BuildWithConcat(() => { this.PushDocument(NoLine); this.VisitNodes(syntax.Children); if (!syntax.EndOfFile.LeadingTrivia.Any(x => x.Type == SyntaxTriviaType.DisableNextLineDiagnosticsDirective)) { this.PushDocument(NoLine); } this.Visit(syntax.EndOfFile); });
private static List <SyntaxBase> GetAllBoundSymbolReferences(ProgramSyntax program, SemanticModel semanticModel) { return(SyntaxAggregator.Aggregate( program, new List <SyntaxBase>(), (accumulated, current) => { if (current is ISymbolReference symbolReference && TestSyntaxHelper.NodeShouldBeBound(symbolReference)) { accumulated.Add(current); } return accumulated; },
public static BicepCompletionContext Create(ProgramSyntax syntax, int offset) { var matchingNodes = FindNodesMatchingOffset(syntax, offset); var declaration = FindLastNodeOfType <IDeclarationSyntax, SyntaxBase>(matchingNodes, out _); var kind = ConvertFlag(IsDeclarationStartContext(matchingNodes, offset), BicepCompletionContextKind.DeclarationStart) | GetDeclarationTypeFlags(matchingNodes, offset) | ConvertFlag(IsPropertyNameContext(matchingNodes, out var @object), BicepCompletionContextKind.PropertyName) | ConvertFlag(IsPropertyValueContext(matchingNodes, offset, out var property), BicepCompletionContextKind.PropertyValue) | ConvertFlag(IsArrayItemContext(matchingNodes, offset, out var array), BicepCompletionContextKind.ArrayItem); return(new BicepCompletionContext(kind, declaration, @object, property, array)); }
public static ImmutableDictionary <SyntaxBase, Symbol> GetBindings( ProgramSyntax programSyntax, IReadOnlyDictionary <string, DeclaredSymbol> outermostDeclarations, NamespaceResolver namespaceResolver, ImmutableArray <LocalScope> childScopes) { // bind identifiers to declarations var bindings = new Dictionary <SyntaxBase, Symbol>(); var allLocalScopes = ScopeCollectorVisitor.Build(childScopes); var binder = new NameBindingVisitor(outermostDeclarations, bindings, namespaceResolver, allLocalScopes); binder.Visit(programSyntax); return(bindings.ToImmutableDictionary()); }
public override void VisitProgramSyntax(ProgramSyntax syntax) { base.VisitProgramSyntax(syntax); this.diagnosticWriter.WriteMultiple(syntax.LexerDiagnostics); var targetScopeSyntaxes = syntax.Children.OfType <TargetScopeSyntax>().ToList(); if (targetScopeSyntaxes.Count > 1) { foreach (var targetScope in targetScopeSyntaxes) { this.diagnosticWriter.Write(targetScope.Keyword, x => x.TargetScopeMultipleDeclarations()); } } }
private static List <SyntaxBase> GetSymbolReferences(ProgramSyntax program) { return(SyntaxAggregator.Aggregate( program, new List <SyntaxBase>(), (accumulated, current) => { if (current is ISymbolReference) { accumulated.Add(current); } return accumulated; }, accumulated => accumulated)); }
public FileSymbol(string name, ProgramSyntax syntax, IEnumerable <NamespaceSymbol> importedNamespaces, IEnumerable <ParameterSymbol> parameterDeclarations, IEnumerable <VariableSymbol> variableDeclarations, IEnumerable <ResourceSymbol> resourceDeclarations, IEnumerable <OutputSymbol> outputDeclarations) : base(name) { this.Syntax = syntax; this.ImportedNamespaces = importedNamespaces.ToImmutableArray(); this.ParameterDeclarations = parameterDeclarations.ToImmutableArray(); this.VariableDeclarations = variableDeclarations.ToImmutableArray(); this.ResourceDeclarations = resourceDeclarations.ToImmutableArray(); this.OutputDeclarations = outputDeclarations.ToImmutableArray(); }
/// <summary> /// Returnes nodes whose span contains the specified offset from least specific to the most specific. /// </summary> /// <param name="syntax">The program node</param> /// <param name="offset">The offset</param> private static List <SyntaxBase> FindNodesMatchingOffset(ProgramSyntax syntax, int offset) { var nodes = new List <SyntaxBase>(); syntax.TryFindMostSpecificNodeInclusive(offset, current => { // callback is invoked only if node span contains the offset // in inclusive mode, 2 nodes can be returned if cursor is between end of one node and beginning of another // we will pick the node to the left as the winner if (nodes.Any() == false || TextSpan.AreNeighbors(nodes.Last(), current) == false) { nodes.Add(current); } // don't filter out the nodes return(true); }); return(nodes); }