-
Notifications
You must be signed in to change notification settings - Fork 756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Decorators #1324
Decorators #1324
Conversation
07a5675
to
f5a9a32
Compare
Codecov Report
@@ Coverage Diff @@
## main #1324 +/- ##
==========================================
- Coverage 94.81% 94.76% -0.06%
==========================================
Files 343 351 +8
Lines 17564 18188 +624
Branches 14 14
==========================================
+ Hits 16653 17235 +582
- Misses 911 953 +42
Flags with carried forward coverage won't be shown. Click here to find out more.
|
|
||
namespace Bicep.Core.Syntax | ||
{ | ||
public static class SyntaxFactory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now have multiple similar classes defined in different projects:
- Bicep.Core.Syntax.SyntaxFactory
- Bicep.Decompiler.BicepHelpers.SyntaxHelpers
- Bicep.Core.UnitTests.Utils.TestSyntaxFactory
To make this PR less overwhelming, I'll send a separate PR to reduce them to one class.
src/Bicep.Core/Parsing/Parser.cs
Outdated
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Globalization; | ||
using System.Linq; | ||
using Bicep.Core.Diagnostics; | ||
using Bicep.Core.Extensions; | ||
using Bicep.Core.Navigation; | ||
using Bicep.Core.Syntax; | ||
|
||
namespace Bicep.Core.Parsing | ||
{ | ||
public class Parser | ||
{ | ||
private readonly TokenReader reader; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shenglol - do you know why your PRs show large whitespace diffs? Are there line ending changes here? If so, any way to avoid this? I notice that when I modify code afterwards, I also get large whitespace diffs (presumably to change back to the previous format). It would be good if we can converge on / enforce a standard here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect that the line endings of this file got normalized by someone's Visual Studio settings. The whitespace diffs showed up after I merged the main branch. I feel like we should put a .editorconfig file at the root level and add that as a VS solution item. I submit a PR to do that later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created #1401 to track this.
src/Bicep.Core/Parsing/Parser.cs
Outdated
LanguageConstants.TargetScopeKeyword => this.TargetScope(leadingNodes), | ||
LanguageConstants.ParameterKeyword => this.ParameterDeclaration(leadingNodes), | ||
LanguageConstants.VariableKeyword => this.VariableDeclaration(leadingNodes), | ||
LanguageConstants.ResourceKeyword => this.ResourceDeclaration(leadingNodes), | ||
LanguageConstants.OutputKeyword => this.OutputDeclaration(leadingNodes), | ||
LanguageConstants.ModuleKeyword => this.ModuleDeclaration(leadingNodes), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Out of interest, what are the pros/cons of modelling decorators as part of the declaration syntax, vs as a top-level syntax independent of the declarations? Do you happen to know how this is handled in similar languages (C# or TS for example)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect having the decorators under the declaration makes it easier to process them. Otherwise, you would always need a visitor to collect the preceding decorators. (Or the ability to efficiently get the preceding peer node in the AST.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypeSymbol targetType, | ||
ObjectSyntax? targetObject); | ||
|
||
public class Decorator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decorator [](start = 17, length = 9)
Is there any value in making decorators symbols? It might be helpful with some of the navigation features like hovers to avoid special casing...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about creating a new DecoratorSymbol
type originally, but on second thought modelling them as FunctionSymbol
s makes it easier to leverage all semantic checkers and LSP capablilities we have implemented for function calls (decorators are essentially higher order functions IMHO). Features like hovering is already working:
Do you mind clarifying what "to avoid special casing" means?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can ignore that comment if hovers are already working. I think the hover text will be confusing to our users. We should probably make it more obvious that it's a decorator. (Higher order functions are an advanced concept after all.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that we should make it more obvious that it's a decorator. Maybe showing descriptions below type signatures would help, but I feel like that's something to be implemented in another PR and we probably need to discuss it.
src/Bicep.Core.Samples/Files/InvalidParameters_LF/main.diagnostics.bicep
Show resolved
Hide resolved
|
||
namespace Bicep.Core.Syntax | ||
{ | ||
public abstract class StatementSyntax : SyntaxBase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StatementSyntax [](start = 26, length = 15)
Should we call it DeclarationSyntax to match the file name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah good catch...too bad my ReSharper license expired which should have caught this. I renamed the file to StatementSyntax
though. It's kind of weird if we call it DeclarationSyntax
while it has nothing to do with the IDeclaration
interface. Let me know if StatementSyntax
works.
this.LeadingNodes = leadingNodes.ToImmutableArray(); | ||
} | ||
|
||
public ImmutableArray<SyntaxBase> LeadingNodes { get; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LeadingNodes [](start = 42, length = 12)
I like how adding this class cleaned up all the declarations btw!
At some point (not necessarily in this PR), we should update the parameter snippets and switch them to the decorator syntax. |
It looks like you have to type |
Had a discussion offline with Marcin. The reason why I didn't implement |
Can we create an issue to track this? |
Yep. Created an issue: #1405. |
// If there are dangling decorators and we hit EOF, ask users to add a declration. | ||
// Set the span of the diagnostic so that it's on the line below the last decorator. | ||
var lastNewLine = missingDeclaration.LeadingNodes.Last(node => node is Token { Type: TokenType.NewLine }); | ||
var diagnosticSpan = new TextSpan(lastNewLine.Span.Position + 2, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's due to different line endings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found an off by 1 bug with LF files (added a comment), but otherwise looks great!
Will send a separate PR to fix that soon. |
Added support to decorators. There are some features that I'm planning on adding in follow-up PRs:
The other thing worth mentioning is that the current parameter modifier syntax will continue working. My idea is to give users sometime to migrate to the new syntax. We can drop modifier support before the 0.3 release if there's no major concerns. I've added semantic checking to ban using decorators and modifier at the same time. Once the PR is merged, I'll be working on updating the examples and test files to use decorators (this can take a while and I would expect some helps from the OSS community). Once they are all updated, I'll implement another checker to warn users that parameter modifier is deprecated.
Partially addresses #64.