Commit Graph

439 Commits

Author SHA1 Message Date
Andrew Scott 8758006acc refactor(language-service): create getReferencesAtPosition stubs (#39829)
Create stubs for getTypeDefinitionAtPosition for both VE and Ivy Language Service
implementations. This will prevent failed requests when it is implemented on the vscode plugin side.

PR Close #39829
2020-11-24 14:19:48 -08:00
Keen Yee Liau 9aaa86967d build(language-service): include sources for Ivy LS (#39748)
We need to expose the declaration files for Ivy sources so that they can
be consumed by the Angular language server (`@angular/language-server`).

PR Close #39748
2020-11-20 09:23:45 -08:00
Andrew Scott fae2769f44 refactor(compiler-cli): Add additional shim locations to reference and variable symbols (#39715)
Both `ReferenceSymbol` and `VariableSymbol` have two locations of
interest to an external consumer.
1. The location for the initializers of the local TCB variables allow consumers
to query the TypeScript Language Service for information about the initialized type of the variable.
2. The location of the local variable itself (i.e. `_t1`) allows
consumers to query the TypeScript LS for references to that variable
from within the template.

PR Close #39715
2020-11-19 12:15:21 -08:00
ayazhafiz 3a344d4e0e test(language-service): add renamed, deleted test file (#39742)
language_service_adapter_spec was renamed to adapters_spec as part of
d39c4bbe37, but I failed to check in
adapters_spec, thereby just deleting the spec. This reintroduces it.

PR Close #39742
2020-11-18 11:11:14 -08:00
ayazhafiz d39c4bbe37 refactor(language-service): language_service_adapter -> adapters (#39619)
This rename is done because we know have a file system adapter over a
project as well as the compiler adapter.

PR Close #39619
2020-11-17 14:45:09 -08:00
ayazhafiz 64c3135be7 refactor(compiler-cli): provide a host to readConfiguration (#39619)
Currently `readConfiguration` relies on the file system to perform disk
utilities needed to read determine a project configuration file and read
it. This poses a challenge for the language service, which would like to
use `readConfiguration` to watch and read configurations dependent on
extended tsconfigs (#39134). Challenges are at least twofold:

1. To test this, the langauge service would need to provide to the
   compiler a mock file system.
2. The language service uses file system utilities primarily through
   TypeScript's `Project` abstraction. In general this should correspond
   to the underlying file system, but it may differ and it is better to
   go through one channel when possible.

This patch alleviates the concern by directly providing to the compiler
a "ParseConfigurationHost" with read-only "file system"-like utilties.
For the language service, this host is derived from the project owned by
the language service.

For more discussion see
https://docs.google.com/document/d/1TrbT-m7bqyYZICmZYHjnJ7NG9Vzt5Rd967h43Qx8jw0/edit?usp=sharing

PR Close #39619
2020-11-17 14:45:09 -08:00
Alex Rickabaugh b6893d23c5 test(language-service): introduce new virtual testing environment (#39594)
This commit adds new language service testing infrastructure which allows
for in-memory testing. It solves a number of issues with the previous
testing infrastructure that relied on a single integration project across
all of the tests, and also provides for much faster builds by using
the compiler-cli's mock versions of @angular/core and @angular/common.

A new `LanguageServiceTestEnvironment` class (conceptually mirroring the
compiler-cli `NgtscTestEnvironment`) controls setup and execution of tests.
The `FileSystem` abstraction is used to drive a `ts.server.ServerHost`,
which backs the language service infrastructure.

Since many language service tests revolve around the template, the API is
currently optimized to spin up a "skeleton" project and then override its
template for each test.

The existing Quick Info tests (quick_info_spec.ts) were ported to the new
infrastructure for validation. The tests were cleaned up a bit to remove
unnecessary initializations as well as correct legitimate template errors
which did not affect the test outcome, but caused additional validation of
test correctness to fail. They still utilize a shared project with all
fields required for each individual unit test, which is an anti-pattern, but
new tests can now easily be written independently without relying on the
shared project, which was extremely difficult previously. Future cleanup
work might refactor these tests to be more independent.

PR Close #39594
2020-11-17 11:59:56 -08:00
Alex Rickabaugh a7155bc2fa test(language-service): move existing tests to legacy directory (#39594)
In preparation for in-memory testing infrastructure, the existing Ivy
language service tests are moved to a `legacy` directory. These existing
tests rely on a single integration project in `test/project/app`, which
presents a number of challenges:

 * adding extra fields/properties to the integration project for one test
   can cause others to fail/flake.
 * it's especially difficult to test any cases that require introducing
   intentional errors, as those tend to break other tests.
 * tests load files from disk, which is slower.
 * tests rely on the real built versions of @angular/core and
   @angular/common, which makes them both slow to build and require rebuilds
   on every compiler change.
 * tests share a single tsconfig.json, making it extremely difficult to test
   how the language service handles different configuration scenarios (e.g.
   different type-checking flags).

PR Close #39594
2020-11-17 11:59:56 -08:00
Andrew Scott 8a1c98c5e8 refactor(compiler-cli): add keySpan to reference nodes (#39616)
Similar to #39613, #39609, and #38898, we should store the `keySpan` for
Reference nodes so that we can accurately map from a template node to a
span in the original file. This is most notably an issue at the moment
for directive references `#ref="exportAs"`. The current behavior for the
language service when requesting information for the reference
is that it will return a text span that results in
highlighting the entire source when it should only highlight "ref" (test
added for this case as well).

PR Close #39616
2020-11-12 15:12:53 -08:00
Andrew Scott c33326c538 refactor(compiler-cli): add keySpan to parsed events (#39609)
Though we currently have the knowledge of where the `key` for an
event binding appears during parsing, we do not propagate this
information to the output AST. This means that once we produce the
template AST, we have no way of mapping a template position to the key
span alone. The best we can currently do is map back to the
`sourceSpan`. This presents problems downstream, specifically for the
language service, where we cannot provide correct information about a
position in a template because the AST is not granular enough.

This is essentially identical to the change from #38898, but for event
bindings rather than input bindings.

PR Close #39609
2020-11-12 15:09:17 -08:00
Andrew Scott 21651d362d refactor(compiler-cli): add keySpan to text attributes (#39613)
Similar to #39609 and #38898, though we currently have the knowledge of where the key for an
attribute appears during parsing, we do not propagate this
information to the output AST. This means that once we produce the
template AST, we have no way of mapping a template position to the key
span alone. The best we can currently do is map back to the
sourceSpan. This presents problems downstream, specifically for the
language service, where we cannot provide correct information about a
position in a template because the AST is not granular enough.

PR Close #39613
2020-11-12 14:19:00 -08:00
Andrew Scott 3a1d36cce3 refactor(language-service): Use compiler APIs in Ivy to get definitions for external resources (#39476)
Rather than re-reading component metadata that was already interpreted
by the Ivy compiler, the Language Service should instead use the
compiler APIs to get information it needs about the metadata.

PR Close #39476
2020-11-06 09:17:33 -08:00
Alex Rickabaugh eaace44d57 refactor(language-service): refactor `HybridVisitor` and expand its capabilities (#39505)
This commit takes the `HybridVisitor` in the language service and gives it
the ability to return not just a node but the template context in which it
appears. In the future, more context regarding where a node appears in the
template might become necessary (ex: the microsyntax container for binding
nodes), and this refactoring enables that.

In the process, `HybridVisitor` is renamed and the concept of a
`TemplateTarget` interface is introduced to contain the results of this
operation.

PR Close #39505
2020-11-02 10:29:50 -08:00
Alex Rickabaugh 643c96184c refactor(language-service): introduce DisplayParts abstraction for Ivy (#39505)
This commit refactors the QuickInfo abstraction shared between the VE and
Ivy services and used to implement hover tooltips (quick info), which was
extracted from the VE code in commit faa81dc. The new DisplayParts
abstraction is more general and can be used to extract information needed by
various LS functions (e.g. autocompletion).

This commit effectively reverts faa81dc, returning the original code to the
VE implementation as the Ivy code is now diverged.

PR Close #39505
2020-11-02 10:29:50 -08:00
Kristiyan Kostadinov cbc0907bfd fix(compiler): preserve this.$event and this.$any accesses in expressions (#39323)
Currently expressions `$event.foo()` and `this.$event.foo()`, as well as `$any(foo)` and
`this.$any(foo)`, are treated as the same expression by the compiler, because `this` is considered
the same implicit receiver as when the receiver is omitted. This introduces the following issues:

1. Any time something called `$any` is used, it'll be stripped away, leaving only the first parameter.
2. If something called `$event` is used anywhere in a template, it'll be preserved as `$event`,
rather than being rewritten to `ctx.$event`, causing the value to undefined at runtime. This
applies to listener, property and text bindings.

These changes resolve the first issue and part of the second one by preserving anything that
is accessed through `this`, even if it's one of the "special" ones like `$any` or `$event`.
Furthermore, these changes only expose the `$event` global variable inside event listeners,
whereas previously it was available everywhere.

Fixes #30278.

PR Close #39323
2020-10-30 10:49:15 -07:00
ayazhafiz 19b88cef71 fix(compiler): do not throw away render3 AST on errors (#39413)
Currently render3's `parseTemplate` throws away the parsed AST and
returns an empty list of HTML nodes if HTML->R3 translation failed. This
is not preferrable in some contexts like that of a language service,
where we would like a well-formed AST even if it is has errors.

PR Close #39413
2020-10-27 13:37:19 -07:00
Keen Yee Liau 0268b72d2c Revert "test(language-service): Make project service a singleton (#39308)" (#39322)
This reverts commit 1b21350e17.

PR Close #39322
2020-10-19 09:25:19 -07:00
Keen Yee Liau 1b21350e17 test(language-service): Make project service a singleton (#39308)
Constructing a project service is expensive. Making it a singleton could
speed up tests considerably.

On my MacBook Pro, test execution went from 24.4s to 14.5s (~40% improvement).

PR Close #39308
2020-10-16 12:34:16 -07:00
Keen Yee Liau 0c01c4a898 test(language-service): wrap setup() in beforeAll to speed up fit() test (#39305)
Test harness `setup()` is expensive, in the order of ~2.5 seconds.

We could speed up `fit()` tests considerably if `setup()` is wrapped
in `beforeAll()` to avoid running it unnecessarily.

PR Close #39305
2020-10-16 12:33:36 -07:00
Andrew Scott 563fb6cdbe feat(language-service): Implement go to definition for style and template urls (#39202)
This commit enables the Ivy Language Service to 'go to definition' of a
templateUrl or styleUrl, which would jump to the template/style file
itself.

PR Close #39202
2020-10-16 12:31:54 -07:00
Andrew Scott 087596bbde refactor(language-service): Move some util functions to common (#39202)
These functions will be useful to the Ivy language service as well to
provide 'go to definition' functionality for template and style urls.

PR Close #39202
2020-10-16 12:31:54 -07:00
Andrew Scott 5bda62c51d refactor(language-service): Return directive defs when input name is part of selector (#39243)
When an input name is part of the directive selector, it would be good to return the directive as well
when performing 'go to definition' or 'go to type definition'. As an example, this would allow
'go to type definition' for ngIf to take the user to the NgIf directive.
'Go to type definition' would otherwise return no results because the
input is a generic type. This would also be the case for all primitive
input types.

PR Close #39243
2020-10-15 14:17:24 -07:00
Keen Yee Liau 8f1317f06f fix(language-service): [Ivy] create compiler only when program changes (#39231)
This commit fixes a bug in which a new Ivy Compiler is created every time
language service receives a new request. This is not needed if the
`ts.Program` has not changed.

A new class `CompilerFactory` is created to manage Compiler lifecycle and
keep track of template changes so that it knows when to override them.
With this change, we no longer need the method `getModifiedResourceFile()`
on the adapter. Instead, we call `overrideComponentTemplate` on the
template type checker.

This commit also changes the incremental build strategy from
`PatchedIncrementalBuildStrategy` to `TrackedIncrementalBuildStrategy`.

PR Close #39231
2020-10-14 14:10:37 -07:00
Andrew Scott 437e563507 refactor(language-service): Allow "go to definition" for directives in Ivy (#39228)
For directives/components, it would be generally more appropriate for
"go to type definition" to be the function which navigates to the class
definition. However, for a better user experience, we should do this
for "go to definition" as well.

PR Close #39228
2020-10-13 08:52:29 -07:00
Pete Bacon Darwin 0accd1e68d refactor(compiler-cli): implement `DeclarationNode` node type (#38959)
Previously the `ConcreteDeclaration` and `InlineDeclaration` had
different properties for the underlying node type. And the `InlineDeclaration`
did not store a value that represented its declaration.

It turns out that a natural declaration node for an inline type is the
expression. For example in UMD/CommonJS this would be the `exports.<name>`
property access node.

So this expression is now used for the `node` of `InlineDeclaration` types
and the `expression` property is dropped.

To support this the codebase has been refactored to use a new `DeclarationNode`
type which is a union of `ts.Declaration|ts.Expression` instead of `ts.Declaration`
throughout.

PR Close #38959
2020-10-12 08:32:46 -07:00
Andrew Scott a84976fdfc feat(language-service): Add getTypeDefinitionAtPosition (go to type definition) (#39145)
This commit adds the implementation for providing "go to type definition"
functionality in the Ivy Language Service.

PR Close #39145
2020-10-09 10:57:37 -07:00
JoostK f84b3786dc test(language-service): test ICU expressions in hybrid visitor (#39072)
This commit adds tests for locating expressions within ICU expressions.

PR Close #39072
2020-10-08 11:55:27 -07:00
Keen Yee Liau 63624a2d46 feat(language-service): [Ivy] getSemanticDiagnostics for external templates (#39065)
This PR enables `getSemanticDiagnostics()` to be called on external templates.

Several changes are needed to land this feature:

1. The adapter needs to implement two additional methods:
   a. `readResource()`
       Load the template from snapshot instead of reading from disk
   b. `getModifiedResourceFiles()`
       Inform the compiler that external templates have changed so that the
       loader could invalidate its internal cache.
2. Create `ScriptInfo` for external templates in MockHost.
   Prior to this, MockHost only track changes in TypeScript files. Now it
   needs to create `ScriptInfo` for external templates as well.

For (1), in order to make sure we don't reload the template if it hasn't
changed, we need to keep track of its version. Since the complexity has
increased, the adapter is refactored into its own class.

PR Close #39065
2020-10-08 08:45:54 -07:00
Andrew Scott 4604fe9ed2 feat(language-service): Add module name to directive quick info (#39121)
This commit adds the module name as the `containerName` to the quick info
for directives.

PR Close #39121
2020-10-08 08:45:29 -07:00
Andrew Scott 3975dd90a6 feat(language-service): Add getDefinitionAndBoundSpan (go to definition) (#39101)
This commit adds the implementation for providing "go to definition"
functionality in the Ivy Language Service.

PR Close #39101
2020-10-06 13:24:52 -07:00
Keen Yee Liau 70e13dc31e fix(language-service): [Ivy] hybrid visitor should not locate let keyword (#39061)
Fixed a boolean logic error that prevented hybrid visitor from returning
undefined when a variable does not have value and cursor is not in the
key span.

PR Close #39061
2020-10-06 11:33:32 -07:00
Andrew Scott faa81dcdd1 refactor(language-service): Extract common methods from VE and Ivy to new package (#39098)
Rather than having the Ivy implementation add the VE code to the deps
list, create a new common package that both Ivy and VE depend on. This
will make it more straightforward in the future to remove the VE code
completely.

PR Close #39098
2020-10-05 16:14:54 -07:00
Andrew Scott 904adb72d2 feat(language-service): add quick info for inline templates in ivy (#39060)
Adds implementation for `getQuickInfoAtPosition` to the Ivy Language
Service, which now returns `ts.QuickInfo` for inline templates.

PR Close #39060
2020-10-02 11:01:31 -07:00
Keen Yee Liau eec9f4a84e test(language-service): add test for multiple bound attributes in microsyntax (#39062)
It used to be the case that all microsyntax bindings share the same source
span, so the second bound attribute would overwrite the first.

This has been fixed in #39036, this case is added to prevent regression.

PR Close #39062
2020-09-30 12:48:18 -07:00
Andrew Scott 31e42f0947 refactor(language-service): create getTypeDefinitionAtPosition stubs (#39050)
Create stubs for getTypeDefinitionAtPosition for both VE and Ivy Language Service implementations.
This will prevent failed requests when it is implemented on the vscode plugin side

PR Close #39050
2020-09-30 09:34:47 -04:00
Andrew Scott 8f66540152 test(language-service): Update AppComponent test project to include more fields (#39033)
In preparation for the Ivy Language service, add the same properties to AppComponent that appear in
TemplateReference so the inline template can be tested thoroughly.

PR Close #39033
2020-09-30 09:26:43 -04:00
Keen Yee Liau ded9aeb447 refactor(language-service): Move two-way binding logic to visitBoundEvent (#38985)
Instead of doing all sorts of checks in the `visit()` method, move checks
that are specific to `BoundEvent` to the `visitBoundEvent()` method.

PR Close #38985
2020-09-30 09:17:46 -04:00
Andrea Canciani daf8b7f100 feat(common): stricter types for DatePipe (#37447)
Make typing of DatePipe stricter to catch some misuses (such as passing
an Observable or an array) at compile time.

BREAKING CHANGE:
The signature of the `date` pipe now explicitly states which types are
accepted. This should only cause issues in corner cases, as any other
values would result in runtime exceptions.

PR Close #37447
2020-09-28 12:23:32 -04:00
Andrea Canciani 5f815c0565 fix(common): correct and simplify typing of AsyncPipe (#37447)
`AsyncPipe.transform` will never return `undefined`, even when passed
`undefined` in input, in contrast with what was declared in the
overloads.

Additionally the "actual" method signature can be updated to match the
most generic case, since the implementation does not rely on wrappers
anymore.

BREAKING CHANGE:
The async pipe no longer claims to return `undefined` for an input that
was typed as `undefined`. Note that the code actually returned `null` on
`undefined` inputs. In the unlikely case you were relying on this,
please fix the typing of the consumers of the pipe output.

PR Close #37447
2020-09-28 12:23:32 -04:00
Keen Yee Liau 323be39297 fix(language-service): hybrid visitor returns parent node of BoundAttribute (#38995)
For the following example, the cursor is between `keySpan` and `valueSpan`
of the `BoundAttribute`.
```html
<test-cmp [foo]¦="bar"></test-cmp>
```
Our hybrid visitor will return `Element`in this case, which is the parent
node of the `BoundAttribute`.
This is because we only look at the `keySpan` and `valueSpan`, and not
the source span. The last element in the AST path is `Element`, so it gets
returned.

In this PR, I propose fixing this by adding a sentinel value `undefined`
to the AST path to signal that we've found a source span but the cursor is
neither in the key span nor the value span.

PR Close #38995
2020-09-25 14:35:08 -04:00
Andrew Scott 4c8766573d refactor(language-service): Update hybrid visitor to use keySpan for bound attributes (#38955)
The keySpan in bound attributes provides more fine-grained location information and can be used
to disambiguate multiple bound attributes in a single microsyntax binding. Previously,
this case could not distinguish between the two different attributes because
the sourceSpans were identical and valueSpans would not match if the cursor
was located in a key.

PR Close #38955
2020-09-24 11:35:12 -04:00
Keen Yee Liau 8f349b2375 fix(compiler): source span for microsyntax text att should be key span (#38766)
In a microsyntax expressions, some attributes are not bound after
desugaring. For example,
```html
<div *ngFor="let item of items">
</div>
```
gets desugared to
```html
<ng-template ngFor let-items [ngForOf]="items">
</ngtemplate>
```
In this case, `ngFor` should be a literal attribute with no RHS value.
Therefore, its source span should be just the `keySpan` and not the
source span of the original template node.
This allows language service to precisely pinpoint different spans in a
microsyntax to provide accurate information.

PR Close #38766
2020-09-10 14:31:23 -07:00
Andrew Scott a46e0e48a3 refactor(compiler-cli): Adjust output of TCB to support `TemplateTypeChecker` Symbol retrieval (#38618)
The statements generated in the TCB are optimized for performance and producing diagnostics.
These optimizations can result in generating a TCB that does not have all the information
needed by the `TemplateTypeChecker` for retrieving `Symbol`s. For example, as an optimization,
the TCB will not generate variable declaration statements for directives that have no
references, inputs, or outputs. However, the `TemplateTypeChecker` always needs these
statements to be present in order to provide `ts.Symbol`s and `ts.Type`s for the directives.

This commit adds logic to the TCB generation to ensure the required
information is available in a form that the `TemplateTypeChecker` can
consume. It also adds an option to the `NgCompiler` that makes this
generation configurable.

PR Close #38618
2020-09-10 12:40:38 -07:00
Keen Yee Liau c6ebb77cec test(language-service): [ivy] remove all markers from test (#38777)
In the test project there are no longer reference markers and location
markers, so there's no need to "pre-process" the source files to remove
them. This will make the Ivy tests cleaner and faster.

PR Close #38777
2020-09-09 16:21:56 -07:00
Pete Bacon Darwin 687477279b refactor(compiler): move `ParsedTemplate` interface to compiler (#38594)
Previously this interface was mostly stored in compiler-cli, but it
contains some properties that would be useful for compiling the
"declare component" prelink code.

This commit moves some of the interface over to the compiler
package so that it can be referenced there without creating a
circular dependency between the compiler and compiler-cli.

PR Close #38594
2020-09-08 11:43:25 -07:00
Pete Bacon Darwin a68f1a78a7 refactor(compiler): element.startSourceSpan is required (#38581)
Previously, the `startSourceSpan` property could be null
but in reality it is always well defined - except for a legacy
case in the old i18n extraction/merging code, where the
typings for source-spans are already being undermined.

Making this property non-null, simplifies code elsewhere
in the project.

PR Close #38581
2020-09-02 14:47:28 -07:00
Alan Agius 0fc44e0436 feat(compiler-cli): add support for TypeScript 4.0 (#38076)
With this change we add support for TypeScript 4.0

PR Close #38076
2020-08-24 13:06:59 -07:00
Keen Yee Liau 4985267211 test(language-service): [Ivy] return cursor position in overwritten template (#38552)
In many testing scenarios, there is a common pattern:

1. Overwrite template (inline or external)
2. Find cursor position
3. Call one of language service APIs
4. Inspect spans in result

In order to faciliate this pattern, this commit refactors
`MockHost.overwrite()` and `MockHost.overwriteInlineTemplate()` to
allow a faux cursor symbol `¦` to be injected into the template, and
the methods will automatically remove it before updating the script snapshot.
Both methods will return the cursor position and the new text without
the cursor symbol.

This makes testing very convenient. Here's a typical example:

```ts
const {position, text} = mockHost.overwrite('template.html', `{{ ti¦tle }}`);
const quickInfo = ngLS.getQuickInfoAtPosition('template.html', position);
const {start, length} = quickInfo!.textSpan;
expect(text.substring(start, start + length)).toBe('title');
```

PR Close #38552
2020-08-24 09:25:04 -07:00
Keen Yee Liau b48cc6ead5 feat(language-service): introduce hybrid visitor to locate AST node (#38540)
This commit introduces two visitors, one for Template AST and the other
for Expression AST to allow us to easily find the node that most closely
corresponds to a given cursor position.

This is crucial because many language service APIs take in a `position`
parameter, and the information returned depends on how well we can find
a good candidate node.

In View Engine implementation of language service, the search for the node
and the processing of information to return the result are strongly coupled.
This makes the code hard to understand and hard to debug because the stack
trace is often littered with layers of visitor calls.

With this new feature, we could test the "searching" part separately and
colocate all the logic (aka hacks) that's required to retrieve an accurate
span for a given node.

Right now, only the most "narrow" node is returned by the main exported
function `findNodeAtPosition`. If needed, we could expose the entire AST
path, or expose other methods to provide more context for a node.

Note that due to limitations in the template AST interface, there are
a few known cases where microsyntax spans are not recorded properly.
This will be dealt with in a follow-up PR.

PR Close #38540
2020-08-24 09:24:18 -07:00
JoostK 874792dc43 feat(compiler): support unary operators for more accurate type checking (#37918)
Prior to this change, the unary + and - operators would be parsed as `x - 0`
and `0 - x` respectively. The runtime semantics of these expressions are
equivalent, however they may introduce inaccurate template type checking
errors as the literal type is lost, for example:

```ts
@Component({
  template: `<button [disabled]="isAdjacent(-1)"></button>`
})
export class Example {
  isAdjacent(direction: -1 | 1): boolean { return false; }
}
```

would incorrectly report a type-check error:

> error TS2345: Argument of type 'number' is not assignable to parameter
  of type '-1 | 1'.

Additionally, the translated expression for the unary + operator would be
considered as arithmetic expression with an incompatible left-hand side:

> error TS2362: The left-hand side of an arithmetic operation must be of
  type 'any', 'number', 'bigint' or an enum type.

To resolve this issues, the implicit transformation should be avoided.
This commit adds a new unary AST node to represent these expressions,
allowing for more accurate type-checking.

Fixes #20845
Fixes #36178

PR Close #37918
2020-08-21 12:25:53 -07:00