public void ValidDisableNextLineDiagnosticsDirective_WithTrailingWhiteSpaceFollowedByComment_ShouldLexCorrectly() { string text = "#disable-next-line BCP226 // test"; var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(text), diagnosticWriter); lexer.Lex(); diagnosticWriter.GetDiagnostics().Should().BeEmpty(); var tokens = lexer.GetTokens(); tokens.Count().Should().Be(1); var leadingTrivia = tokens.First().LeadingTrivia; leadingTrivia.Count().Should().Be(3); leadingTrivia.Should().SatisfyRespectively( x => { x.Text.Should().Be("#disable-next-line BCP226"); x.Type.Should().Be(SyntaxTriviaType.DisableNextLineDiagnosticsDirective); }, x => { x.Text.Should().Be(" "); x.Type.Should().Be(SyntaxTriviaType.Whitespace); }, x => { x.Text.Should().Be("// test"); x.Type.Should().Be(SyntaxTriviaType.SingleLineComment); }); }
public void ValidDisableNextLineDiagnosticsDirective_ShouldLexCorrectly() { string text = "#disable-next-line BCP226"; var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(text), diagnosticWriter); lexer.Lex(); diagnosticWriter.GetDiagnostics().Should().BeEmpty(); var tokens = lexer.GetTokens(); tokens.Count().Should().Be(1); var leadingTrivia = tokens.First().LeadingTrivia; leadingTrivia.Count().Should().Be(1); var disableNextLineSyntaxTrivia = leadingTrivia.First() as DisableNextLineDiagnosticsSyntaxTrivia; disableNextLineSyntaxTrivia.Should().NotBeNull(); disableNextLineSyntaxTrivia !.DiagnosticCodes.Count().Should().Be(1); var firstCode = disableNextLineSyntaxTrivia.DiagnosticCodes.First(); firstCode.Text.Should().Be("BCP226"); firstCode.Span.Should().Be(new TextSpan(19, 6)); disableNextLineSyntaxTrivia.Type.Should().Be(SyntaxTriviaType.DisableNextLineDiagnosticsDirective); disableNextLineSyntaxTrivia.Text.Should().Be(text); disableNextLineSyntaxTrivia.Span.Should().Be(new TextSpan(0, 25)); }
public void DisableNextLineDiagnosticsDirectiveWithLeadingWhiteSpace_ShouldLexCorrectly() { var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(" #disable-next-line no-unused-params"), diagnosticWriter); lexer.Lex(); diagnosticWriter.GetDiagnostics().Should().BeEmpty(); var endOfFileToken = lexer.GetTokens().First(x => x.Type == TokenType.EndOfFile); endOfFileToken.Should().NotBeNull(); var leadingTrivia = endOfFileToken.LeadingTrivia; leadingTrivia.Count().Should().Be(2); leadingTrivia.Should().SatisfyRespectively( x => { x.Type.Should().Be(SyntaxTriviaType.Whitespace); }, x => { x.Type.Should().Be(SyntaxTriviaType.DisableNextLineDiagnosticsDirective); }); }
public void DisableNextLineDiagnosticsDirectiveWithInvalidTrailingCharacter_ShouldLexCorrectly() { var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow("#disable-next-line BCP037|"), diagnosticWriter); lexer.Lex(); var diagnostics = diagnosticWriter.GetDiagnostics(); diagnostics.Should().SatisfyRespectively( x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP001"); x.Message.Should().Be("The following token is not recognized: \"|\"."); }); var tokens = lexer.GetTokens(); var leadingTrivia = tokens[0].LeadingTrivia; leadingTrivia.Count().Should().Be(1); leadingTrivia.Should().SatisfyRespectively( x => { x.Type.Should().Be(SyntaxTriviaType.DisableNextLineDiagnosticsDirective); x.Text.Should().Be("#disable-next-line BCP037"); }); }
public void ValidDisableNextLineDiagnosticsDirective_WithinResourceAndWithTrailingWhiteSpace_ShouldLexCorrectly() { string text = @"resource vm 'Microsoft.Compute/virtualMachines@2020-12-01' = { #disable-next-line BCP226 properties: vmProperties }"; var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(text), diagnosticWriter); lexer.Lex(); diagnosticWriter.GetDiagnostics().Should().BeEmpty(); var tokens = lexer.GetTokens(); tokens.Count().Should().Be(13); var leadingTrivia = tokens.ElementAt(6).LeadingTrivia; leadingTrivia.Count().Should().Be(2); leadingTrivia.Should().SatisfyRespectively( x => { x.Text.Should().Be("#disable-next-line BCP226"); x.Type.Should().Be(SyntaxTriviaType.DisableNextLineDiagnosticsDirective); }, x => { x.Text.Should().Be(" "); x.Type.Should().Be(SyntaxTriviaType.Whitespace); }); }
private void AssignTypeWithDiagnostics(SyntaxBase syntax, Func <IDiagnosticWriter, ITypeReference> assignFunc) => AssignTypeWithCaching(syntax, () => { var diagnosticWriter = ToListDiagnosticWriter.Create(); var reference = assignFunc(diagnosticWriter); return(new TypeAssignment(reference, diagnosticWriter.GetDiagnostics())); });
private static void RunSingleTokenTest(string text, TokenType expectedTokenType, string expectedMessage, string expectedCode, int expectedStartPosition = 0, int?expectedLength = null, string?expectedTokenText = null) { expectedTokenText ??= text; expectedLength ??= text.Length - expectedStartPosition; var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(text), diagnosticWriter); lexer.Lex(); var tokens = lexer.GetTokens().ToImmutableArray(); tokens.Should().HaveCount(2); tokens.Select(t => t.Type).Should().Equal(expectedTokenType, TokenType.EndOfFile); tokens.First().Text.Should().Be(expectedTokenText); var errors = diagnosticWriter.GetDiagnostics(); errors.Should().HaveCount(1); var error = errors.Single(); error.Message.Should().Be(expectedMessage); error.Code.Should().Be(expectedCode); error.Span.Position.Should().Be(expectedStartPosition); error.Span.Length.Should().Be(expectedLength); }
public void UnterminatedStringUnexpectedNewline_ShouldBeRecognizedWithError() { var text = "'unfinished\n'even more unfinished\r\n'test'"; var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(text), diagnosticWriter); lexer.Lex(); var tokens = lexer.GetTokens().ToImmutableArray(); tokens.Should().HaveCount(6); tokens.Select(t => t.Type).Should().Equal(TokenType.StringComplete, TokenType.NewLine, TokenType.StringComplete, TokenType.NewLine, TokenType.StringComplete, TokenType.EndOfFile); var expectedTexts = new[] { "'unfinished", "\n", "'even more unfinished", "\r\n", "'test'", string.Empty }; tokens.Select(t => t.Text).Should().Equal(expectedTexts); tokens.Select(t => t.Span.Position).Should().Equal(expectedTexts.Select((s, i) => expectedTexts.Take(i).Select(s => s.Length).Sum())); tokens.Select(t => t.Span.Length).Should().Equal(expectedTexts.Select(s => s.Length)); }
public void NonExpressionShouldProduceNoViolations(string displayName, SyntaxBase expression) { var diagnosticWriter = ToListDiagnosticWriter.Create(); TypeValidator.GetCompileTimeConstantViolation(expression, diagnosticWriter); diagnosticWriter.GetDiagnostics().Should().BeEmpty(); }
public static EmitLimitationInfo Calculate(SemanticModel.SemanticModel semanticModel) { var diagnosticWriter = ToListDiagnosticWriter.Create(); var moduleScopeData = GetSupportedScopeInfo(semanticModel, diagnosticWriter); return(new EmitLimitationInfo(diagnosticWriter.GetDiagnostics(), moduleScopeData)); }
public void NonLiteralExpression_IsLiteralExpression_ShouldReturnViolations(string displayName, SyntaxBase expression) { var diagnosticWriter = ToListDiagnosticWriter.Create(); TypeValidator.GetCompileTimeConstantViolation(expression, diagnosticWriter); diagnosticWriter.GetDiagnostics().Should().NotBeEmpty(); }
private IEnumerable <Token> GetLineEndingTokens(string contents) { var lexer = new Lexer(new SlidingTextWindow(contents), ToListDiagnosticWriter.Create()); lexer.Lex(); return(lexer.GetTokens().Where(token => token.Type == TokenType.NewLine)); }
public static IReadOnlyList <IDiagnostic> GetParseDiagnostics(this SyntaxBase syntax) { var diagnosticWriter = ToListDiagnosticWriter.Create(); var parseErrorVisitor = new ParseDiagnosticsVisitor(diagnosticWriter); parseErrorVisitor.Visit(syntax); return(diagnosticWriter.GetDiagnostics()); }
/// <summary> /// Gets all the analyzer diagnostics unsorted. /// </summary> /// <returns></returns> public IReadOnlyList <IDiagnostic> GetAnalyzerDiagnostics() { var diagnostics = LinterAnalyzer.Analyze(this); var diagnosticWriter = ToListDiagnosticWriter.Create(); diagnosticWriter.WriteMultiple(diagnostics); return(diagnosticWriter.GetDiagnostics()); }
public static EmitLimitationInfo Calculate(SemanticModel model) { var diagnosticWriter = ToListDiagnosticWriter.Create(); var moduleScopeData = GetSupportedScopeInfo(model, diagnosticWriter); var resourceScopeData = GetResoureScopeInfo(model, diagnosticWriter); DeployTimeConstantVisitor.ValidateDeployTimeConstants(model, diagnosticWriter); return(new EmitLimitationInfo(diagnosticWriter.GetDiagnostics(), moduleScopeData, resourceScopeData)); }
public void LexerShouldProduceValidStringLiteralTokensOnValidFiles(DataSet dataSet) { var lexer = new Lexer(new SlidingTextWindow(dataSet.Bicep), ToListDiagnosticWriter.Create()); lexer.Lex(); foreach (Token stringToken in lexer.GetTokens().Where(token => token.Type == TokenType.StringComplete)) { Lexer.TryGetStringValue(stringToken).Should().NotBeNull($"because string token at span {stringToken.Span} should have a string value. Token Text = {stringToken.Text}"); } }
public void CompleteStringsWithUnicodeEscapes_ShouldLexCorrectly(string text) { var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(text), diagnosticWriter); lexer.Lex(); diagnosticWriter.GetDiagnostics().Should().BeEmpty(); lexer.GetTokens().Select(t => t.Type).Should().Equal(TokenType.StringComplete, TokenType.EndOfFile); }
public Parser(string text) { // treating the lexer as an implementation detail of the parser var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(text), diagnosticWriter); lexer.Lex(); this.lexerDiagnostics = diagnosticWriter.GetDiagnostics().ToImmutableArray(); this.reader = new TokenReader(lexer.GetTokens()); }
public void LexerShouldRoundtrip(DataSet dataSet) { var lexer = new Lexer(new SlidingTextWindow(dataSet.Bicep), ToListDiagnosticWriter.Create()); lexer.Lex(); var serialized = new StringBuilder(); new TokenWriter(serialized).WriteTokens(lexer.GetTokens()); serialized.ToString().Should().Be(dataSet.Bicep, "because the lexer should not lose information"); }
public static EmitLimitationInfo Calculate(SemanticModel model) { var diagnosticWriter = ToListDiagnosticWriter.Create(); var moduleScopeData = ScopeHelper.GetModuleScopeInfo(model, diagnosticWriter); var resourceScopeData = ScopeHelper.GetResoureScopeInfo(model, diagnosticWriter); DeployTimeConstantVisitor.ValidateDeployTimeConstants(model, diagnosticWriter); diagnosticWriter.WriteMultiple(DetectDuplicateNames(model, resourceScopeData, moduleScopeData)); return(new EmitLimitationInfo(diagnosticWriter.GetDiagnostics(), moduleScopeData, resourceScopeData)); }
/// <summary> /// Gets all the semantic diagnostics unsorted. Does not include parser and lexer diagnostics. /// </summary> /// <returns></returns> public IReadOnlyList <Diagnostic> GetSemanticDiagnostics() { var diagnosticWriter = ToListDiagnosticWriter.Create(); var visitor = new SemanticDiagnosticVisitor(diagnosticWriter); visitor.Visit(this.Root); var typeValidationDiagnostics = typeManager.GetAllDiagnostics(); diagnosticWriter.WriteMultiple(typeValidationDiagnostics); return(diagnosticWriter.GetDiagnostics()); }
public void LexerShouldProduceValidTokenLocations(DataSet dataSet) { var lexer = new Lexer(new SlidingTextWindow(dataSet.Bicep), ToListDiagnosticWriter.Create()); lexer.Lex(); foreach (Token token in lexer.GetTokens()) { // lookup the text of the token in original contents by token's span string tokenText = dataSet.Bicep[new Range(token.Span.Position, token.GetEndPosition())]; tokenText.Should().Be(token.Text, "because token text at location should match original contents at the same location"); } }
public void Multiline_strings_should_lex_correctly(string text, string expectedValue) { var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(text), diagnosticWriter); lexer.Lex(); lexer.GetTokens().Select(t => t.Type).Should().Equal(TokenType.MultilineString, TokenType.EndOfFile); var multilineToken = lexer.GetTokens().First(); multilineToken.Text.Should().Be(text); Lexer.TryGetMultilineStringValue(multilineToken).Should().Be(expectedValue); }
/// <summary> /// Gets all the analyzer diagnostics unsorted. /// </summary> /// <returns></returns> public IReadOnlyList <IDiagnostic> GetAnalyzerDiagnostics(ConfigHelper?overrideConfig = default) { if (overrideConfig != default) { LinterAnalyzer.OverrideConfig(overrideConfig); } var diagnostics = LinterAnalyzer.Analyze(this, overrideConfig); var diagnosticWriter = ToListDiagnosticWriter.Create(); diagnosticWriter.WriteMultiple(diagnostics); return(diagnosticWriter.GetDiagnostics()); }
public void Unterminated_multiline_strings_should_attach_a_diagnostic(string text) { var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(text), diagnosticWriter); lexer.Lex(); lexer.GetTokens().Select(t => t.Type).Should().Equal(TokenType.MultilineString, TokenType.EndOfFile); var diagnostics = diagnosticWriter.GetDiagnostics().ToList(); diagnostics.Should().HaveCount(1); var diagnostic = diagnostics.Single(); diagnostic.Code.Should().Be("BCP140"); diagnostic.Message.Should().Be($"The multi-line string at this location is not terminated. Terminate it with \"'''\"."); }
public void MissingCodesInDisableNextLineDiagnosticsDirective_ShouldBeRecognizedWithError() { var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow("#disable-next-line"), diagnosticWriter); lexer.Lex(); var diagnostics = diagnosticWriter.GetDiagnostics(); diagnostics.Should().SatisfyRespectively( x => { x.Level.Should().Be(DiagnosticLevel.Error); x.Code.Should().Be("BCP226"); x.Message.Should().Be("Expected at least one diagnostic code at this location. Valid format is \"#disable-next-line diagnosticCode1 diagnosticCode2 ...\""); }); }
public static EmitLimitationInfo Calculate(SemanticModel model) { var diagnosticWriter = ToListDiagnosticWriter.Create(); var moduleScopeData = ScopeHelper.GetModuleScopeInfo(model, diagnosticWriter); var resourceScopeData = ScopeHelper.GetResourceScopeInfo(model, diagnosticWriter); DeployTimeConstantValidator.Validate(model, diagnosticWriter); ForSyntaxValidatorVisitor.Validate(model, diagnosticWriter); FunctionPlacementValidatorVisitor.Validate(model, diagnosticWriter); DetectDuplicateNames(model, diagnosticWriter, resourceScopeData, moduleScopeData); DetectIncorrectlyFormattedNames(model, diagnosticWriter); DetectUnexpectedResourceLoopInvariantProperties(model, diagnosticWriter); DetectUnexpectedModuleLoopInvariantProperties(model, diagnosticWriter); DetectUnsupportedModuleParameterAssignments(model, diagnosticWriter); return(new EmitLimitationInfo(diagnosticWriter.GetDiagnostics(), moduleScopeData, resourceScopeData)); }
public void InvalidUnicodeEscapes_ShouldProduceExpectedDiagnostic(string text, string expectedSpanText) { var diagnosticWriter = ToListDiagnosticWriter.Create(); var lexer = new Lexer(new SlidingTextWindow(text), diagnosticWriter); lexer.Lex(); lexer.GetTokens().Select(t => t.Type).Should().Equal(TokenType.StringComplete, TokenType.EndOfFile); var diagnostics = diagnosticWriter.GetDiagnostics().ToList(); diagnostics.Should().HaveCount(1); var diagnostic = diagnostics.Single(); diagnostic.Code.Should().Be("BCP133"); diagnostic.Message.Should().Be(@"The unicode escape sequence is not valid. Valid unicode escape sequences range from \u{0} to \u{10FFFF}."); var spanText = text[new Range(diagnostic.Span.Position, diagnostic.Span.GetEndPosition())]; spanText.Should().Be(expectedSpanText); }
/// <summary> /// Gets all the semantic diagnostics unsorted. Does not include parser and lexer diagnostics. /// </summary> /// <returns></returns> public IReadOnlyList <IDiagnostic> GetSemanticDiagnostics() { var diagnosticWriter = ToListDiagnosticWriter.Create(); var visitor = new SemanticDiagnosticVisitor(diagnosticWriter); visitor.Visit(this.Root); foreach (var missingDeclarationSyntax in this.SourceFile.ProgramSyntax.Children.OfType <MissingDeclarationSyntax>()) { // Trigger type checking manually as missing declarations are not bound to any symbol. this.TypeManager.GetTypeInfo(missingDeclarationSyntax); } var typeValidationDiagnostics = TypeManager.GetAllDiagnostics(); diagnosticWriter.WriteMultiple(typeValidationDiagnostics); diagnosticWriter.WriteMultiple(EmitLimitationInfo.Diagnostics); return(diagnosticWriter.GetDiagnostics()); }
public void LexerShouldProduceContiguousSpans(DataSet dataSet) { var lexer = new Lexer(new SlidingTextWindow(dataSet.Bicep), ToListDiagnosticWriter.Create()); lexer.Lex(); int visitedPosition = 0; // local function void VisitSpan(TextSpan span, string text) { // the token should begin at the position where the previous token ended span.Position.Should().Be(visitedPosition, $"because token or trivia '{text}' at span '{span}' should begin at position {visitedPosition}."); // cover the span of the token visitedPosition += span.Length; } // local function void VisitTrivia(IEnumerable <SyntaxTrivia> trivia) { foreach (var trivium in trivia) { VisitSpan(trivium.Span, trivium.Text); } } var tokens = lexer.GetTokens(); foreach (var token in tokens) { VisitTrivia(token.LeadingTrivia); VisitSpan(token.Span, token.Text); VisitTrivia(token.TrailingTrivia); } // when we're done visited position should match the length of the file visitedPosition.Should().Be(dataSet.Bicep.Length); }