point folks to the angular repo (#710)
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 5617d32..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,18 +0,0 @@
-.DS_Store
-
-.project
-
-.idea
-angular2-dart-analyzer.iml
-
-.packages
-.pub
-.dart_tool/
-packages
-pubspec.lock
-deps/sdk
-deps/.gclient
-
-server_plugin/bin/server.snapshot
-
-angular_analyzer_plugin/tools/analyzer_plugin/pubspec.yaml
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 02a9ebc..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-language: dart
-sudo: false
-dart:
- - dev
-cache:
- directories:
-before_script:
- - git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
- - export PATH=`pwd`/depot_tools:"$PATH"
- - ./tools/get_deps.sh
-script:
- - ./tools/check_format.sh
- - ./tools/check_no_solo_tests.sh
- - ./tools/travis.sh
-env:
- - PACKAGE=angular_analyzer_plugin
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index d39f519..0000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,217 +0,0 @@
-## 0.0.17+6
-
-- Fixed an issue where an unnecessary navigation range was added to HTML files.
-- Fixed an issue where navigation would be delayed in IntelliJ and other IDEs
- that use the notification pattern for navigation.
-- Change analyzer API for forwards compatibility with part files. The old API
- could have caused out-of-date errors to be cached for a file. The new API,
- however, introduces extra asynchrony. Manual testing seemed to show everything
- working properly however this _may_ cause race conditions or hurt performance.
-
-## 0.0.17+5
-
-- Fixed an issue where a corrupt URI would crash the plugin on windows.
-
-## 0.0.17+4
-
-- Refactored how non-angular expressions (`new`, `+=`, `..`, etc.) are detected.
-- Refactored how `exports` are handled in a fairly major way.
-- Typecheck the results and input of pipe expressions and the existence of a
- matching pipe. Optional arguments are not yet typechecked.
-- Add typechecking support for `[attr.foo.if]`, and ensure that a corresponding
- `[attr.foo]` binding exists.
-- Fixed issues with `<ng-container>`, which resulted in the inner content simply
- being ignored instead of being validated (and also caused some problems
- with finding inner `<ng-content>` tags).
-- More checks for rejected operators like `+=`, `++` other unary operators and
- compound assignments.
-- Named arguments are no longer reported as disallowed as angular now supports
- them.
-
-## 0.0.17+3
-
-- Fixed an issue where a cast error from certain top-level getters would crash
- the plugin.
-
-## 0.0.17+2
-
-- Fixed an issue where pipes with a dynamic type optional parameter would crash
- the plugin.
-
-## 0.0.17+1
-
-- Fixed an issue where standard HTML events weren't recognized due to changes
- made to dart:html sources on newer SDKs.
-
-## 0.0.17
-
-- More dart 2 runtime support.
-- Upgrade package:analyzer to support newest dart semantics.
-
-## 0.0.16
-
-- Fixed an issue where you couldn't reference a static member of the component
- class without a warning.
-- Support dart 2 runtimes
-- Better error message for when attribute selectors have an operator but no
- value.
-- In previous versions, the `x*=y` selector was working incorrectly. It matched
- attributes whose *names began with* `x` and optionally contained a value `y`.
- This has been fixed to do the correct thing: match an attribute of name `x`
- when the value contains `y`.
-- Support '^=' css selector syntax.
-- Upgrade package:analyzer to support newest dart semantics.
-
-## 0.0.15
-
-- Refactored attribute autocompletion
-- Fixed a bug where pipes that inherited transform() got flagged.
-- Fixed a bug where parts' templateUrls should be relative to the parts' library
- and not the part itself.
-- Added support for === operator.
-
-Some larger items:
-
-### Newer options config
-
-The required config has been changed in a backwards-compatible way. However,
-note that while 0.0.14's config works for 0.0.15 users, the reverse is not true.
-
-Specifically, we no longer require `enabled: true`, and we are moving from
-configuring the plugin inside `analyzer`, to having its own top level. This
-solves a number of problems related to finding, merging, or modifying config,
-with a potentially large number of methods of loading the plugin.
-
-Old:
-
-```yaml
-analyzer:
- plugins:
- angular:
- enabled: true
- custom_tag_names:
- - foo
- - bar
-```
-
-New:
-
-```yaml
-analyzer:
- plugins:
- - angular
-
-angular:
- custom_tag_names:
- - foo
- - bar
-```
-
-This is encouraged for users on more recent versions than 0.0.14. Support for
-the old system will likely first be flagged within the dart analyzer itself, and
-then dropped from our plugin a while after that.
-
-## 0.0.14
-
-- Fixed issues with locating sources in Windows
-- Fixed an order-of-operations bug where getting completions before errors
- suppressed the subsequent error notification.
-- Fixed a performance problem due to new navigation features, and correctness
- issue where local unsaved changes were used in html navigation line/offset
- info.
-- Fixed crashes in latest IntelliJ due to new navigation features
-- Upgrade package:analyzer to support newest dart semantics.
-- Fixed crash autocompleting before a comment
-- Upgraded package:analyzer for latest dart semantics + bug fixes
-- Upgraded package:analyzer_plugin for fix with autocompleting members on
- dynamic values
-
-## 0.0.13
-
-- Fixed a memory leak cause by a stream with no listener
-- Support FutureOr-typed inputs
-- Upgrade package:analyzer to support newest dart semantics.
-
-## 0.0.12
-
-- Support `(focusin)` and `(focusout)` events.
-- Fix crash autocompleting an input in a star-attr when the input name matches
- the star attr text exactly.
-- Bugfix regarding quotes in attribute selector values. For example, `[x="y"]`
- now correctly expects the value `y` for some attr `x`.
-- Allow (and suggest) `List` instead of `QueryList`. Note, QueryList is still
- supported, for now.
-
-Some larger items:
-
-### Allow custom events with custom types to be specified. (#485)
-
-Example syntax:
-
-```yaml
- analyzer:
- plugins:
- angular:
- enabled: true
- custom_events:
- doodle:
- type: DoodleEvent
- path: 'package:doodle/events.dart'
- poodle:
- type: PoodleEvent
- path: 'package:doodle/events.dart'
-```
-
-### Add new options for ContentChild(ren) in prep for deprecating ElementRef;
-
-Accept (for the moment) ElementRef, Element, and HtmlElement (the
-latter two being from dart:html).
-
-Ensure HtmlElement and Element use read: x when @ContentChild('foo'), and check
-assignability for the read: type.
-
-Note, we currently don't differentiate SVG and HTML, so we accept either type
-for either case at the moment.
-
-## 0.0.11
-
-- *@View no longer supported.*
-- Clearer error for templates that are included from unconventional components.
- Usually, this is from test components where this occurs.
-- Allow `directives: VARIABLE` in addition to `directives: const [VARIABLE]`.
-- Functional Directive support
-- Handle optional parameters in pipes
-- Change "overcomplicated templates" error (templates set to const strings that
- are calculated rather than defined full-form, making error ranges difficult or
- impossible to provide) to a hint from an error.
-- Expect angular classes to be in `package:angular` (though still look at
- `package:angular2` if that is missing).
-- Check that reductions (ie, `(keyup.space)`) are only on key events.
-- Support angular security, which otherwise produces assignment errors.
-- *Plugin loading mechanism changed.*
-- Support `<audio>` tag.
-- Handle directive inheritance.
-
-Some larger items:
-
-### Allow custom tag names
-
-Example syntax:
-
-```yaml
- analyzer:
- plugins:
- angular:
- enabled: true
- custom_tag_names:
- - foo
- - bar
- - baz
-```
-
-Most errors related to custom tags are suppressed, because custom tags are often
-handled by other frameworks (ie, polymer).
-
-# 0.0.10
-
-Started changelog.
diff --git a/README.md b/README.md
index 0f5e5e4..d88381e 100644
--- a/README.md
+++ b/README.md
@@ -1,218 +1,2 @@
-[](https://travis-ci.org/dart-lang/angular_analyzer_plugin) [](https://pub.dartlang.org/packages/angular_analyzer_plugin)
-
-**Requires angular-5.0.0\* and dart SDK 2.0.0-dev.31\*\* or higher to work.**
-
-\* Works with angular-4.0.0 by following the steps in the section "loading an exact version."
-
-\*\* Linux and Mac users should be able to an SDK version as old as 1.25.0-dev.12.0
-
-## Integration with Dart Analysis Server
-
- To provide information for DAS clients the `server_plugin` plugin contributes several extensions.
-
-* Angular analysis errors are automatically merged into normal `errors` notifications for Dart and HTML files.
-
-
-
-## Installing By Angular Version -- For Angular Developers (recommended)
-
-Using this strategy allows the dart ecosystem to discover which version of our plugin will work best with your version of angular, and therefore is recommended.
-
-Simply add to your [analysis_options.yaml file](https://www.dartlang.org/guides/language/analysis-options#the-analysis-options-file):
-
-```yaml
-analyzer:
- plugins:
- - angular
-```
-
-Then simply reboot your analysis server (inside IntelliJ this is done by clicking on the skull icon if it exists, or the refresh icon otherwise) and wait for the plugin to fully load, which can take a minute on the first run.
-
-The plugin will self-upgrade if you update angular. Otherwise, you can get any version of the plugin you wish by following the steps in the next section.
-
-## Loading an Exact Version
-
-This is much like the previous step. However, you should include this project in your pubspec:
-
-```yaml
-dependencies:
- angular_analyzer_plugin: 0.0.13
-```
-
-and then load the plugin as itself, rather than as a dependency of angular:
-
-```yaml
-analyzer:
- plugins:
- - angular_analyzer_plugin
-```
-
-Like the previous installation option, you then just need to reboot your analysis server after running pub get.
-
-## Troubleshooting
-
-If you have any issues, filing an issue with us is always a welcome option. There are a few things you can try on your own, as well, to get an idea of what's going wrong:
-
-* Are you using angular 5 or newer? If not, are you loading a recent exact version of the plugin?
-* Are you using a bleeding edge SDK? The latest stable will not work correctly, and windows users require at least 2.0.0-dev-31.
-* Did you turn the plugin on correctly in your analysis options file?
-* From IntelliJ in the Dart Analysis panel, there's a gear icon that has "analyzer diagnostics," which opens a web page that has a section for loaded plugins. Are there any errors?
-* Does your editor support html+dart analysis, or is it an old version? Some (such as VSCode, vim) may have special steps to show errors surfaced by dart analysis inside your html files.
-* Check the directory `~/.dartServer/.plugin_manager` (on Windows: `\Users\you\AppData\Local\.dartServer\.plugin_manager`). Does it have any subdirectories?
-* There should be a hash representing each plugin you've loaded. Can you run `pub get` from `HASH/analyzer_plugin`? (If you have multiple hashes, it should be safe to clear this directory & reload.)
-* If you run `bin/plugin.dart` from `.plugin_manager/HASH/analyzer_plugin`, do you get any import errors? (Note: this is expected to crash when launched in this way, but without import-related errors)
-
-We may ask you any or all of these questions if you open an issue, so feel free to go run through these checks on your own to get a hint what might be wrong.
-
-## Upgrading
-
-Any Dart users on 2.0.0-dev.48 or newer will get updates on every restart of the analysis server. If you are on an older Dart version than that, check the Troubleshooting section.
-
-## Building -- For hacking on this plugin, or using the latest unpublished.
-
-There's an `pubspec.yaml` file that needs to be updated to point to your local system:
-
-```console
-$ cd angular_analyzer_plugin/tools/analyzer_plugin
-$ cp pubspec.yaml.defaults pubspec.yaml
-```
-
-Modify `pubspec.yaml` in this folder to fix the absolute paths. They **must** be absolute!
-
-Then run `pub get`.
-
-You can now use this in projects on your local system which a correctly configured pubspec and analysis options. For instance, `playground/`. Note that it imports the plugin by path, and imports it as a plugin inside `analysis_options.yaml`.
-
-## Chart of Current Features
-
-We plug into many editors with varying degrees of support. In theory anything that supports Dart analysis also supports our plugin, but in practice that's not always the case.
-
-Bootstrapping | Validation | Auto-Complete | Navigation | Refactoring
---------------|------------|---------------|------------|-------------
-IntelliJ | :white_check_mark: | :white_check_mark: | :warning: some support in EAP | :no_pedestrians:
-Vim (special setup required) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :no_pedestrians:
-VS Code (Dart Code [w/ flag](https://github.com/Dart-Code/Dart-Code/issues/396)) | :white_check_mark: | :question: | :question: | :no_pedestrians:
-others | :question: let us know! | :question: let us know! | :question: let us know! | :question: let us know!
-
-If you are using an editor with Dart support that's not in this list, then please let us know what does or doesn't work. We can sometimes contribute fixes, too!
-
-Bootstrapping | Validation | Auto-Complete | Navigation | Refactoring
---------------|------------|---------------|------------|-------------
-`bootstrap(AppComponent, [MyService, provide(...)]);` | :no_pedestrians: | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-
-Template syntax | Validation | Auto-Complete | Navigation | Refactoring
-----------------|------------|---------------|------------|-------------
-`<div stringInput="string">` | :white_check_mark: typecheck is string input on component | :white_check_mark: | :white_check_mark: | :x:
-`<input [value]="firstName">` | :white_check_mark: soundness of expression, type of expression, existence of `value` on element or directive | :white_check_mark: | :white_check_mark: | :x:
-`<input bind-value="firstName">` | :white_check_mark: | :skull: | :white_check_mark: | :x:
-`<div [attr.role]="myAriaRole">` | :last_quarter_moon: soundness of expression, but no other validation | :last_quarter_moon: complete inside binding but binding not suggested | :last_quarter_moon: no html specific navigation | :x:
-`<div [attr.role.if]="myAriaRole">` | :white_check_mark: | :last_quarter_moon: complete inside binding but binding not suggested | :white_check_mark: | :x:
-`<div [class.extra-sparkle]="isDelightful">` | :white_check_mark: validity of clasname, soundness of expression, type of expression must be bool | :last_quarter_moon: complete inside binding but binding not suggested | :last_quarter_moon: no css specific navigation | :x:
-`<div [style.width.px]="mySize">` | :waning_gibbous_moon: soundness of expression, css properties are generally checked but not against a dictionary, same for units, expression must type to `int` if units are present | :last_quarter_moon: complete inside binding but binding not suggested | :last_quarter_moon: no css specific navigation | :x:
-`<button (click)="readRainbow($event)">` | :white_check_mark: soundness of expression, type of `$event`, existence of output on component/element and DOM events which propagate can be tracked anywhere | :white_check_mark: | :last_quarter_moon: no navigation for `$event` | :x:
-`<button (keyup.enter)="...">` | :waning_gibbous_moon: soundness of expression, type of `$event`, keycode and modifier names not checked | :white_check_mark: | :last_quarter_moon: no navigation for `$event` | :x:
-`<button on-click="readRainbow($event)">` | :white_check_mark: | :skull: | :last_quarter_moon: no navigation for `$event` | :x:
-`<div title="Hello {{ponyName}}">` | :white_check_mark: soundness of expression, matching mustache delimiters | :white_check_mark: | :white_check_mark: | :x:
-`<p>Hello {{ponyName}}</p>` | :white_check_mark: soundness of expression, matching mustache delimiters | :white_check_mark: | :white_check_mark: | :x:
-`<my-cmp></my-cmp>` | :white_check_mark: existence of directive |:white_check_mark: | :white_check_mark: | :x:
-`<my-cmp [(title)]="name">` | :white_check_mark: soundness of expression, existence of `title` input and `titleChange` output on directive or component with proper type | :white_check_mark: | :white_check_mark: navigates to the input | :x:
-`<video #movieplayer ...></video><button (click)="movieplayer.play()">` | :white_check_mark: type of new variable tracked and checked in other expressions | :white_check_mark: | :white_check_mark: | :x:
-`<video directiveWithExportAs #moviePlayer="exportAsValue">` | :white_check_mark: existence of exportAs value checked within bound directives | :white_check_mark: | :white_check_mark: | :x:
-`<video ref-movieplayer ...></video><button (click)="movieplayer.play()">` | :white_check_mark: |:white_check_mark: | :white_check_mark: | :x:
-`<p *myUnless="myExpression">...</p>` | :white_check_mark: desugared to `<template [myUnless]="myExpression"><p>...` and checked from there | :white_check_mark: | :white_check_mark: some bugs ,mostly works | :x:
-`<p>Card No.: {{cardNumber \| myCardNumberFormatter}}</p>` | :first_quarter_moon: Pipe name, input, and return type checked, optional argument types not yet checked| :x: | :x: | :x:
-`<my-component @deferred>` | :x: | :x: | :x: | :x:
-
-Built-in directives | Validation | Auto-Complete | Navigation | Refactoring
---------------------|------------|---------------|------------|-------------
-`<section *ngIf="showSection">` | :white_check_mark: type checking, check for the star | :white_check_mark: | :white_check_mark: | :x:
-`<li *ngFor="let item of list">` | :white_check_mark: type checking and new var, check for the star, catch accidental usage of `#item` | :white_check_mark: | :last_quarter_moon: some bugs, mostly works | :x:
-`<div [ngClass]="{active: isActive, disabled: isDisabled}">` | :warning: Requires quotes around key value strings to work | :white_check_mark: | :white_check_mark: | :x:
-
-Forms | Validation | Auto-Complete | Navigation | Refactoring
-------|------------|---------------|------------|-------------
-`<input [(ngModel)]="userName">` | :white_check_mark: | :white_check_mark: | :white_check_mark: goes to `ngModel` input | :x:
-`<form #myform="ngForm">` | :white_check_mark: if `ngForm` is not an exported directive | :white_check_mark: | :white_check_mark: | :x:
-
-Class decorators | Validation | Auto-Complete | Navigation | Refactoring
------------------|------------|---------------|------------|-------------
-`@Component(...) class MyComponent {}` | :white_check_mark: Validates directives list is all directives, that the template file exists, that a template is specified via string or URL but not both, requires a valid selector | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`@View(...) class MyComponent {}` | :warning: Supported, requires `@Directive` or `@Component`, but doesn't catch ambigous cases such as templates defined in the `@View` as well as `@Component` | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`@Directive(...) class MyDirective {}` | :white_check_mark: Validates directives list is all directives, requires a valid selector | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`@Directive(...) void directive(...) {}` | :white_check_mark: Validates directives list is all directives requires a valid selector, not exported | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`@Pipe(...) class MyPipe {}` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-`@Injectable() class MyService {}` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-
-Directive configuration | Validation | Auto-Complete | Navigation | Refactoring
-------------------------|------------|---------------|------------|-------------
-`@Directive(property1: value1, ...)` | :warning: deprecated, but supported | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`selector: '.cool-button:not(a)'` | :white_check_mark: | :no_pedestrians: | :white_check_mark: selectors can be reached from matching html | :x:
-`providers: [MyService, provide(...)]` | :x: | :x: | :x: | :x:
-`inputs: ['myprop', 'myprop2: byname']` | :white_check_mark: | :x: | :white_check_mark: | :x:
-`outputs: ['myprop', 'myprop2: byname']` | :white_check_mark: | :x: | :white_check_mark: | :x:
-
-@Component extends @Directive, so the @Directive configuration applies to components as well
-
-Component Configuration | Validation | Auto-Complete | Navigation | Refactoring
-------------------------|------------|---------------|------------|-------------
-`viewProviders: [MyService, provide(...)]` | :x: | :x: | :x: | :x:
-`template: 'Hello {{name}}'` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x:
-`templateUrl: 'my-component.html'` | :white_check_mark: | :x: | :white_check_mark: | :x:
-`styles: ['.primary {color: red}']` | :x: | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`styleUrls: ['my-component.css']` | :x: | :x: | :x: | :x:
-`directives: [MyDirective, MyComponent]` | :white_check_mark: must be directives or lists of directives, configuration affects view errors | :x: | :white_check_mark: regular navigation | :x:
-`pipes: [MyPipe, OtherPipe]` | :x: | :x: | :white_check_mark: regular navigation | :x:
-`exports: [Class, Enum, staticFn]` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x:
-
-Class field decorators for directives and components | Validation | Auto-Complete | Navigation | Refactoring
------------------------------------------------------|------------|---------------|------------|-------------
-`@Input() myProperty;` | :white_check_mark: | :no_pedestrians: | :x: | :x:
-`@Input("name") myProperty;` | :white_check_mark: | :no_pedestrians: | :x: | :x:
-`@Output() myEvent = new Stream<X>();` | :white_check_mark: Subtype of `Stream<T>` required, streamed type determines `$event` type | :no_pedestrians: | :x: | :x:
-`@Output("name") myEvent = new Stream<X>();` | :white_check_mark: | :no_pedestrians: | :x: | :x:
-`@Attribute("name") String ctorArg` | :white_check_mark: | :x: | :x: | :x:
-`@HostBinding('[class.valid]') isValid;` | :x: | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`@HostListener('click', ['$event']) onClick(e) {...}` | :x: | :x: | :x: | :x:
-`@ContentChild(myPredicate) myChildComponent;` | :x: | :no_pedestrians: | :x: | :x:
-`@ContentChildren(myPredicate) myChildComponents;` | :x: | :no_pedestrians: | :x: | :x:
-`@ViewChild(myPredicate) myChildComponent;` | :x: | :no_pedestrians: | :x: | :x:
-`@ViewChildren(myPredicate) myChildComponents;` | :x: | :no_pedestrians: | :x: | :x:
-
-Transclusions| Validation | Auto-Complete | Navigation | Refactoring
------------------------------------------------------|------------|---------------|------------|-------------
-`<ng-content></ng-content>` | :white_check_mark: | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`<my-comp>text content</my-comp>` | :white_check_mark: | :x: | :x: | :x:
-`<ng-content select="foo"></ng-content>` | :white_check_mark: | :white_check_mark: | :white_check_mark: navigation from where matched | :x:
-`<my-comp><foo></foo></my-comp>` | :white_check_mark: | :white_check_mark: | :white_check_mark: navigation to the corresponding selector | :x:
-`<ng-content select=".foo[bar]"></ng-content>` | :white_check_mark: | :white_check_mark: | :white_check_mark: navigation from where matched | :x:
-`<my-comp><div class="foo" bar></div></my-comp>` | :white_check_mark: | :white_check_mark: | :white_check_mark: navigation to the corresponding selector | :x:
-
-Directive and component change detection and lifecycle hooks (implemented as class methods) | Validation | Auto-Complete | Navigation | Refactoring
---------------------------------------------------------------------------------------------|------------|---------------|------------|-------------
-`MyAppComponent(MyService myService, ...) { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-`ngOnChanges(changeRecord) { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-`ngOnInit() { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-`ngDoCheck() { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-`ngAfterContentInit() { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-`ngAfterContentChecked() { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-`ngAfterViewInit() { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-`ngAfterViewChecked() { ... }` | :no_pedestrians: | :no_pedestrians: | :x: | :x:
-`ngOnDestroy() { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-
-Dependency injection configuration | Validation | Auto-Complete | Navigation | Refactoring
------------------------------------|------------|---------------|------------|-------------
-`provide(MyService, useClass: MyMockService)` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-`provide(MyService, useFactory: myFactory)` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-`provide(MyValue, useValue: 41)` | :x: | :no_pedestrians: | :no_pedestrians: | :x:
-
-Routing and navigation | Validation | Auto-Complete | Navigation | Refactoring
------------------------|------------|---------------|------------|-------------
-`@RouteConfig(const [ const Route(...) ])` | :x: | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`<router-outlet></router-outlet>` | :no_pedestrians: | :x: | :no_pedestrians: | :no_pedestrians:
-`<a [routerLink]="[ '/MyCmp', {myParam: 'value' } ]">` | :question: | :x: | :no_pedestrians: | :no_pedestrians:
-`@CanActivate(() => ...)class MyComponent() {}` | :x: | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`routerOnActivate(nextInstruction, prevInstruction) { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`routerCanReuse(nextInstruction, prevInstruction) { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`routerOnReuse(nextInstruction, prevInstruction) { ... }` | :x: | :x: | :no_pedestrians: | :no_pedestrians:
-`routerCanDeactivate(nextInstruction, prevInstruction) { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
-`routerOnDeactivate(nextInstruction, prevInstruction) { ... }` | :x: | :no_pedestrians: | :no_pedestrians: | :no_pedestrians:
+All development has moved to
+https://github.com/dart-lang/angular/tree/master/angular_analyzer_plugin
diff --git a/angular_analyzer_plugin/AUTHORS b/angular_analyzer_plugin/AUTHORS
deleted file mode 100644
index ff09364..0000000
--- a/angular_analyzer_plugin/AUTHORS
+++ /dev/null
@@ -1,7 +0,0 @@
-# Below is a list of people and organizations that have contributed
-# to the project. Names should be added to the list like so:
-#
-# Name/Organization <email address>
-
-Google Inc.
-
diff --git a/angular_analyzer_plugin/LICENSE b/angular_analyzer_plugin/LICENSE
deleted file mode 100644
index de31e1a..0000000
--- a/angular_analyzer_plugin/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2015, the Dart project authors. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of Google Inc. nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/angular_analyzer_plugin/README.md b/angular_analyzer_plugin/README.md
deleted file mode 100644
index ab8a7ea..0000000
--- a/angular_analyzer_plugin/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# AngularDart analyzer plugin
-
-A plugin for the Dart `analyzer` library [package](https://pub.dartlang.org/packages/analyzer) providing AngularDart support.
-
-## Features and bugs
-
-Please file feature requests and bugs at the [issue tracker][tracker].
-
-[tracker]: https://github.com/dart-lang/angular_analyzer_plugin/issues
diff --git a/angular_analyzer_plugin/analysis_options.yaml b/angular_analyzer_plugin/analysis_options.yaml
deleted file mode 100644
index 28edd97..0000000
--- a/angular_analyzer_plugin/analysis_options.yaml
+++ /dev/null
@@ -1,80 +0,0 @@
-analyzer:
- exclude:
- # TODO(devoncarew): We should remove this blanket exclusion as it could hide
- # other issues.
- - lib/src/summary/format.dart
- strong-mode:
- implicit-casts: false
-
-linter:
- rules:
- - always_declare_return_types
- - always_put_control_body_on_new_line
- - always_require_non_null_named_parameters
- - annotate_overrides
- - avoid_annotating_with_dynamic
- - avoid_catching_errors
- - avoid_classes_with_only_static_members
- - avoid_empty_else
- - avoid_init_to_null
- - avoid_null_checks_in_equality_operators
- - avoid_positional_boolean_parameters
- - avoid_return_types_on_setters
- - avoid_setters_without_getters
- - avoid_slow_async_io
- - avoid_types_on_closure_parameters
- - await_only_futures
- - camel_case_types
- - cancel_subscriptions
- - cascade_invocations
- - close_sinks
- - control_flow_in_finally
- - directives_ordering
- - empty_catches
- - empty_constructor_bodies
- - empty_statements
- - iterable_contains_unrelated_type
- - join_return_with_assignment
- - library_names
- - library_prefixes
- - list_remove_unrelated_type
- - no_adjacent_strings_in_list
- - no_duplicate_case_values
- - non_constant_identifier_names
- - omit_local_variable_types
- - only_throw_errors
- - overridden_fields
- - parameter_assignments
- - prefer_adjacent_string_concatenation
- - prefer_collection_literals
- - prefer_conditional_assignment
- - prefer_const_constructors
- - prefer_constructors_over_static_methods
- - prefer_contains
- - prefer_expression_function_bodies
- - prefer_final_fields
- - prefer_final_locals
- - prefer_function_declarations_over_variables
- - prefer_interpolation_to_compose_strings
- - prefer_is_empty
- - prefer_is_not_empty
- - recursive_getters
- - slash_for_doc_comments
- - super_goes_last
- - test_types_in_equals
- - throw_in_finally
- - type_init_formals
- - unawaited_futures
- - unnecessary_brace_in_string_interps
- - unnecessary_getters_setters
- - unnecessary_lambdas
- - unnecessary_null_aware_assignments
- - unnecessary_null_in_if_null_operators
- - unnecessary_overrides
- - unnecessary_this
- - unrelated_type_equality_checks
- - use_rethrow_when_possible
- - use_setters_to_change_properties
- - use_string_buffers
- - use_to_and_as_if_applicable
- - valid_regexps
diff --git a/angular_analyzer_plugin/lib/angular_analyzer_plugin.dart b/angular_analyzer_plugin/lib/angular_analyzer_plugin.dart
deleted file mode 100644
index 27ca4a0..0000000
--- a/angular_analyzer_plugin/lib/angular_analyzer_plugin.dart
+++ /dev/null
@@ -1,2 +0,0 @@
-// Empty. This file must exist for the self hosting plugin model, which we use
-// for development.
diff --git a/angular_analyzer_plugin/lib/ast.dart b/angular_analyzer_plugin/lib/ast.dart
deleted file mode 100644
index ec682ef..0000000
--- a/angular_analyzer_plugin/lib/ast.dart
+++ /dev/null
@@ -1,474 +0,0 @@
-import 'dart:collection';
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:meta/meta.dart';
-
-abstract class AngularAstNode {
- List<AngularAstNode> get children;
- int get length;
- int get offset;
-
- void accept(AngularAstVisitor visitor);
-}
-
-abstract class AngularAstVisitor {
- void visitDocumentInfo(DocumentInfo document) {
- for (AngularAstNode child in document.childNodes) {
- child.accept(this);
- }
- }
-
- void visitElementInfo(ElementInfo elementInfo) =>
- _visitAllChildren(elementInfo);
-
- void visitEmptyStarBinding(EmptyStarBinding emptyBinding) =>
- visitTextAttr(emptyBinding);
-
- void visitExpressionBoundAttr(ExpressionBoundAttribute attr) =>
- _visitAllChildren(attr);
-
- void visitMustache(Mustache mustache) {}
-
- void visitStatementsBoundAttr(StatementsBoundAttribute attr) =>
- _visitAllChildren(attr);
-
- void visitTemplateAttr(TemplateAttribute attr) => _visitAllChildren(attr);
-
- void visitTextAttr(TextAttribute textAttr) => _visitAllChildren(textAttr);
-
- void visitTextInfo(TextInfo textInfo) => _visitAllChildren(textInfo);
-
- void _visitAllChildren(AngularAstNode node) {
- for (final child in node.children) {
- child.accept(this);
- }
- }
-}
-
-/// Information about an attribute.
-abstract class AttributeInfo extends AngularAstNode {
- HasDirectives parent;
-
- final String name;
- final int nameOffset;
-
- final String value;
- final int valueOffset;
-
- final String originalName;
- final int originalNameOffset;
-
- AttributeInfo(this.name, this.nameOffset, this.value, this.valueOffset,
- this.originalName, this.originalNameOffset);
-
- @override
- int get length => valueOffset == null
- ? originalName.length
- : valueOffset + value.length - originalNameOffset;
-
- @override
- int get offset => originalNameOffset;
-
- int get valueLength => value != null ? value.length : 0;
-
- @override
- String toString() =>
- '([$name, $nameOffset], [$value, $valueOffset, $valueLength], '
- '[$originalName, $originalNameOffset])';
-}
-
-abstract class BoundAttributeInfo extends AttributeInfo {
- Map<String, LocalVariable> localVariables =
- new HashMap<String, LocalVariable>();
-
- BoundAttributeInfo(String name, int nameOffset, String value, int valueOffset,
- String originalName, int originalNameOffset)
- : super(name, nameOffset, value, valueOffset, originalName,
- originalNameOffset);
-
- @override
- List<AngularAstNode> get children => const <AngularAstNode>[];
-
- @override
- String toString() => '(${super.toString()}, [$children])';
-}
-
-/// Allows us to track ranges for navigating ContentChild(ren), and detect when
-/// multiple ContentChilds are matched which is an error.
-
-/// Naming here is important: "bound content child" != "content child binding."
-class ContentChildBinding {
- final AbstractDirective directive;
- final ContentChild boundContentChild;
- final Set<ElementInfo> boundElements = new HashSet<ElementInfo>();
- // TODO: track bound attributes in #foo?
-
- ContentChildBinding(this.directive, this.boundContentChild);
-}
-
-/// A binding to an [AbstractDirective], either on an [ElementInfo] or a
-/// [TemplateAttribute]. For each bound directive, there is a directive binding.
-/// Has [InputBinding]s and [OutputBinding]s which themselves indicate an
-/// [AttributeInfo] bound to an [InputElement] or [OutputElement] in the context
-/// of this [DirectiveBinding].
-///
-/// Naming here is important: "bound directive" != "directive binding."
-class DirectiveBinding {
- final AbstractDirective boundDirective;
- final inputBindings = <InputBinding>[];
- final outputBindings = <OutputBinding>[];
- final contentChildBindings = <ContentChild, ContentChildBinding>{};
- final contentChildrenBindings = <ContentChild, ContentChildBinding>{};
-
- DirectiveBinding(this.boundDirective);
-}
-
-/// A wrapper for a given HTML document or dart-angular inline HTML template.
-class DocumentInfo extends ElementInfo {
- factory DocumentInfo() = DocumentInfo._;
-
- DocumentInfo._()
- : super(
- '',
- const SourceRange(0, 0),
- const SourceRange(0, 0),
- const SourceRange(0, 0),
- const SourceRange(0, 0),
- [],
- null,
- null,
- isTemplate: false,
- );
-
- @override
- List<AngularAstNode> get children => childNodes;
-
- @override
- bool get isSynthetic => false;
-
- @override
- void accept(AngularAstVisitor visitor) => visitor.visitDocumentInfo(this);
-}
-
-/// An element in an HTML tree.
-class ElementInfo extends NodeInfo implements HasDirectives {
- final List<NodeInfo> childNodes = <NodeInfo>[];
-
- final String localName;
- final SourceRange openingSpan;
- final SourceRange closingSpan;
- final SourceRange openingNameSpan;
- final SourceRange closingNameSpan;
- final bool isTemplate;
- final List<AttributeInfo> attributes;
- final TemplateAttribute templateAttribute;
- final ElementInfo parent;
-
- @override
- final boundDirectives = <DirectiveBinding>[];
- @override
- final boundStandardOutputs = <OutputBinding>[];
- @override
- final boundStandardInputs = <InputBinding>[];
- @override
- final availableDirectives = <AbstractDirective, List<AngularElement>>{};
-
- int childNodesMaxEnd;
-
- bool tagMatchedAsTransclusion = false;
- bool tagMatchedAsDirective = false;
- bool tagMatchedAsImmediateContentChild = false;
- bool tagMatchedAsCustomTag = false;
- ElementInfo(
- this.localName,
- this.openingSpan,
- this.closingSpan,
- this.openingNameSpan,
- this.closingNameSpan,
- this.attributes,
- this.templateAttribute,
- this.parent,
- {@required this.isTemplate}) {
- if (!isSynthetic) {
- childNodesMaxEnd = offset + length;
- }
- }
-
- @override
- List<AngularAstNode> get children {
- final list = new List<AngularAstNode>.from(attributes);
- if (templateAttribute != null) {
- list.add(templateAttribute);
- }
- return list..addAll(childNodes);
- }
-
- List<AbstractDirective> get directives =>
- boundDirectives.map((bd) => bd.boundDirective).toList();
- bool get isOrHasTemplateAttribute => isTemplate || templateAttribute != null;
-
- @override
- bool get isSynthetic => openingSpan == null;
-
- @override
- int get length => (closingSpan != null)
- ? closingSpan.offset + closingSpan.length - openingSpan.offset
- : ((childNodesMaxEnd != null)
- ? childNodesMaxEnd - offset
- : openingSpan.length);
-
- @override
- int get offset => openingSpan.offset;
-
- bool get openingSpanIsClosed => isSynthetic
- ? false
- : (openingSpan.offset + openingSpan.length) ==
- (openingNameSpan.offset + openingNameSpan.length + ">".length);
-
- @override
- void accept(AngularAstVisitor visitor) => visitor.visitElementInfo(this);
-}
-
-/// `*ngFor` creates an empty text attribute, which is harmless. But so do the
-/// less harmless cases of empty `*ngIf`, and or `*ngFor="let item of"`, etc.
-class EmptyStarBinding extends TextAttribute {
- // is this an empty binding in the middle of the star, or is it the original
- // prefix binding which is usually harmless to be empty?
- bool isPrefix;
-
- EmptyStarBinding(
- String name, int nameOffset, String originalName, int originalNameOffset,
- {@required this.isPrefix})
- : super.synthetic(
- name, nameOffset, null, null, originalName, originalNameOffset, []);
-
- @override
- void accept(AngularAstVisitor visitor) => visitor.visitEmptyStarBinding(this);
-}
-
-class ExpressionBoundAttribute extends BoundAttributeInfo {
- Expression expression;
- final ExpressionBoundType bound;
- ExpressionBoundAttribute(
- String name,
- int nameOffset,
- String value,
- int valueOffset,
- String originalName,
- int originalNameOffset,
- this.expression,
- this.bound)
- : super(name, nameOffset, value, valueOffset, originalName,
- originalNameOffset);
-
- @override
- void accept(AngularAstVisitor visitor) =>
- visitor.visitExpressionBoundAttr(this);
-
- @override
- String toString() => '(${super.toString()}, [$bound, $expression])';
-}
-
-enum ExpressionBoundType { input, twoWay, attr, attrIf, clazz, style }
-
-/// An AngularAstNode which has directives, such as [ElementInfo] and
-/// [TemplateAttribute]. Contains an array of [DirectiveBinding]s because those
-/// contain more info than just the bound directive.
-abstract class HasDirectives extends AngularAstNode {
- Map<AbstractDirective, List<AngularElement>> get availableDirectives;
- List<DirectiveBinding> get boundDirectives;
- List<InputBinding> get boundStandardInputs;
- List<OutputBinding> get boundStandardOutputs;
-}
-
-/// A binding between an [AttributeInfo] and an [InputElement]. This is used in
-/// the context of a [DirectiveBinding] because each instance of a bound
-/// directive has different input bindings. Note that inputs can be bound via
-/// bracket syntax (an [ExpressionBoundAttribute]), or via plain attribute syntax
-/// (a [TextAttribute]).
-///
-/// Naming here is important: "bound input" != "input binding."
-class InputBinding {
- final InputElement boundInput;
- final AttributeInfo attribute;
-
- InputBinding(this.boundInput, this.attribute);
-}
-
-/// A variable defined by a [AbstractDirective].
-class LocalVariable extends AngularElementImpl {
- final LocalVariableElement dartVariable;
-
- LocalVariable(String name, int nameOffset, int nameLength, Source source,
- this.dartVariable)
- : super(name, nameOffset, nameLength, source);
-}
-
-class Mustache extends AngularAstNode {
- Expression expression;
- @override
- final int offset;
- @override
- final int length;
- final int exprBegin;
- final int exprEnd;
-
- Map<String, LocalVariable> localVariables =
- new HashMap<String, LocalVariable>();
-
- Mustache(
- this.offset,
- this.length,
- this.expression,
- this.exprBegin,
- this.exprEnd,
- );
-
- @override
- List<AngularAstNode> get children => const <AngularAstNode>[];
-
- @override
- void accept(AngularAstVisitor visitor) => visitor.visitMustache(this);
-}
-
-/// The HTML elements in the tree
-abstract class NodeInfo extends AngularAstNode {
- bool get isSynthetic;
-}
-
-/// A binding between an [BoundAttributeInfo] and an [OutputElement]. This is
-/// used in the context of a [DirectiveBinding] because each instance of a bound
-/// directive has different output bindings.
-///
-/// Binds to an [BoundAttributeInfo] and not a [StatementsBoundAttribute] because
-/// it might be a two-way binding, and thats the greatest common subtype of
-/// statements bound and expression bound attributes.
-///
-/// Naming here is important: "bound output" != "output binding."
-class OutputBinding {
- final OutputElement boundOutput;
- final BoundAttributeInfo attribute;
-
- OutputBinding(this.boundOutput, this.attribute);
-}
-
-class StatementsBoundAttribute extends BoundAttributeInfo {
- List<Statement> statements;
-
- /// Reductions as in `(keyup.ctrl.shift.space)`. Not currently analyzed.
- List<String> reductions;
-
- StatementsBoundAttribute(
- String name,
- int nameOffset,
- String value,
- int valueOffset,
- String originalName,
- int originalNameOffset,
- this.reductions,
- this.statements)
- : super(name, nameOffset, value, valueOffset, originalName,
- originalNameOffset);
-
- int get reductionsLength =>
- reductions.isEmpty ? null : '.'.length + reductions.join('.').length;
-
- int get reductionsOffset =>
- reductions.isEmpty ? null : nameOffset + name.length;
- @override
- void accept(AngularAstVisitor visitor) =>
- visitor.visitStatementsBoundAttr(this);
-
- @override
- String toString() => '(${super.toString()}, [$statements])';
-}
-
-class TemplateAttribute extends BoundAttributeInfo implements HasDirectives {
- final List<AttributeInfo> virtualAttributes;
- @override
- final boundDirectives = <DirectiveBinding>[];
- @override
- final boundStandardOutputs = <OutputBinding>[];
- @override
- final boundStandardInputs = <InputBinding>[];
- @override
- final availableDirectives = <AbstractDirective, List<AngularElement>>{};
-
- String prefix;
-
- TemplateAttribute(String name, int nameOffset, String value, int valueOffset,
- String originalName, int originalNameOffset, this.virtualAttributes,
- {this.prefix})
- : super(name, nameOffset, value, valueOffset, originalName,
- originalNameOffset);
-
- @override
- List<AngularAstNode> get children =>
- new List<AngularAstNode>.from(virtualAttributes);
-
- List<AbstractDirective> get directives =>
- boundDirectives.map((bd) => bd.boundDirective).toList();
-
- @override
- void accept(AngularAstVisitor visitor) => visitor.visitTemplateAttr(this);
-
- @override
- String toString() => '(${super.toString()}, [$virtualAttributes])';
-}
-
-class TextAttribute extends AttributeInfo {
- final List<Mustache> mustaches;
- final bool isReference;
-
- TextAttribute(String name, int nameOffset, String value, int valueOffset,
- this.mustaches)
- : isReference = name.startsWith('#'),
- super(name, nameOffset, value, valueOffset, name, nameOffset);
-
- TextAttribute.synthetic(
- String name,
- int nameOffset,
- String value,
- int valueOffset,
- String originalName,
- int originalNameOffset,
- this.mustaches)
- : isReference = name.startsWith('#'),
- super(name, nameOffset, value, valueOffset, originalName,
- originalNameOffset);
-
- @override
- List<AngularAstNode> get children => new List<AngularAstNode>.from(mustaches);
-
- @override
- void accept(AngularAstVisitor visitor) => visitor.visitTextAttr(this);
-}
-
-/// A text node in an HTML tree.
-class TextInfo extends NodeInfo {
- final List<Mustache> mustaches;
- final ElementInfo parent;
- final String text;
-
- @override
- final int offset;
- final bool _isSynthetic;
- TextInfo(this.offset, this.text, this.parent, this.mustaches,
- {bool synthetic: false})
- : _isSynthetic = synthetic;
-
- @override
- List<AngularAstNode> get children => new List<AngularAstNode>.from(mustaches);
-
- @override
- bool get isSynthetic => _isSynthetic;
-
- @override
- int get length => text.length;
-
- @override
- void accept(AngularAstVisitor visitor) => visitor.visitTextInfo(this);
-}
diff --git a/angular_analyzer_plugin/lib/errors.dart b/angular_analyzer_plugin/lib/errors.dart
deleted file mode 100644
index e585663..0000000
--- a/angular_analyzer_plugin/lib/errors.dart
+++ /dev/null
@@ -1,551 +0,0 @@
-import 'dart:collection';
-
-import 'package:analyzer/error/error.dart';
-import 'package:angular_ast/angular_ast.dart';
-
-/// used by angularWarningCodeByUniqueName to create a map for fast lookup
-const _angularWarningCodeValues = const <AngularWarningCode>[
- AngularWarningCode.ARGUMENT_SELECTOR_MISSING,
- AngularWarningCode.CANNOT_PARSE_SELECTOR,
- AngularWarningCode.REFERENCED_HTML_FILE_DOESNT_EXIST,
- AngularWarningCode.COMPONENT_ANNOTATION_MISSING,
- AngularWarningCode.TEMPLATE_URL_AND_TEMPLATE_DEFINED,
- AngularWarningCode.NO_TEMPLATE_URL_OR_TEMPLATE_DEFINED,
- AngularWarningCode.EXPECTED_IDENTIFIER,
- AngularWarningCode.UNEXPECTED_HASH_IN_TEMPLATE,
- AngularWarningCode.STRING_VALUE_EXPECTED,
- AngularWarningCode.TYPE_LITERAL_EXPECTED,
- AngularWarningCode.TYPE_IS_NOT_A_DIRECTIVE,
- AngularWarningCode.FUNCTION_IS_NOT_A_DIRECTIVE,
- AngularWarningCode.UNRESOLVED_TAG,
- AngularWarningCode.UNTERMINATED_MUSTACHE,
- AngularWarningCode.UNOPENED_MUSTACHE,
- AngularWarningCode.NONEXIST_INPUT_BOUND,
- AngularWarningCode.NONEXIST_OUTPUT_BOUND,
- AngularWarningCode.EMPTY_BINDING,
- AngularWarningCode.NONEXIST_TWO_WAY_OUTPUT_BOUND,
- AngularWarningCode.TWO_WAY_BINDING_OUTPUT_TYPE_ERROR,
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR,
- AngularWarningCode.ATTR_IF_BINDING_TYPE_ERROR,
- AngularWarningCode.UNMATCHED_ATTR_IF_BINDING,
- AngularWarningCode.TRAILING_EXPRESSION,
- AngularWarningCode.OUTPUT_MUST_BE_STREAM,
- AngularWarningCode.TWO_WAY_BINDING_NOT_ASSIGNABLE,
- AngularWarningCode.INPUT_ANNOTATION_PLACEMENT_INVALID,
- AngularWarningCode.OUTPUT_ANNOTATION_PLACEMENT_INVALID,
- AngularWarningCode.INVALID_HTML_CLASSNAME,
- AngularWarningCode.CLASS_BINDING_NOT_BOOLEAN,
- AngularWarningCode.CSS_UNIT_BINDING_NOT_NUMBER,
- AngularWarningCode.INVALID_CSS_UNIT_NAME,
- AngularWarningCode.INVALID_CSS_PROPERTY_NAME,
- AngularWarningCode.INVALID_BINDING_NAME,
- AngularWarningCode.STRUCTURAL_DIRECTIVES_REQUIRE_TEMPLATE,
- AngularWarningCode.CUSTOM_DIRECTIVE_MAY_REQUIRE_TEMPLATE,
- AngularWarningCode.TEMPLATE_ATTR_NOT_USED,
- AngularWarningCode.NO_DIRECTIVE_EXPORTED_BY_SPECIFIED_NAME,
- AngularWarningCode.CONTENT_NOT_TRANSCLUDED,
- AngularWarningCode.OUTPUT_STATEMENT_REQUIRES_EXPRESSION_STATEMENT,
- AngularWarningCode.DISALLOWED_EXPRESSION,
- AngularWarningCode.ATTRIBUTE_PARAMETER_MUST_BE_STRING,
- AngularWarningCode.STRING_STYLE_INPUT_BINDING_INVALID,
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY,
- AngularWarningCode.UNKNOWN_CHILD_QUERY_TYPE,
- AngularWarningCode.CHILD_QUERY_TYPE_REQUIRES_READ,
- AngularWarningCode.CONTENT_OR_VIEW_CHILDREN_REQUIRES_QUERY_LIST,
- AngularWarningCode.CONTENT_OR_VIEW_CHILDREN_REQUIRES_LIST,
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- AngularWarningCode.EXPORTS_MUST_BE_PLAIN_IDENTIFIERS,
- AngularWarningCode.DUPLICATE_EXPORT,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.COMPONENTS_CANT_EXPORT_THEMSELVES,
- AngularWarningCode.PIPE_SINGLE_NAME_REQUIRED,
- AngularWarningCode.TYPE_IS_NOT_A_PIPE,
- AngularWarningCode.PIPE_CANNOT_BE_ABSTRACT,
- AngularWarningCode.PIPE_REQUIRES_PIPETRANSFORM,
- AngularWarningCode.PIPE_REQUIRES_TRANSFORM_METHOD,
- AngularWarningCode.PIPE_TRANSFORM_NO_NAMED_ARGS,
- AngularWarningCode.PIPE_TRANSFORM_REQ_ONE_ARG,
- AngularWarningCode.PIPE_NOT_FOUND,
- AngularWarningCode.AMBIGUOUS_PIPE,
- AngularWarningCode.UNSAFE_BINDING,
- AngularWarningCode.EVENT_REDUCTION_NOT_ALLOWED,
- AngularWarningCode.FUNCTIONAL_DIRECTIVES_CANT_BE_EXPORTED,
- AngularHintCode.OFFSETS_CANNOT_BE_CREATED,
-];
-
-/// The lazy initialized map from [AngularWarningCode.uniqueName] to the
-/// [AngularWarningCode] instance.
-HashMap<String, ErrorCode> _uniqueNameToCodeMap;
-
-/// Return the [AngularWarningCode] with the given [uniqueName], or `null` if not
-/// found.
-ErrorCode angularWarningCodeByUniqueName(String uniqueName) {
- if (_uniqueNameToCodeMap == null) {
- _uniqueNameToCodeMap = new HashMap<String, ErrorCode>();
- for (final angularCode in _angularWarningCodeValues) {
- _uniqueNameToCodeMap[angularCode.uniqueName] = angularCode;
- }
- for (final angularAstCode in angularAstWarningCodes) {
- _uniqueNameToCodeMap[angularAstCode.uniqueName] = angularAstCode;
- }
- }
- return _uniqueNameToCodeMap[uniqueName];
-}
-
-class AngularHintCode extends AngularWarningCode {
- /// When a user does for instance `template: 'foo$bar$baz`, we cannot analyze
- /// the template because we cannot easily map errors to code offsets.
- static const OFFSETS_CANNOT_BE_CREATED = const AngularHintCode(
- 'OFFSETS_CANNOT_BE_CREATED',
- 'Errors cannot be tracked for the constant expression because it is too'
- ' complex for errors to be mapped to locations in the file');
-
- /// Initialize a newly created error code to have the given [name].
- /// The message associated with the error will be created from the given
- /// [message] template. The correction associated with the error will be
- /// created from the given [correction] template.
- const AngularHintCode(String name, String message, [String correction])
- : super(name, message, correction);
-
- @override
- ErrorSeverity get errorSeverity => ErrorSeverity.INFO;
-
- @override
- ErrorType get type => ErrorType.HINT;
-}
-
-/// The error codes used for Angular warnings. The convention for this
-/// class is for the name of the error code to indicate the problem that caused
-/// the error to be generated and for the error message to explain what is wrong
-/// and, when appropriate, how the problem can be corrected.
-class AngularWarningCode extends ErrorCode {
- /// An error code indicating that the annotation does not define the
- /// required "selector" argument.
- static const ARGUMENT_SELECTOR_MISSING = const AngularWarningCode(
- 'ARGUMENT_SELECTOR_MISSING', 'Argument "selector" missing');
-
- /// An error code indicating that the provided selector cannot be parsed.
- static const CANNOT_PARSE_SELECTOR = const AngularWarningCode(
- 'CANNOT_PARSE_SELECTOR', 'Cannot parse the given selector ({0})');
-
- /// An error code indicating that a template points to a missing html file
- static const REFERENCED_HTML_FILE_DOESNT_EXIST = const AngularWarningCode(
- 'REFERENCED_HTML_FILE_DOESNT_EXIST',
- 'The referenced HTML file doesn\'t exist');
-
- /// An error code indicating that the component has @View annotation,
- /// but not @Component annotation.
- static const COMPONENT_ANNOTATION_MISSING = const AngularWarningCode(
- 'COMPONENT_ANNOTATION_MISSING',
- 'Every @View requires exactly one @Component annotation');
-
- /// An error code indicating that a @View or @Component has both a
- /// template and a templateUrl defined at once (illegal)
- static const TEMPLATE_URL_AND_TEMPLATE_DEFINED = const AngularWarningCode(
- 'TEMPLATE_URL_AND_TEMPLATE_DEFINED',
- 'Cannot define both template and templateUrl. Remove one');
-
- /// An error code indicating that a @View or @Component does not have
- /// a template or a templateUrl
- static const NO_TEMPLATE_URL_OR_TEMPLATE_DEFINED = const AngularWarningCode(
- 'NO_TEMPLATE_URL_OR_TEMPLATE_DEFINED',
- 'Either a template or templateUrl is required');
-
- /// An error code indicating that an identifier was expected, but not found.
- static const EXPECTED_IDENTIFIER =
- const AngularWarningCode('EXPECTED_IDENTIFIER', 'Expected identifier');
-
- /// An error code indicating that an hash was unexpected in template.
- static const UNEXPECTED_HASH_IN_TEMPLATE = const AngularWarningCode(
- 'UNEXPECTED_HASH_IN_TEMPLATE', "Did you mean 'let' instead?");
-
- /// An error code indicating that the value of an expression is not a string.
- static const STRING_VALUE_EXPECTED = const AngularWarningCode(
- 'STRING_VALUE_EXPECTED', 'A string value expected');
-
- /// An error code indicating that the value of an expression is not a string.
- static const TYPE_LITERAL_EXPECTED = const AngularWarningCode(
- 'TYPE_LITERAL_EXPECTED', 'A type literal expected');
-
- /// An error code indicating that the value of an expression is not a string.
- static const TYPE_IS_NOT_A_DIRECTIVE = const AngularWarningCode(
- 'TYPE_IS_NOT_A_DIRECTIVE',
- 'The type "{0}" is included in the directives list, but is not a'
- ' directive');
-
- /// An error code indicating that a function not annotated with @Directive was
- /// used as one.
- static const FUNCTION_IS_NOT_A_DIRECTIVE = const AngularWarningCode(
- 'FUNCTION_IS_NOT_A_DIRECTIVE',
- 'The function "{0}" is included in the directives list, but is not a'
- ' functional directive');
-
- /// An error code indicating that the value of type is not a Pipe.
- static const TYPE_IS_NOT_A_PIPE = const AngularWarningCode(
- 'TYPE_IS_NOT_A_PIPE',
- 'The type "{0}" is included in the pipes list, but is not a pipe');
-
- /// An error code indicating that the tag was not resolved.
- static const UNRESOLVED_TAG =
- const AngularWarningCode('UNRESOLVED_TAG', 'Unresolved tag "{0}"');
-
- /// An error code indicating that the embedded expression is not terminated.
- static const UNTERMINATED_MUSTACHE = const AngularWarningCode(
- 'UNTERMINATED_MUSTACHE', 'Unterminated mustache');
-
- /// An error code indicating that a mustache ending was found unopened
- static const UNOPENED_MUSTACHE = const AngularWarningCode(
- 'UNOPENED_MUSTACHE', 'Mustache terminator with no opening');
-
- /// An error code indicating that a nonexist input was bound
- static const NONEXIST_INPUT_BOUND = const AngularWarningCode(
- 'NONEXIST_INPUT_BOUND',
- 'The bound input {0} does not exist on any directives or on the element');
-
- /// An error code indicating that a nonexist output was bound
- static const NONEXIST_OUTPUT_BOUND = const AngularWarningCode(
- 'NONEXIST_OUTPUT_BOUND',
- 'The bound output {0} does not exist on any directives or on the'
- ' element');
-
- /// An error code indicating that a nonexist output was bound
- static const EMPTY_BINDING = const AngularWarningCode(
- 'EMPTY_BINDING', 'The binding {0} does not have a value specified');
-
- /// An error code indicating that a nonexist output was bound, perhaps
- /// because an input was two way bound. The nonexist bound output is
- /// an implementation detail, so give its own error.
- static const NONEXIST_TWO_WAY_OUTPUT_BOUND = const AngularWarningCode(
- 'NONEXIST_TWO_WAY_OUTPUT_BOUND',
- 'The two-way binding {0} requires a bindable output of name {1}');
-
- /// An error code indicating that the output event in a two-way binding
- /// doesn't match the input
- static const TWO_WAY_BINDING_OUTPUT_TYPE_ERROR = const AngularWarningCode(
- 'TWO_WAY_BINDING_OUTPUT_TYPE_ERROR',
- 'Output event in two-way binding (of type {0}) is not assignable to'
- ' component input (of type {1})');
-
- /// An error code indicating that an input was bound with a incorrectly
- /// typed expression
- static const INPUT_BINDING_TYPE_ERROR = const AngularWarningCode(
- 'INPUT_BINDING_TYPE_ERROR',
- 'Attribute value expression (of type {0}) is not assignable to component'
- ' input (of type {1})');
-
- /// An error code indicating that an [attr.foo.if] binding was bound to an
- /// expression that was not of type bool
- static const ATTR_IF_BINDING_TYPE_ERROR = const AngularWarningCode(
- 'ATTR_IF_BINDING_TYPE_ERROR',
- 'Attribute value expression (of type {0}) must be of type bool');
-
- /// An error code indicating that an [attr.foo.if] binding was used, but no
- /// [attr.foo] binding simultaneously occured.
- static const UNMATCHED_ATTR_IF_BINDING = const AngularWarningCode(
- 'UNMATCHED_ATTR_IF_BINDING',
- 'attr-if binding for attr {0} does not have a corresponding'
- ' [attr.{0}] binding for it to affect');
-
- /// An error code indicating that an expression did not correctly
- /// end with an EOF token.
- static const TRAILING_EXPRESSION = const AngularWarningCode(
- 'TRAILING_EXPRESSION', 'Expressions must end with an EOF');
-
- /// An error code indicating that an @Output is not an EventEmitter
- static const OUTPUT_MUST_BE_STREAM = const AngularWarningCode(
- 'OUTPUT_MUST_BE_STREAM', 'Output (of name {0}) must return a Stream');
-
- /// An error code indicating that a two-way binding expression was not
- /// a assignable (and therefore could only be one-way bound...)
- static const TWO_WAY_BINDING_NOT_ASSIGNABLE = const AngularWarningCode(
- 'TWO_WAY_BINDING_NOT_ASSIGNABLE',
- 'Only assignable expressions can be two-way bound');
-
- /// An error code indicating that an @Input annottaion was used in the wrong
- /// place
- static const INPUT_ANNOTATION_PLACEMENT_INVALID = const AngularWarningCode(
- 'INPUT_ANNOTATION_PLACEMENT_INVALID',
- 'The @Input() annotation can only be put on properties and setters');
-
- /// An error code indicating that an @Output annottaion was used in the wrong
- /// place
- static const OUTPUT_ANNOTATION_PLACEMENT_INVALID = const AngularWarningCode(
- 'OUTPUT_ANNOTATION_PLACEMENT_INVALID',
- 'The @Output() annotation can only be put on properties and getters');
-
- /// An error code indicating that a html classname was bound via
- /// [class.classname]="x" where classname is not a css identifier
- /// https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- static const INVALID_HTML_CLASSNAME = const AngularWarningCode(
- 'INVALID_HTML_CLASSNAME',
- 'The html classname {0} is not a valid classname');
-
- /// An error code indicating that a html classname was bound via
- /// [class.classname]="x" where x was not a boolean
- static const CLASS_BINDING_NOT_BOOLEAN = const AngularWarningCode(
- 'CLASS_BINDING_NOT_BOOLEAN', 'Binding to a classname requires a boolean');
-
- /// An error code indicating that a css property with a unit was bound via
- /// [style.property.unit]="x" where x was not a number
- static const CSS_UNIT_BINDING_NOT_NUMBER = const AngularWarningCode(
- 'CSS_UNIT_BINDING_NOT_NUMBER',
- 'Binding to a css property with a unit requires a number');
-
- /// An error code indicating that a css property with a unit was bound via
- /// [style.property.unit]="x" where unit was not an identifier
- /// https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- static const INVALID_CSS_UNIT_NAME = const AngularWarningCode(
- 'INVALID_CSS_UNIT_NAME',
- 'The css unit {0} is not a valid css identifier');
-
- /// An error code indicating that a css property bound via
- /// [style.property]="x" or [style.property.unit]="x" where property was not an
- /// identifier
- /// https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- static const INVALID_CSS_PROPERTY_NAME = const AngularWarningCode(
- 'INVALID_CSS_PROPERTY_NAME',
- 'The css property {0} is not a valid css identifier');
-
- /// An error code indicating that a binding was not a * dart identifier, or
- /// [class.classname], or [attr.attrname], or [style.property], or
- /// [style.property.unit].
- static const INVALID_BINDING_NAME = const AngularWarningCode(
- 'INVALID_BINDING_NAME',
- 'The binding {} is not a valid dart identifer, attribute, style, or class'
- ' binding');
-
- /// An error code indicating that ngIf or ngFor were used without a template
- static const STRUCTURAL_DIRECTIVES_REQUIRE_TEMPLATE =
- const AngularWarningCode(
- 'STRUCTURAL_DIRECTIVES_REQUIRE_TEMPLATE',
- 'Structural directive {0} requires a template. Did you mean'
- ' *{0}="..." or template="{0} ..." or <template {0} ...>?');
-
- /// An error code indicating in #y="x", x was not an exported name
- static const NO_DIRECTIVE_EXPORTED_BY_SPECIFIED_NAME =
- const AngularWarningCode('NO_DIRECTIVE_EXPORTED_BY_SPECIFIED_NAME',
- 'No directives matching this element are exported by the name {0}');
-
- /// An error code indicating in <div dir1 dir2 #y="x">, x is ambigious since
- /// both directives dir1 and dir2 have same exportAs name "x".
- static const DIRECTIVE_EXPORTED_BY_AMBIGIOUS = const AngularWarningCode(
- 'DIRECTIVE_EXPORTED_BY_AMBIGIOUS',
- "More than one directive's exportAs value matches '{0}'.");
-
- /// An error code indicating that a custom component appears to require a star.
- static const AngularWarningCode CUSTOM_DIRECTIVE_MAY_REQUIRE_TEMPLATE =
- const AngularWarningCode(
- 'CUSTOM_DIRECTIVE_MAY_REQUIRE_TEMPLATE',
- 'The directive {0} accepts a TemplateRef in its constructor, so it'
- ' may require a *-style-attr to work correctly.');
-
- /// An error code indicating that a custom component appears to require a star.
- static const AngularWarningCode TEMPLATE_ATTR_NOT_USED =
- const AngularWarningCode(
- 'TEMPLATE_ATTR_NOT_USED',
- 'This template attr does not match any directives that use the'
- ' resulting hidden template. Check that all directives are being'
- ' imported and used correctly.');
-
- /// An error code indicating that an output-bound statement
- /// must be an [ExpressionStatement].
- static const OUTPUT_STATEMENT_REQUIRES_EXPRESSION_STATEMENT =
- const AngularWarningCode('OUTPUT_STATEMENT_REQUIRES_EXPRESSION_STATEMENT',
- "Syntax Error: unexpected {0}");
-
- /// An error code indicating that a mustache or other expression binding was an
- /// unsupported type such as an 'as' expression or a constructor
- static const DISALLOWED_EXPRESSION = const AngularWarningCode(
- 'DISALLOWED_EXPRESSION', "{0} not allowed in angular templates");
-
- /// An error code indicating that dom inside a component won't be transcluded
- static const CONTENT_NOT_TRANSCLUDED = const AngularWarningCode(
- 'CONTENT_NOT_TRANSCLUDED',
- 'The content does not match any transclusion selectors of the surrounding'
- ' component');
-
- /// An error code indicating that an <ng-content> tag had content, which is not
- /// allowed.
- static const NG_CONTENT_MUST_BE_EMPTY = const AngularWarningCode(
- 'NG_CONTENT_MUST_BE_EMPTY',
- 'Nothing is allowed inside an <ng-content> tag, as it will be replaced');
-
- /// An error code indicating that a constructor parameter was marked with
- /// @Attribute, but the argument wasn't of type string.
- static const ATTRIBUTE_PARAMETER_MUST_BE_STRING = const AngularWarningCode(
- 'ATTRIBUTE_PARAMETER_MUST_BE_STRING',
- 'Parameters marked with @Attribute must be of type String');
-
- /// An error code indicating that an input binding was used in string form, ie,
- /// `x="y"` rather than `[x]="y"`, where input x is not a string input.
- static const STRING_STYLE_INPUT_BINDING_INVALID = const AngularWarningCode(
- 'STRING_STYLE_INPUT_BINDING_INVALID',
- 'Input {0} is not a string input, but is not bound with [bracket] syntax.'
- ' This binds the String attribute value directly, resulting in a type '
- 'error.');
-
- /// An error code indicating that a @ContentChild or @ContentChildren field
- /// either mismatched types in the definition, or where it was used (ie
- /// `@ContentChild(TemplateRef) ElementRef foo`, or `@ContentChild('foo')
- /// TemplateRef foo` with `<div #foo>`).
- static const INVALID_TYPE_FOR_CHILD_QUERY = const AngularWarningCode(
- 'INVALID_TYPE_FOR_CHILD_QUERY',
- 'The field {0} marked with @{1} referencing type {2} expects a member'
- ' referencing type {2}, but got a {3}');
-
- /// An error code indicating that a @ContentChild or @ContentChildren field
- /// didn't have an expected value
- static const UNKNOWN_CHILD_QUERY_TYPE = const AngularWarningCode(
- 'UNKNOWN_CHILD_QUERY_TYPE',
- 'The field {0} marked with @{1} must reference a directive, a string'
- ' let-binding name, TemplateRef, or ElementRef');
-
- /// An error code indicating that a @ContentChild or @ContentChildren field
- /// didn't have an expected value
- static const CHILD_QUERY_TYPE_REQUIRES_READ = const AngularWarningCode(
- 'CHILD_QUERY_TYPE_REQUIRES_READ',
- 'The field {0} marked with @{1} cannot reference type {2} unless the @{1}'
- ' annotation includes `read: {2}`');
-
- /// An error code indicating that @ContentChildren or @ViewChildren was used
- /// but the property wasn't a `QueryList`.
- static const CONTENT_OR_VIEW_CHILDREN_REQUIRES_LIST =
- const AngularWarningCode(
- 'CONTENT_OR_VIEW_CHILDREN_REQUIRES_LIST',
- 'The field {0} marked with @{1} expects a member of type List,'
- ' but got {2}');
-
- /// Here for backwards compatibility. Should not be used. Use
- /// [CONTENT_OR_VIEW_CHILDREN_REQUIRES_LIST] instead. Note: we can remove this
- /// the next time we tick the salt in `lib/src/file_tracker.dart`.
- @deprecated
- static const CONTENT_OR_VIEW_CHILDREN_REQUIRES_QUERY_LIST =
- const AngularWarningCode(
- 'CONTENT_OR_VIEW_CHILDREN_REQUIRES_QUERY_LIST',
- 'The field {0} marked with @{1} expects a member of type QueryList,'
- ' but got {2}');
-
- /// An error code indicating that @ContentChild or @ViewChild with a string
- /// let-binding query was matched in a way that's not assignable to the
- /// annotated property.
- static const MATCHED_LET_BINDING_HAS_WRONG_TYPE = const AngularWarningCode(
- 'MATCHED_LET_BINDING_HAS_WRONG_TYPE',
- 'Marking this with #{0} here expects the element to be of type {1}, (but'
- ' is of type {2}) because an enclosing element marks {0} as a content'
- ' child field of type {1}.');
-
- /// An error code indicating that @ContentChild or @ViewChild was matched
- /// multiple times.
- static const SINGULAR_CHILD_QUERY_MATCHED_MULTIPLE_TIMES =
- const AngularWarningCode(
- 'SINGULAR_CHILD_QUERY_MATCHED_MULTIPLE_TIMES',
- 'A containing {0} expects a single child matching {1}, but this is'
- ' not the first match. Use (Content or View)Children to allow'
- ' multiple matches.');
-
- /// An error code indicating that the exports array got a non-identifier
- static const EXPORTS_MUST_BE_PLAIN_IDENTIFIERS = const AngularWarningCode(
- 'EXPORTS_MUST_BE_PLAIN_IDENTIFIERS', 'Exports must be plain identifiers');
-
- /// An error code indicating that an identifier was exported multiple times
- static const DUPLICATE_EXPORT = const AngularWarningCode(
- 'DUPLICATE_EXPORT', 'Duplicate export of identifier {0}');
-
- /// An error code indicating that an identifier was used in a template, but
- /// not exported in the component.
- static const IDENTIFIER_NOT_EXPORTED = const AngularWarningCode(
- 'IDENTIFIER_NOT_EXPORTED',
- 'Identifier {0} was not exported by the component and therefore cannot be'
- ' used in its template. Add it to the exports property on the component'
- ' definition to use it here.');
-
- /// An error code indicating component Foo exports Foo, which is unnecessary
- static const COMPONENTS_CANT_EXPORT_THEMSELVES = const AngularWarningCode(
- 'COMPONENTS_CANT_EXPORT_THEMSELVES',
- 'Components export their class by default, and therefore should not be'
- ' specified in the exports list');
-
- /// An error code indicating that the Pipe class cannot be abstract.
- static const PIPE_CANNOT_BE_ABSTRACT = const AngularWarningCode(
- 'PIPE_CANNOT_BE_ABSTRACT', r'Pipe classes cannot be abstract');
-
- /// An error code indicating that the Pipe annotation does not define the
- /// required pipe name argument - and is the only non-named argument.
- static const PIPE_SINGLE_NAME_REQUIRED = const AngularWarningCode(
- 'PIPE_NAME_MISSING',
- r'@Pipe declarations must contain exactly one'
- r' non-named argument of String type for pipe name');
-
- /// An error code indicating that a declared Pipe does not extend
- /// [PipeTransform] class.
- static const PIPE_REQUIRES_PIPETRANSFORM = const AngularWarningCode(
- 'PIPE_REQUIRES_PIPETRANSFORM',
- "@Pipe declared classes need to extend 'PipeTransform'");
-
- /// An error code indicating that a declared Pipe does not have
- /// a 'transform' method.
- static const PIPE_REQUIRES_TRANSFORM_METHOD = const AngularWarningCode(
- 'PIPE_REQUIRES_TRANSFORM_METHOD',
- "@Pipe declared classes must contain a 'transform' method",
- );
-
- /// An error indicating that the 'transform' method within a Pipe
- /// cannot have named arguments.
- static const PIPE_TRANSFORM_NO_NAMED_ARGS = const AngularWarningCode(
- 'PIPE_TRANSFORM_NO_NAMED_ARGS',
- "'transform' method for pipe should not have named arguments");
-
- /// An error indicating that the 'transform' method within a Pipe
- /// requires at least one argument.
- static const PIPE_TRANSFORM_REQ_ONE_ARG = const AngularWarningCode(
- 'PIPE_TRANSFORM_REQ_ONE_ARG',
- "'transform' method requires at least one argument");
-
- /// An error indicating that pipe syntax was used in an angular template, but
- /// the name of the pipe doesn't match one defined in the component
- static const PIPE_NOT_FOUND = const AngularWarningCode(
- 'PIPE_NOT_FOUND',
- "Pipe by name of {0} not found. Did you reference it in your @Component"
- " configuration?");
-
- /// An error indicating that pipe syntax was used in an angular template, but
- /// the name of the pipe doesn't match one defined in the component
- static const AMBIGUOUS_PIPE = const AngularWarningCode(
- 'AMBIGUOUS_PIPE',
- "Multiple pipes by name of {0} found. Check the `pipes` field of your "
- "@Component annotation for duplicates and/or conflicts.");
-
- /// An error indicating that a security exception will be thrown by this input
- /// binding
- static const UNSAFE_BINDING = const AngularWarningCode(
- 'UNSAFE_BINDING',
- 'A security exception will be thrown by this binding. You must use the '
- ' security service to get an instance of {0} and bind that result.');
-
- /// An error indicating that an event other than `(keyup.x)` or `(keydown.+)`
- /// etc, had reduction suffixes in that style, which is not allowed.
- static const EVENT_REDUCTION_NOT_ALLOWED = const AngularWarningCode(
- 'EVENT_REDUCTION_NOT_ALLOWED',
- 'Event reductions are only allowed on keyup and keydown events');
-
- /// An error indicating that functional directve had exportAs specified, which
- /// is not allowed.
- static const FUNCTIONAL_DIRECTIVES_CANT_BE_EXPORTED =
- const AngularWarningCode(
- 'FUNCTIONAL_DIRECTIVES_CANT_BE_EXPORTED',
- 'Function directives cannot have an exportAs setting, because they'
- " can't be exported");
-
- /// Initialize a newly created error code to have the given [name].
- /// The message associated with the error will be created from the given
- /// [message] template. The correction associated with the error will be
- /// created from the given [correction] template.
- const AngularWarningCode(String name, String message, [String correction])
- : super(name, message, correction);
-
- @override
- ErrorSeverity get errorSeverity => ErrorSeverity.WARNING;
-
- @override
- ErrorType get type => ErrorType.STATIC_WARNING;
-}
diff --git a/angular_analyzer_plugin/lib/notification_manager.dart b/angular_analyzer_plugin/lib/notification_manager.dart
deleted file mode 100644
index 2333bf2..0000000
--- a/angular_analyzer_plugin/lib/notification_manager.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-abstract class NotificationManager {
- void recordAnalysisErrors(
- String path, LineInfo lineInfo, List<AnalysisError> analysisErrors);
-}
diff --git a/angular_analyzer_plugin/lib/plugin.dart b/angular_analyzer_plugin/lib/plugin.dart
deleted file mode 100644
index 2ec6526..0000000
--- a/angular_analyzer_plugin/lib/plugin.dart
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-import 'dart:async';
-
-import 'package:analyzer/context/context_root.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/builder.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer_plugin/plugin/completion_mixin.dart';
-import 'package:analyzer_plugin/plugin/navigation_mixin.dart';
-import 'package:analyzer_plugin/plugin/plugin.dart';
-import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
-import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
-import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
-import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
-import 'package:analyzer_plugin/src/utilities/completion/completion_core.dart';
-import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
-import 'package:analyzer_plugin/utilities/analyzer_converter.dart';
-import 'package:analyzer_plugin/utilities/completion/completion_core.dart';
-import 'package:analyzer_plugin/utilities/navigation/navigation.dart';
-import 'package:angular_analyzer_plugin/src/angular_driver.dart';
-import 'package:angular_analyzer_plugin/src/completion.dart';
-import 'package:angular_analyzer_plugin/src/completion_request.dart';
-import 'package:angular_analyzer_plugin/src/navigation.dart';
-import 'package:angular_analyzer_plugin/src/navigation_request.dart';
-import 'package:angular_analyzer_plugin/src/notification_manager.dart';
-import 'package:angular_analyzer_plugin/src/options.dart';
-import 'package:meta/meta.dart';
-
-class AngularAnalyzerPlugin extends ServerPlugin
- with CompletionMixin, NavigationMixin {
- AngularAnalyzerPlugin(ResourceProvider provider) : super(provider);
-
- @override
- String get contactInfo =>
- 'Please file issues at https://github.com/dart-lang/angular_analyzer_plugin';
-
- @override
- List<String> get fileGlobsToAnalyze => <String>['*.dart', '*.html'];
-
- @override
- String get name => 'Angular Analysis Plugin';
-
- @override
- String get version => '1.0.0-alpha.0';
-
- AngularDriver angularDriverForPath(String path) {
- final driver = super.driverForPath(path);
- if (driver is AngularDriver) {
- return driver;
- }
- return null;
- }
-
- @override
- void contentChanged(String path) {
- final driver = angularDriverForPath(path);
- if (driver == null) {
- return;
- }
-
- driver
- ..addFile(path) // TODO new API to only do this on file add
- ..fileChanged(path);
-
- driver.dartDriver
- ..addFile(path) // TODO new API to only do this on file add
- ..changeFile(path);
- }
-
- @override
- AnalysisDriverGeneric createAnalysisDriver(plugin.ContextRoot contextRoot) {
- final root = new ContextRoot(contextRoot.root, contextRoot.exclude,
- pathContext: resourceProvider.pathContext)
- ..optionsFilePath = contextRoot.optionsFile;
- final options = getOptions(root.optionsFilePath);
-
- final logger = new PerformanceLog(new StringBuffer());
- final builder = new ContextBuilder(resourceProvider, sdkManager, null)
- ..analysisDriverScheduler = (new AnalysisDriverScheduler(logger)..start())
- ..byteStore = byteStore
- ..performanceLog = logger
- ..fileContentOverlay = fileContentOverlay;
-
- final dartDriver = builder.buildDriver(root)
- ..results.listen((_) {}) // Consume the stream, otherwise we leak.
- ..exceptions.listen((_) {}); // Consume the stream, otherwise we leak.
-
- final sourceFactory = dartDriver.sourceFactory;
-
- final driver = new AngularDriver(
- resourceProvider,
- // TODO(mfairhurst) remove NotificationManager & old plugin loader.
- new NoopNotificationManager(),
- dartDriver,
- analysisDriverScheduler,
- byteStore,
- sourceFactory,
- fileContentOverlay,
- options);
-
- driver.dartResultsStream
- .listen((result) => onResult(result, driver, isHtml: false));
- driver.htmlResultsStream
- .listen((result) => onResult(result, driver, isHtml: true));
- return driver;
- }
-
- @override
- List<CompletionContributor> getCompletionContributors(String path) {
- if (angularDriverForPath(path) == null) {
- return [];
- }
-
- return <CompletionContributor>[
- new AngularCompletionContributor(),
- new NgInheritedReferenceContributor(),
- new NgTypeMemberContributor(),
- new NgOffsetLengthContributor(),
- ];
- }
-
- @override
- Future<CompletionRequest> getCompletionRequest(
- plugin.CompletionGetSuggestionsParams parameters) async {
- final path = parameters.file;
- final driver = angularDriverForPath(path);
- final offset = parameters.offset;
-
- if (driver == null) {
- return new DartCompletionRequestImpl(resourceProvider, offset, null);
- }
-
- final templates = await driver.getTemplatesForFile(path);
- final standardHtml = await driver.getStandardHtml();
- assert(standardHtml != null);
- return new AngularCompletionRequest(
- offset, path, resourceProvider, templates, standardHtml);
- }
-
- /// Return a list containing the navigation contributors that should be used to
- /// create navigation information when used in the context of the given
- /// analysis [driver].
- @override
- List<NavigationContributor> getNavigationContributors(String path) =>
- [new AngularNavigation(angularDriverForPath(path).contentOverlay)];
-
- /// Return the navigation request that should be passed to the contributors
- /// returned from [getNavigationContributors].
- @override
- Future<NavigationRequest> getNavigationRequest(
- plugin.AnalysisGetNavigationParams parameters) async {
- final driver = driverForPath(parameters.file) as AngularDriver;
- final isHtml = parameters.file.endsWith('.html');
- final result = isHtml
- ? await driver.requestHtmlResult(parameters.file)
- : await driver.requestDartResult(parameters.file);
- return new AngularNavigationRequest(
- parameters.file, parameters.offset, parameters.length, result);
- }
-
- AngularOptions getOptions(String optionsFilePath) {
- if (optionsFilePath != null && optionsFilePath.isNotEmpty) {
- final file = resourceProvider.getFile(optionsFilePath);
- if (file.exists) {
- return new AngularOptions.from(file.createSource());
- }
- }
- return new AngularOptions.defaults();
- }
-
- /// The method that is called when an error has occurred in the analysis
- /// server. This method will not be invoked under normal conditions.
- @override
- void onError(Object exception, StackTrace stackTrace) {
- print('Communication Exception: $exception\n$stackTrace');
- // ignore: only_throw_errors
- throw exception;
- }
-
- void onResult(DirectivesResult result, AngularDriver driver,
- {@required bool isHtml}) {
- _handleResultErrors(result, driver);
- _handleResultNavigation(result, driver, isHtml: isHtml);
- }
-
- /// This method is used when the set of subscribed notifications has been
- /// changed and notifications need to be sent even when the specified files
- /// have already been analyzed.
- @override
- void sendNotificationsForSubscriptions(
- Map<String, List<plugin.AnalysisService>> subscriptions) {
- subscriptions.forEach((filePath, services) {
- final driver = angularDriverForPath(filePath);
- if (driver == null) {
- return;
- }
-
- // Kick off a full reanalysis of files with subscriptions. This will add
- // a resolved result to the stream which will send the new necessary
- // notifications.
- filePath.endsWith('.dart')
- ? driver.requestDartResult(filePath)
- : driver.requestHtmlResult(filePath);
- });
- }
-
- /// Send notifications for errors for this result
- void _handleResultErrors(DirectivesResult result, AngularDriver driver) {
- final converter = new AnalyzerConverter();
- final lineInfo =
- new LineInfo.fromContent(driver.getFileContent(result.filename));
- // TODO(mfairhurst) Get the right analysis options.
- final errors = converter.convertAnalysisErrors(
- result.errors,
- lineInfo: lineInfo,
- );
- channel.sendNotification(
- new plugin.AnalysisErrorsParams(result.filename, errors)
- .toNotification());
- }
-
- /// Send notifications for navigation for this result
- void _handleResultNavigation(DirectivesResult result, AngularDriver driver,
- {@required bool isHtml}) {
- final collector = new NavigationCollectorImpl();
- final filename = result.filename;
- if (filename == null ||
- !subscriptionManager.hasSubscriptionForFile(
- filename, plugin.AnalysisService.NAVIGATION)) {
- return;
- }
-
- if (result.cacheResult) {
- // get a non-cached result, so we have an AST.
- // TODO(mfairhurst) make this assurance in a less hacky way
- isHtml
- ? driver.requestHtmlResult(filename)
- : driver.requestDartResult(filename);
- return;
- }
-
- new AngularNavigation(driver.contentOverlay)
- ..computeNavigation(
- new AngularNavigationRequest(filename, null, null, result), collector,
- templatesOnly: isHtml);
- collector.createRegions();
- channel.sendNotification(new plugin.AnalysisNavigationParams(
- filename, collector.regions, collector.targets, collector.files)
- .toNotification());
- }
-}
diff --git a/angular_analyzer_plugin/lib/src/angular_driver.dart b/angular_analyzer_plugin/lib/src/angular_driver.dart
deleted file mode 100644
index fa8c44c..0000000
--- a/angular_analyzer_plugin/lib/src/angular_driver.dart
+++ /dev/null
@@ -1,1134 +0,0 @@
-import 'dart:async';
-import 'dart:collection';
-import 'dart:convert';
-
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/analysis/byte_store.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/dart/analysis/file_state.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/api_signature.dart';
-import 'package:analyzer_plugin/utilities/completion/completion_core.dart';
-import 'package:angular_analyzer_plugin/errors.dart';
-import 'package:angular_analyzer_plugin/notification_manager.dart';
-import 'package:angular_analyzer_plugin/src/converter.dart';
-import 'package:angular_analyzer_plugin/src/directive_extraction.dart';
-import 'package:angular_analyzer_plugin/src/directive_linking.dart';
-import 'package:angular_analyzer_plugin/src/file_tracker.dart';
-import 'package:angular_analyzer_plugin/src/from_file_prefixed_error.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/options.dart';
-import 'package:angular_analyzer_plugin/src/pipe_extraction.dart';
-import 'package:angular_analyzer_plugin/src/resolver.dart';
-import 'package:angular_analyzer_plugin/src/standard_components.dart';
-import 'package:angular_analyzer_plugin/src/summary/format.dart';
-import 'package:angular_analyzer_plugin/src/summary/idl.dart';
-import 'package:angular_analyzer_plugin/src/view_extraction.dart';
-import 'package:crypto/crypto.dart';
-
-class AngularDriver
- implements
- AnalysisDriverGeneric,
- FileDirectiveProvider,
- FilePipeProvider,
- DirectiveLinkerEnablement,
- FileHasher {
- final ResourceProvider _resourceProvider;
- // TODO(mfairhurst) remove NotificationManager & old plugin loader.
- final NotificationManager notificationManager;
- final AnalysisDriverScheduler _scheduler;
- final AnalysisDriver dartDriver;
- final FileContentOverlay contentOverlay;
- final AngularOptions options;
- StandardHtml standardHtml;
- StandardAngular standardAngular;
- SourceFactory _sourceFactory;
- final _addedFiles = new LinkedHashSet<String>();
- final _dartFiles = new LinkedHashSet<String>();
- final _changedFiles = new LinkedHashSet<String>();
- final _requestedDartFiles = <String, List<Completer<DirectivesResult>>>{};
- final _requestedHtmlFiles = <String, List<Completer<DirectivesResult>>>{};
- final _filesToAnalyze = new HashSet<String>();
- final _htmlFilesToAnalyze = new HashSet<String>();
- final ByteStore byteStore;
- FileTracker _fileTracker;
- final lastSignatures = <String, String>{};
- bool _hasAngularImported = false;
- bool _hasAngular2Imported = false; // TODO only support package:angular
- final completionContributors = <CompletionContributor>[];
-
- final _dartResultsController = new StreamController<DirectivesResult>();
-
- // ignore: close_sinks
- final _htmlResultsController = new StreamController<DirectivesResult>();
-
- AngularDriver(
- this._resourceProvider,
- this.notificationManager,
- this.dartDriver,
- this._scheduler,
- this.byteStore,
- SourceFactory sourceFactory,
- this.contentOverlay,
- this.options) {
- _sourceFactory = sourceFactory.clone();
- _scheduler.add(this);
- _fileTracker = new FileTracker(this, options);
- // TODO only support package:angular once we all move to that
- _hasAngularImported =
- _sourceFactory.resolveUri(null, "package:angular/angular.dart") != null;
- _hasAngular2Imported =
- _sourceFactory.resolveUri(null, "package:angular2/angular2.dart") !=
- null;
- }
-
- // ignore: close_sinks
- Stream<DirectivesResult> get dartResultsStream =>
- _dartResultsController.stream;
-
- @override
- bool get hasFilesToAnalyze =>
- _filesToAnalyze.isNotEmpty ||
- _htmlFilesToAnalyze.isNotEmpty ||
- _requestedDartFiles.isNotEmpty ||
- _requestedHtmlFiles.isNotEmpty;
-
- Stream<DirectivesResult> get htmlResultsStream =>
- _htmlResultsController.stream;
-
- List<String> get priorityFiles => [];
-
- /// This is implemented in order to satisfy the [AnalysisDriverGeneric]
- /// interface. Ideally, we analyze these files first. For the moment, this lets
- /// the analysis server team add this method to the interface without breaking
- /// any code.
- @override
- set priorityFiles(List<String> priorityPaths) {
- // TODO analyze these files first
- }
-
- @override
- AnalysisDriverPriority get workPriority {
- if (!_hasAngularImported && !_hasAngular2Imported) {
- return AnalysisDriverPriority.nothing;
- }
- if (standardHtml == null) {
- return AnalysisDriverPriority.interactive;
- }
- if (_requestedDartFiles.isNotEmpty) {
- return AnalysisDriverPriority.interactive;
- }
- if (_requestedHtmlFiles.isNotEmpty) {
- return AnalysisDriverPriority.interactive;
- }
- if (_filesToAnalyze.isNotEmpty) {
- return AnalysisDriverPriority.general;
- }
- if (_htmlFilesToAnalyze.isNotEmpty) {
- return AnalysisDriverPriority.general;
- }
- if (_changedFiles.isNotEmpty) {
- return AnalysisDriverPriority.general;
- }
- return AnalysisDriverPriority.nothing;
- }
-
- @override
- void addFile(String path) {
- if (_ownsFile(path)) {
- _addedFiles.add(path);
- if (path.endsWith('.dart')) {
- _dartFiles.add(path);
- }
- fileChanged(path);
- }
- }
-
- AnalysisError deserializeError(Source source, SummarizedAnalysisError error) {
- final errorName = error.errorCode;
- final errorCode = angularWarningCodeByUniqueName(errorName) ??
- errorCodeByUniqueName(errorName);
- if (errorCode == null) {
- return null;
- }
- return new AnalysisError.forValues(source, error.offset, error.length,
- errorCode, error.message, error.correction);
- }
-
- List<AnalysisError> deserializeErrors(
- Source source, List<SummarizedAnalysisError> errors) =>
- errors
- .map((error) => deserializeError(source, error))
- .where((e) => e != null)
- .toList();
-
- List<AnalysisError> deserializeFromPathErrors(
- Source source, List<SummarizedAnalysisErrorFromPath> errors) =>
- errors
- .map((error) {
- final originalError = deserializeError(source, error.originalError);
- if (originalError == null) {
- return null;
- }
- return new FromFilePrefixedError.fromPath(
- error.path, error.classname, originalError);
- })
- .where((e) => e != null)
- .toList();
-
- /// Notify the driver that the client is going to stop using it.
- @override
- void dispose() {
- _dartResultsController.close();
- _htmlResultsController.close();
- }
-
- void fileChanged(String path) {
- if (_ownsFile(path)) {
- _fileTracker.rehashContents(path);
-
- if (path.endsWith('.html')) {
- _htmlFilesToAnalyze.add(path);
- for (final path in _fileTracker.getHtmlPathsReferencingHtml(path)) {
- _htmlFilesToAnalyze.add(path);
- }
- for (final path in _fileTracker.getDartPathsAffectedByHtml(path)) {
- _filesToAnalyze.add(path);
- }
- } else {
- _changedFiles.add(path);
- }
- }
- _scheduler.notify(this);
- }
-
- Future<DirectivesResult> getAngularTopLevels(String path) async {
- final baseKey = _fileTracker.getContentSignature(path).toHex();
- final key = '$baseKey.ngunlinked';
- final bytes = byteStore.get(key);
- if (bytes != null) {
- final summary = new UnlinkedDartSummary.fromBuffer(bytes);
- return new DirectivesResult(
- path,
- await resynthesizeDirectives(summary, path),
- await resynthesizePipes(summary, path),
- deserializeErrors(getSource(path), summary.errors),
- );
- }
-
- final dartResult = await dartDriver.getResult(path);
- if (dartResult == null) {
- return null;
- }
-
- final context = dartResult.unit.declaredElement.context;
- final ast = dartResult.unit;
- final source = dartResult.unit.declaredElement.source;
- final extractor =
- new DirectiveExtractor(ast, context.typeProvider, source, context);
- final topLevels = extractor.getAngularTopLevels();
-
- final directives = new List<AbstractDirective>.from(
- topLevels.where((c) => c is AbstractDirective));
-
- final viewExtractor = new ViewExtractor(
- ast, directives, context, source, await getStandardAngular())
- ..getViews();
-
- final tplErrorListener = new RecordingErrorListener();
- final errorReporter = new ErrorReporter(tplErrorListener, source);
-
- // collect inline ng-content tags
- for (final directive in directives) {
- if (directive is Component && directive?.view != null) {
- final view = directive.view;
- if ((view.templateText ?? "") != "") {
- final template = new Template(view);
- view.template = template;
-
- final tplParser = new TemplateParser()
- ..parse(view.templateText, source, offset: view.templateOffset);
-
- final parser =
- new EmbeddedDartParser(source, tplErrorListener, errorReporter);
-
- template.ast = new HtmlTreeConverter(parser, source, tplErrorListener)
- .convertFromAstList(tplParser.rawAst);
- template.ast.accept(new NgContentRecorder(directive, errorReporter));
- }
- }
- }
-
- // collect Pipes
- final pipeExtractor =
- new PipeExtractor(ast, source, await getStandardAngular());
- final pipes = pipeExtractor.getPipes();
- final errors = new List<AnalysisError>.from(extractor.errorListener.errors)
- ..addAll(viewExtractor.errorListener.errors)
- ..addAll(pipeExtractor.errorListener.errors);
- final result = new DirectivesResult(path, topLevels, pipes, errors);
- final summary = serializeDartResult(result);
- final newBytes = summary.toBuffer();
- byteStore.put(key, newBytes);
- return result;
- }
-
- @override
- ApiSignature getContentHash(String path) {
- final key = new ApiSignature();
- final contentBytes = utf8.encode(getFileContent(path));
- key.addBytes(md5.convert(contentBytes).bytes);
- return key;
- }
-
- Future<OutputElement> getCustomOutputElement(
- CustomEvent event, DartType dynamicType) async {
- OutputElement defaultOutput() => new OutputElement(
- event.name,
- event.nameOffset,
- event.name.length,
- options.source,
- null,
- null,
- dynamicType);
-
- final typePath =
- event.typePath ?? (event.typeName != null ? 'dart:core' : null);
- if (typePath == null) {
- return defaultOutput();
- }
-
- final typeSource = _sourceFactory.resolveUri(null, typePath);
- if (typeSource == null) {
- return defaultOutput();
- }
-
- final typeResult = await dartDriver.getResult(typeSource.fullName);
- if (typeResult == null) {
- return defaultOutput();
- }
-
- final typeElement =
- typeResult.libraryElement.publicNamespace.get(event.typeName);
- if (typeElement is ClassElement) {
- var type = typeElement.type;
- if (type is ParameterizedType) {
- type = type.instantiate(
- type.typeParameters.map((p) => p.bound ?? dynamicType).toList());
- }
- return new OutputElement(event.name, event.nameOffset, event.name.length,
- options.source, null, null, type);
- }
- if (typeElement is TypeDefiningElement) {
- return new OutputElement(event.name, event.nameOffset, event.name.length,
- options.source, null, null, typeElement.type);
- }
-
- return defaultOutput();
- }
-
- String getFileContent(String path) =>
- contentOverlay[path] ??
- ((Source source) => // ignore: avoid_types_on_closure_parameters
- source.exists() ? source.contents.data : "")(getSource(path));
-
- Future<String> getHtmlKey(String htmlPath) async {
- final key = await _fileTracker.getHtmlSignature(htmlPath);
- return '${key.toHex()}.ngresolved';
- }
-
- @override
- Future<List<NgContent>> getHtmlNgContent(String path) async {
- final baseKey = _fileTracker.getContentSignature(path).toHex();
- final key = '$baseKey.ngunlinked';
- final bytes = byteStore.get(key);
- final source = getSource(path);
- if (bytes != null) {
- return new DirectiveLinker(this, standardAngular).deserializeNgContents(
- new UnlinkedHtmlSummary.fromBuffer(bytes).ngContents, source);
- }
-
- final htmlContent = getFileContent(path);
- final tplErrorListener = new RecordingErrorListener();
- final errorReporter = new ErrorReporter(tplErrorListener, source);
-
- final tplParser = new TemplateParser()..parse(htmlContent, source);
-
- final parser =
- new EmbeddedDartParser(source, tplErrorListener, errorReporter);
-
- final ast = new HtmlTreeConverter(parser, source, tplErrorListener)
- .convertFromAstList(tplParser.rawAst);
- final contents = <NgContent>[];
- ast.accept(new NgContentRecorder.forFile(contents, source, errorReporter));
-
- final summary = new UnlinkedHtmlSummaryBuilder()
- ..ngContents = serializeNgContents(contents);
- final newBytes = summary.toBuffer();
- byteStore.put(key, newBytes);
-
- return contents;
- }
-
- @override
- Source getSource(String path) =>
- _resourceProvider.getFile(path).createSource();
-
- Future<StandardAngular> getStandardAngular() async {
- if (standardAngular == null) {
- final source =
- _sourceFactory.resolveUri(null, "package:angular/angular.dart");
-
- if (source == null) {
- return standardAngular;
- }
-
- final securitySource =
- _sourceFactory.resolveUri(null, "package:angular/security.dart");
- final protoSecuritySource = _sourceFactory.resolveUri(
- null, 'package:webutil.html.types.proto/html.pb.dart');
-
- standardAngular = new StandardAngular.fromAnalysis(
- angularResult: await dartDriver.getResult(source.fullName),
- securityResult: await dartDriver.getResult(securitySource.fullName),
- protoSecurityResult: protoSecuritySource == null
- ? null
- : await dartDriver.getResult(protoSecuritySource.fullName));
- }
-
- return standardAngular;
- }
-
- Future<StandardHtml> getStandardHtml() async {
- if (standardHtml == null) {
- final source = _sourceFactory.resolveUri(null, DartSdk.DART_HTML);
-
- final result = await dartDriver.getResult(source.fullName);
- final securitySchema = (await getStandardAngular()).securitySchema;
-
- final components = <String, Component>{};
- final standardEvents = <String, OutputElement>{};
- final customEvents = <String, OutputElement>{};
- final attributes = <String, InputElement>{};
- result.unit.accept(new BuildStandardHtmlComponentsVisitor(
- components, standardEvents, attributes, source, securitySchema));
-
- for (final event in options.customEvents.values) {
- customEvents[event.name] = await getCustomOutputElement(
- event, result.typeProvider.dynamicType);
- }
-
- standardHtml = new StandardHtml(
- components,
- attributes,
- standardEvents,
- customEvents,
- result.libraryElement.exportNamespace.get('Element') as ClassElement,
- result.libraryElement.exportNamespace.get('HtmlElement')
- as ClassElement);
- }
-
- return standardHtml;
- }
-
- Future<List<Template>> getTemplatesForFile(String filePath) async {
- final templates = <Template>[];
- final isDartFile = filePath.endsWith('.dart');
- if (!isDartFile && !filePath.endsWith('.html')) {
- return templates;
- }
-
- final directiveResults = isDartFile
- ? await requestDartResult(filePath)
- : await requestHtmlResult(filePath);
- final directives = directiveResults.directives;
- if (directives == null) {
- return templates;
- }
- for (var directive in directives) {
- if (directive is Component) {
- final view = directive.view;
- final match = isDartFile
- ? view.source.toString() == filePath
- : view.templateUriSource?.fullName == filePath;
- if (match && view.template != null) {
- templates.add(view.template);
- }
- }
- }
- return templates;
- }
-
- @override
- Future<CompilationUnitElement> getUnit(String path) async =>
- (await dartDriver.getUnitElement(path)).element;
-
- @override
- Future<String> getUnitElementSignature(String path) =>
- dartDriver.getUnitElementSignature(path);
-
- @override
- Future<List<AngularTopLevel>> getUnlinkedAngularTopLevels(path) async =>
- (await getAngularTopLevels(path)).angularTopLevels;
-
- @override
- Future<List<Pipe>> getUnlinkedPipes(path) async =>
- (await getAngularTopLevels(path)).pipes;
-
- @override
- Future<Null> performWork() async {
- if (standardAngular == null) {
- await getStandardAngular();
- return;
- }
-
- if (standardHtml == null) {
- await getStandardHtml();
- return;
- }
-
- if (_changedFiles.isNotEmpty) {
- _changedFiles.clear();
- _filesToAnalyze.addAll(_dartFiles);
- return;
- }
-
- if (_requestedDartFiles.isNotEmpty) {
- final path = _requestedDartFiles.keys.first;
- final completers = _requestedDartFiles.remove(path);
- try {
- final result = await _resolveDart(path,
- onlyIfChangedSignature: false, ignoreCache: true);
- completers.forEach((completer) => completer.complete(result));
- } catch (e, st) {
- completers.forEach((completer) => completer.completeError(e, st));
- }
-
- return;
- }
-
- if (_requestedHtmlFiles.isNotEmpty) {
- final path = _requestedHtmlFiles.keys.first;
- final completers = _requestedHtmlFiles.remove(path);
- DirectivesResult result;
-
- try {
- // Try resolving HTML using the existing dart/html relationships which may
- // be already known. However, if we don't see any relationships, try using
- // the .dart equivalent. Better than no result -- the real one WILL come.
- if (_fileTracker.getDartPathsReferencingHtml(path).isEmpty) {
- result =
- await _resolveHtmlFrom(path, path.replaceAll(".html", ".dart"));
- } else {
- result = await _resolveHtml(path, ignoreCache: true);
- }
-
- // After whichever resolution is complete, push errors.
- completers.forEach((completer) => completer.complete(result));
- } catch (e, st) {
- completers.forEach((completer) => completer.completeError(e, st));
- }
-
- return;
- }
-
- if (_filesToAnalyze.isNotEmpty) {
- final path = _filesToAnalyze.first;
- await pushDartErrors(path);
- _filesToAnalyze.remove(path);
- return;
- }
-
- if (_htmlFilesToAnalyze.isNotEmpty) {
- final path = _htmlFilesToAnalyze.first;
- await pushHtmlErrors(path);
- _htmlFilesToAnalyze.remove(path);
- return;
- }
-
- return;
- }
-
- Future pushDartErrors(String path) async {
- final result = await _resolveDart(path);
- if (result == null) {
- return;
- }
- final errors = result.errors;
- final lineInfo = new LineInfo.fromContent(getFileContent(path));
- // TODO(mfairhurst) remove this with old plugin loader
- notificationManager.recordAnalysisErrors(path, lineInfo, errors);
- }
-
- Future pushDartNavigation(String path) async {}
-
- Future pushDartOccurrences(String path) async {}
-
- Future pushHtmlErrors(String htmlPath) async {
- final errors = (await _resolveHtml(htmlPath)).errors;
- final lineInfo = new LineInfo.fromContent(getFileContent(htmlPath));
- // TODO(mfairhurst) remove this with old plugin loader
- notificationManager.recordAnalysisErrors(htmlPath, lineInfo, errors);
- }
-
- @deprecated
- Future<List<AnalysisError>> requestDartErrors(String path) async {
- final result = await requestDartResult(path);
- return result.errors;
- }
-
- /// Get a fully linked (warning: slow) [DirectivesResult] for the components
- /// this Dart path, and their templates (if defined in the component directly
- /// rather than linking to a different html file).
- Future<DirectivesResult> requestDartResult(String path) {
- final completer = new Completer<DirectivesResult>();
- _requestedDartFiles
- .putIfAbsent(path, () => <Completer<DirectivesResult>>[])
- .add(completer);
- _scheduler.notify(this);
- return completer.future;
- }
-
- @deprecated
- Future<List<AnalysisError>> requestHtmlErrors(String path) async {
- final result = await requestDartResult(path);
- return result.errors;
- }
-
- /// Get a fully linked (warning: slow) [DirectivesResult] for the templates in
- /// this HTML path. Note that you may get an empty HTML file if dart analysis
- /// has not finished finding all `templateUrl`s.
- Future<DirectivesResult> requestHtmlResult(String path) {
- final completer = new Completer<DirectivesResult>();
- _requestedHtmlFiles
- .putIfAbsent(path, () => <Completer<DirectivesResult>>[])
- .add(completer);
- _scheduler.notify(this);
- return completer.future;
- }
-
- Future<List<AngularTopLevel>> resynthesizeDirectives(
- UnlinkedDartSummary unlinked, String path) async =>
- new DirectiveLinker(this, standardAngular)
- .resynthesizeDirectives(unlinked, path);
-
- Future<List<Pipe>> resynthesizePipes(
- UnlinkedDartSummary unlinked, String path) async {
- if (unlinked == null) {
- return [];
- }
- final unit = await getUnit(path);
- final pipes = <Pipe>[];
-
- for (final dirSum in unlinked.pipeSummaries) {
- final classElem = unit.getType(dirSum.decoratedClassName);
- pipes.add(new Pipe(dirSum.pipeName, dirSum.pipeNameOffset, classElem,
- isPure: dirSum.isPure));
- }
-
- final pipeExtractor = new PipeExtractor(null, unit.source, null);
- pipes.forEach(pipeExtractor.loadTransformInformation);
- return pipes;
- }
-
- SummarizedClassAnnotationsBuilder serializeAnnotatedClass(
- AngularAnnotatedClass clazz) {
- final className = clazz.classElement.name;
- final inputs = <SummarizedBindableBuilder>[];
- final outputs = <SummarizedBindableBuilder>[];
- final contentChildFields = <SummarizedContentChildFieldBuilder>[];
- final contentChildrenFields = <SummarizedContentChildFieldBuilder>[];
- for (final input in clazz.inputs) {
- final name = input.name;
- final nameOffset = input.nameOffset;
- final propName = input.setter.name.replaceAll('=', '');
- final propNameOffset = input.setterRange.offset;
- inputs.add(new SummarizedBindableBuilder()
- ..name = name
- ..nameOffset = nameOffset
- ..propName = propName
- ..propNameOffset = propNameOffset);
- }
- for (final output in clazz.outputs) {
- final name = output.name;
- final nameOffset = output.nameOffset;
- final propName = output.getter.name.replaceAll('=', '');
- final propNameOffset = output.getterRange.offset;
- outputs.add(new SummarizedBindableBuilder()
- ..name = name
- ..nameOffset = nameOffset
- ..propName = propName
- ..propNameOffset = propNameOffset);
- }
- for (final childField in clazz.contentChildFields) {
- contentChildFields.add(new SummarizedContentChildFieldBuilder()
- ..fieldName = childField.fieldName
- ..nameOffset = childField.nameRange.offset
- ..nameLength = childField.nameRange.length
- ..typeOffset = childField.typeRange.offset
- ..typeLength = childField.typeRange.length);
- }
- for (final childrenField in clazz.contentChildrenFields) {
- contentChildrenFields.add(new SummarizedContentChildFieldBuilder()
- ..fieldName = childrenField.fieldName
- ..nameOffset = childrenField.nameRange.offset
- ..nameLength = childrenField.nameRange.length
- ..typeOffset = childrenField.typeRange.offset
- ..typeLength = childrenField.typeRange.length);
- }
- return new SummarizedClassAnnotationsBuilder()
- ..className = className
- ..inputs = inputs
- ..outputs = outputs
- ..contentChildFields = contentChildFields
- ..contentChildrenFields = contentChildrenFields;
- }
-
- UnlinkedDartSummaryBuilder serializeDartResult(DirectivesResult result) {
- final dirSums = serializeDirectives(result.directives);
- final pipeSums = serializePipes(result.pipes);
- final classSums = result.angularAnnotatedClasses
- .where((c) => c is! AbstractDirective)
- .map(serializeAnnotatedClass)
- .toList();
- final summary = new UnlinkedDartSummaryBuilder()
- ..directiveSummaries = dirSums
- ..pipeSummaries = pipeSums
- ..annotatedClasses = classSums
- ..errors = summarizeErrors(result.errors);
- return summary;
- }
-
- List<SummarizedDirectiveBuilder> serializeDirectives(
- List<AbstractDirective> directives) {
- final dirSums = <SummarizedDirectiveBuilder>[];
- for (final directive in directives) {
- final selector = directive.selector.originalString;
- final selectorOffset = directive.selector.offset;
- final exportAs = directive?.exportAs?.name;
- final exportAsOffset = directive?.exportAs?.nameOffset;
- final exports = <SummarizedExportedIdentifierBuilder>[];
- if (directive is Component) {
- for (final export in directive?.view?.exports ?? <Null>[]) {
- exports.add(new SummarizedExportedIdentifierBuilder()
- ..name = export.identifier
- ..prefix = export.prefix
- ..offset = export.span.offset
- ..length = export.span.length);
- }
- }
- List<SummarizedDirectiveUseBuilder> dirUseSums;
- List<SummarizedPipesUseBuilder> pipeUseSums;
- final ngContents = <SummarizedNgContentBuilder>[];
- String templateUrl;
- int templateUrlOffset;
- int templateUrlLength;
- String templateText;
- int templateTextOffset;
- SourceRange constDirectivesSourceRange;
- if (directive is Component && directive.view != null) {
- templateUrl = directive.view?.templateUriSource?.fullName;
- templateUrlOffset = directive.view?.templateUrlRange?.offset;
- templateUrlLength = directive.view?.templateUrlRange?.length;
- templateText = directive.view.templateText;
- templateTextOffset = directive.view.templateOffset;
-
- dirUseSums = directive.view.directivesStrategy.resolve(
- (references) => references
- .map((reference) => new SummarizedDirectiveUseBuilder()
- ..name = reference.name
- ..prefix = reference.prefix
- ..offset = reference.range.offset
- ..length = reference.range.length)
- .toList(),
- (constValue, _) => null);
-
- pipeUseSums = directive.view.pipeReferences
- .map((pipe) => new SummarizedPipesUseBuilder()
- ..name = pipe.identifier
- ..prefix = pipe.prefix)
- .toList();
-
- constDirectivesSourceRange = directive.view.directivesStrategy.resolve(
- (references) => null, (constValue, sourceRange) => sourceRange);
-
- if (directive.ngContents != null) {
- ngContents.addAll(serializeNgContents(directive.ngContents));
- }
- }
-
- dirSums.add(new SummarizedDirectiveBuilder()
- ..classAnnotations = directive is AbstractClassDirective
- ? serializeAnnotatedClass(directive)
- : null
- ..isComponent = directive is Component
- ..functionName =
- directive is FunctionalDirective ? directive.name : null
- ..selectorStr = selector
- ..selectorOffset = selectorOffset
- ..exportAs = exportAs
- ..exportAsOffset = exportAsOffset
- ..templateText = templateText
- ..templateOffset = templateTextOffset
- ..templateUrl = templateUrl
- ..templateUrlOffset = templateUrlOffset
- ..templateUrlLength = templateUrlLength
- ..ngContents = ngContents
- ..exports = exports
- ..usesArrayOfDirectiveReferencesStrategy = dirUseSums != null
- ..subdirectives = dirUseSums
- ..pipesUse = pipeUseSums
- ..constDirectiveStrategyOffset = constDirectivesSourceRange?.offset
- ..constDirectiveStrategyLength = constDirectivesSourceRange?.length);
- }
-
- return dirSums;
- }
-
- List<SummarizedNgContentBuilder> serializeNgContents(
- List<NgContent> ngContents) =>
- ngContents
- .map((ngContent) => new SummarizedNgContentBuilder()
- ..selectorStr = ngContent.selector?.originalString
- ..selectorOffset = ngContent.selector?.offset
- ..offset = ngContent.offset
- ..length = ngContent.length)
- .toList();
-
- List<SummarizedPipeBuilder> serializePipes(List<Pipe> pipes) {
- final pipeSums = <SummarizedPipeBuilder>[];
- for (final pipe in pipes) {
- pipeSums.add(new SummarizedPipeBuilder(
- pipeName: pipe.pipeName,
- pipeNameOffset: pipe.pipeNameOffset,
- decoratedClassName: pipe.classElement.name,
- isPure: pipe.isPure));
- }
- return pipeSums;
- }
-
- SummarizedAnalysisErrorBuilder summarizeError(AnalysisError error) =>
- new SummarizedAnalysisErrorBuilder(
- offset: error.offset,
- length: error.length,
- errorCode: error.errorCode.uniqueName,
- message: error.message,
- correction: error.correction);
-
- List<SummarizedAnalysisErrorBuilder> summarizeErrors(
- List<AnalysisError> errors) =>
- errors.map(summarizeError).toList();
-
- bool _ownsFile(String path) =>
- path.endsWith('.dart') || path.endsWith('.html');
-
- Future<DirectivesResult> _resolveDart(String path,
- {bool ignoreCache: false, bool onlyIfChangedSignature: true}) async {
- // This happens when the path is..."hidden by a generated file"..whch I
- // don't understand, but, can protect against. Should not be analyzed.
- // TODO detect this on file add rather than on file analyze.
- if (await dartDriver.getUnitElementSignature(path) == null) {
- _dartFiles.remove(path);
- return null;
- }
-
- final baseKey = (await _fileTracker.getUnitElementSignature(path)).toHex();
- final key = '$baseKey.ngresolved';
-
- if (lastSignatures[path] == key && onlyIfChangedSignature) {
- return null;
- }
-
- lastSignatures[path] = key;
-
- if (!ignoreCache) {
- final bytes = byteStore.get(key);
- if (bytes != null) {
- final summary = new LinkedDartSummary.fromBuffer(bytes);
-
- for (final htmlPath in summary.referencedHtmlFiles) {
- _htmlFilesToAnalyze.add(htmlPath);
- }
-
- _fileTracker
- ..setDartHasTemplate(path, summary.hasDartTemplates)
- ..setDartHtmlTemplates(path, summary.referencedHtmlFiles)
- ..setDartImports(path, summary.referencedDartFiles);
-
- final result = new DirectivesResult.fromCache(
- path, deserializeErrors(getSource(path), summary.errors));
- _dartResultsController.add(result);
- return result;
- }
- }
-
- final result = await getAngularTopLevels(path);
- final directives = result.directives;
- final pipes = result.pipes;
- final unit = (await dartDriver.getUnitElement(path)).element;
- if (unit == null) {
- return null;
- }
- final context = unit.context;
- final source = unit.source;
-
- final errors = new List<AnalysisError>.from(result.errors);
- final standardHtml = await getStandardHtml();
-
- final linkErrorListener = new RecordingErrorListener();
- final linkErrorReporter = new ErrorReporter(linkErrorListener, source);
-
- final linker = new ChildDirectiveLinker(this, this,
- await getStandardAngular(), await getStandardHtml(), linkErrorReporter);
- await linker.linkDirectivesAndPipes(directives, pipes, unit.library);
- final attrValidator = new AttributeAnnotationValidator(linkErrorReporter);
- new List<AbstractClassDirective>.from(
- directives.where((d) => d is AbstractClassDirective))
- .forEach(attrValidator.validate);
- errors.addAll(linkErrorListener.errors);
-
- final htmlViews = <String>[];
- final usesDart = <String>[];
- final fullyResolvedDirectives = <AbstractDirective>[];
-
- var hasDartTemplate = false;
- for (final directive in directives) {
- if (directive is Component) {
- final view = directive.view;
- if ((view?.templateText ?? '') != '') {
- hasDartTemplate = true;
- final tplErrorListener = new RecordingErrorListener();
- final errorReporter = new ErrorReporter(tplErrorListener, source);
- final template = new Template(view);
- view.template = template;
-
- final tplParser = new TemplateParser()
- ..parse(view.templateText, source, offset: view.templateOffset);
-
- final document = tplParser.rawAst;
- final parser =
- new EmbeddedDartParser(source, tplErrorListener, errorReporter);
-
- template.ast = new HtmlTreeConverter(parser, source, tplErrorListener)
- .convertFromAstList(tplParser.rawAst);
- template.ast.accept(new NgContentRecorder(directive, errorReporter));
- setIgnoredErrors(template, document);
- new TemplateResolver(
- context.typeProvider,
- context.typeSystem,
- standardHtml.components.values.toList(),
- standardHtml.events,
- standardHtml.attributes,
- await getStandardAngular(),
- await getStandardHtml(),
- tplErrorListener,
- options)
- .resolve(template);
- errors
- ..addAll(tplParser.parseErrors.where(
- (e) => !view.template.ignoredErrors.contains(e.errorCode.name)))
- ..addAll(tplErrorListener.errors.where((e) =>
- !view.template.ignoredErrors.contains(e.errorCode.name)));
- fullyResolvedDirectives.add(directive);
- } else if (view?.templateUriSource != null) {
- _htmlFilesToAnalyze.add(view.templateUriSource.fullName);
- htmlViews.add(view.templateUriSource.fullName);
- }
-
- for (final subDirective in (view?.directives ?? <Null>[])) {
- usesDart.add(subDirective.source.fullName);
- }
- }
- }
-
- _fileTracker
- ..setDartHasTemplate(path, hasDartTemplate)
- ..setDartHtmlTemplates(path, htmlViews)
- ..setDartImports(path, usesDart);
-
- final summary = new LinkedDartSummaryBuilder()
- ..errors = summarizeErrors(errors)
- ..referencedHtmlFiles = htmlViews
- ..referencedDartFiles = usesDart
- ..hasDartTemplates = hasDartTemplate;
- final newBytes = summary.toBuffer();
- byteStore.put(key, newBytes);
- final directivesResult = new DirectivesResult(
- path, directives, pipes, errors,
- fullyResolvedDirectives: fullyResolvedDirectives);
- _dartResultsController.add(directivesResult);
- return directivesResult;
- }
-
- Future<DirectivesResult> _resolveHtml(
- String htmlPath, {
- bool ignoreCache: false,
- }) async {
- final key = await getHtmlKey(htmlPath);
- final bytes = byteStore.get(key);
- final htmlSource = _sourceFactory.forUri('file:$htmlPath');
- if (!ignoreCache && bytes != null) {
- final summary = new LinkedHtmlSummary.fromBuffer(bytes);
- final errors = new List<AnalysisError>.from(
- deserializeErrors(htmlSource, summary.errors))
- ..addAll(deserializeFromPathErrors(htmlSource, summary.errorsFromPath));
- final result = new DirectivesResult.fromCache(htmlPath, errors);
- _htmlResultsController.add(result);
- return result;
- }
-
- final result = new DirectivesResult(htmlPath, [], [], []);
-
- for (final dartContext
- in _fileTracker.getDartPathsReferencingHtml(htmlPath)) {
- final pairResult = await _resolveHtmlFrom(htmlPath, dartContext);
- result.angularTopLevels.addAll(pairResult.angularTopLevels);
- result.errors.addAll(pairResult.errors);
- result.fullyResolvedDirectives.addAll(pairResult.fullyResolvedDirectives);
- }
-
- final summary = new LinkedHtmlSummaryBuilder()
- ..errors = summarizeErrors(result.errors
- .where((error) => error is! FromFilePrefixedError)
- .toList())
- ..errorsFromPath = result.errors
- .where((error) => error is FromFilePrefixedError)
- .map((error) => new SummarizedAnalysisErrorFromPathBuilder()
- ..path = (error as FromFilePrefixedError).fromSourcePath
- ..classname = (error as FromFilePrefixedError).classname
- ..originalError =
- summarizeError((error as FromFilePrefixedError).originalError))
- .toList();
- final newBytes = summary.toBuffer();
- byteStore.put(key, newBytes);
-
- _htmlResultsController.add(result);
- return result;
- }
-
- Future<DirectivesResult> _resolveHtmlFrom(
- String htmlPath, String dartPath) async {
- final result = await getAngularTopLevels(dartPath);
- final directives = result.directives;
- final pipes = result.pipes;
- final unit = (await dartDriver.getUnitElement(dartPath)).element;
- final htmlSource = _sourceFactory.forUri('file:$htmlPath');
-
- if (unit == null) {
- return null;
- }
- final context = unit.context;
- final dartSource = _sourceFactory.forUri('file:$dartPath');
- final htmlContent = getFileContent(htmlPath);
- final standardHtml = await getStandardHtml();
-
- final errors = <AnalysisError>[];
- // ignore link errors, they are exposed when resolving dart
- final linkErrorListener = new IgnoringErrorListener();
- final linkErrorReporter = new ErrorReporter(linkErrorListener, dartSource);
-
- final linker = new ChildDirectiveLinker(this, this,
- await getStandardAngular(), await getStandardHtml(), linkErrorReporter);
- await linker.linkDirectivesAndPipes(directives, pipes, unit.library);
- final attrValidator = new AttributeAnnotationValidator(linkErrorReporter);
-
- new List<AbstractClassDirective>.from(
- directives.where((d) => d is AbstractClassDirective))
- .forEach(attrValidator.validate);
-
- final fullyResolvedDirectives = <AbstractDirective>[];
-
- for (final directive in directives) {
- if (directive is Component) {
- final view = directive.view;
- if (view.templateUriSource?.fullName == htmlPath) {
- final tplErrorListener = new RecordingErrorListener();
- final errorReporter = new ErrorReporter(tplErrorListener, dartSource);
- final template = new Template(view);
- view.template = template;
-
- final tplParser = new TemplateParser()
- ..parse(htmlContent, htmlSource);
-
- final document = tplParser.rawAst;
- final parser = new EmbeddedDartParser(
- htmlSource, tplErrorListener, errorReporter);
-
- template.ast =
- new HtmlTreeConverter(parser, htmlSource, tplErrorListener)
- .convertFromAstList(tplParser.rawAst);
- template.ast.accept(new NgContentRecorder(directive, errorReporter));
- setIgnoredErrors(template, document);
- new TemplateResolver(
- context.typeProvider,
- context.typeSystem,
- standardHtml.components.values.toList(),
- standardHtml.events,
- standardHtml.attributes,
- await getStandardAngular(),
- await getStandardHtml(),
- tplErrorListener,
- options)
- .resolve(template);
-
- bool rightErrorType(AnalysisError e) =>
- !view.template.ignoredErrors.contains(e.errorCode.name);
- String shorten(String filename) {
- final index = filename.lastIndexOf('.');
- return index == -1 ? filename : filename.substring(0, index);
- }
-
- errors.addAll(tplParser.parseErrors.where(rightErrorType));
-
- if (shorten(view.source.fullName) !=
- shorten(view.templateSource.fullName)) {
- errors.addAll(tplErrorListener.errors.where(rightErrorType).map(
- (e) => new FromFilePrefixedError(
- view.source, directive.classElement.name, e)));
- } else {
- errors.addAll(tplErrorListener.errors.where(rightErrorType));
- }
-
- fullyResolvedDirectives.add(directive);
- }
- }
- }
-
- return new DirectivesResult(htmlPath, directives, pipes, errors,
- fullyResolvedDirectives: fullyResolvedDirectives);
- }
-}
-
-class DirectivesResult {
- final String filename;
- final List<AngularTopLevel> angularTopLevels;
- final List<AbstractDirective> fullyResolvedDirectives = [];
- List<AnalysisError> errors;
- List<Pipe> pipes;
- bool cacheResult;
- DirectivesResult(
- this.filename, this.angularTopLevels, this.pipes, this.errors,
- {List<AbstractDirective> fullyResolvedDirectives: const []})
- : cacheResult = false {
- // Use `addAll` instead of initializing it to `const []` when not specified,
- // so that the result is not const and we can add to it, while still being
- // final.
- this.fullyResolvedDirectives.addAll(fullyResolvedDirectives);
- }
-
- DirectivesResult.fromCache(this.filename, this.errors)
- : angularTopLevels = const [],
- cacheResult = true;
- List<AngularAnnotatedClass> get angularAnnotatedClasses =>
- new List<AngularAnnotatedClass>.from(
- angularTopLevels.where((c) => c is AngularAnnotatedClass));
-
- List<AbstractDirective> get directives => new List<AbstractDirective>.from(
- angularTopLevels.where((c) => c is AbstractDirective));
-}
diff --git a/angular_analyzer_plugin/lib/src/completion.dart b/angular_analyzer_plugin/lib/src/completion.dart
deleted file mode 100644
index 8b8c3f7..0000000
--- a/angular_analyzer_plugin/lib/src/completion.dart
+++ /dev/null
@@ -1,1229 +0,0 @@
-import 'dart:async';
-import 'dart:collection';
-
-import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart'
- show PropertyAccessorElement, FunctionElement, ClassElement, LibraryElement;
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/type_system.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart'
- hide AnalysisError;
-import 'package:analyzer_plugin/src/utilities/completion/completion_core.dart';
-import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
-import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
-import 'package:analyzer_plugin/utilities/completion/completion_core.dart';
-import 'package:analyzer_plugin/utilities/completion/inherited_reference_contributor.dart';
-import 'package:analyzer_plugin/utilities/completion/relevance.dart';
-import 'package:analyzer_plugin/utilities/completion/type_member_contributor.dart';
-import 'package:angular_analyzer_plugin/ast.dart';
-import 'package:angular_analyzer_plugin/src/completion_request.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-
-bool offsetContained(int offset, int start, int length) =>
- start <= offset && start + length >= offset;
-
-/// Contributor to contribute angular entities.
-class AngularCompletionContributor extends CompletionContributor {
- /// Initialize a newly created handler to handle requests for the given
- /// [server].
- AngularCompletionContributor();
-
- /// Return a [Future] that completes with a list of suggestions
- /// for the given completion [request].
- @override
- Future<Null> computeSuggestions(
- AngularCompletionRequest request, CompletionCollector collector) async {
- final templates = request.templates;
- final standardHtml = request.standardHtml;
- final events = standardHtml.events.values.toList();
- final attributes = standardHtml.uniqueAttributeElements;
-
- final templateCompleter = new TemplateCompleter();
- for (final template in templates) {
- await templateCompleter.computeSuggestions(
- request,
- collector,
- template,
- events,
- attributes,
- );
- }
- }
-}
-
-class LocalVariablesExtractor implements AngularAstVisitor {
- Map<String, LocalVariable> variables;
-
- // don't recurse
- @override
- void visitDocumentInfo(DocumentInfo document) {}
-
- @override
- void visitElementInfo(ElementInfo element) {}
-
- @override
- void visitEmptyStarBinding(EmptyStarBinding binding) {}
-
- @override
- void visitExpressionBoundAttr(ExpressionBoundAttribute attr) {
- variables = attr.localVariables;
- }
-
- @override
- void visitMustache(Mustache mustache) {
- variables = mustache.localVariables;
- }
-
- @override
- void visitStatementsBoundAttr(StatementsBoundAttribute attr) {
- variables = attr.localVariables;
- }
-
- @override
- void visitTemplateAttr(TemplateAttribute attr) {
- variables = attr.localVariables;
- }
-
- @override
- void visitTextAttr(TextAttribute attr) {}
-
- @override
- void visitTextInfo(TextInfo text) {}
-}
-
-/// Extension of [InheritedReferenceContributor] to allow for Dart-based
-/// completion within Angular context. Triggered in [StatementsBoundAttribute],
-/// [ExpressionsBoundAttribute], [Mustache], and [TemplateAttribute]
-/// on identifier completion.
-class NgInheritedReferenceContributor extends CompletionContributor {
- final InheritedReferenceContributor _inheritedReferenceContributor =
- new InheritedReferenceContributor();
-
- void addExportedPrefixSuggestions(CompletionCollector collector, View view) {
- if (view.exports == null) {
- return;
- }
-
- view.exports
- .map((export) => export.prefix)
- .where((prefix) => prefix != '')
- .toSet()
- .map((prefix) => _addExportedPrefixSuggestion(
- prefix, _getPrefixedImport(view.classElement.library, prefix)))
- .forEach(collector.addSuggestion);
- }
-
- void addExportSuggestions(
- CompletionCollector collector, View view, OpType optype,
- {String prefix}) {
- if (prefix == null) {
- collector.addSuggestion(_addExportedClassSuggestion(
- new ExportedIdentifier(view.classElement.name, null,
- element: view.classElement),
- view.classElement.type,
- ElementKind.CLASS,
- optype,
- relevance: DART_RELEVANCE_DEFAULT));
- }
-
- final exports = view.exports;
- if (exports == null) {
- return;
- }
-
- for (final export in exports) {
- if (prefix != null && export.prefix != prefix) {
- continue;
- }
-
- final element = export.element;
- if (element is PropertyAccessorElement) {
- collector.addSuggestion(_addExportedGetterSuggestion(
- export, element.variable.type, ElementKind.GETTER, optype,
- relevance: DART_RELEVANCE_DEFAULT, withPrefix: prefix == null));
- }
- if (element is FunctionElement) {
- collector.addSuggestion(_addExportedFunctionSuggestion(
- export, element.returnType, ElementKind.FUNCTION, optype,
- relevance: DART_RELEVANCE_DEFAULT, withPrefix: prefix == null));
- }
- if (element is ClassElement) {
- collector.addSuggestion(_addExportedClassSuggestion(
- export,
- element.type,
- element.isEnum ? ElementKind.ENUM : ElementKind.CLASS,
- optype,
- relevance: DART_RELEVANCE_DEFAULT,
- withPrefix: prefix == null));
- }
- }
- }
-
- void addLocalVariables(CompletionCollector collector,
- Map<String, LocalVariable> localVars, OpType optype) {
- for (final eachVar in localVars.values) {
- collector.addSuggestion(_addLocalVariableSuggestion(eachVar,
- eachVar.dartVariable.type, ElementKind.LOCAL_VARIABLE, optype,
- relevance: DART_RELEVANCE_LOCAL_VARIABLE));
- }
- }
-
- @override
- Future<Null> computeSuggestions(
- AngularCompletionRequest request, CompletionCollector collector) async {
- final templates = request.templates;
-
- for (final template in templates) {
- final context = template.view.component.classElement.enclosingElement
- .enclosingElement.context;
- final typeProvider = context.typeProvider;
- final typeSystem = context.typeSystem;
- final dartSnippet = request.dartSnippet;
-
- if (dartSnippet != null) {
- final angularTarget = request.angularTarget;
- final completionTarget = request.completionTarget;
-
- final optype =
- defineOpType(completionTarget, request.offset, dartSnippet);
- final classElement = template.view.classElement;
- final libraryElement = classElement.library;
-
- final dartResolveResult = new _ResolveResultShell(request.path,
- libraryElement: libraryElement,
- typeProvider: typeProvider,
- typeSystem: typeSystem);
- final dartRequest = new DartCompletionRequestImpl(
- request.resourceProvider, request.offset, dartResolveResult);
- await _inheritedReferenceContributor.computeSuggestionsForClass(
- dartRequest, collector, classElement,
- entryPoint: dartSnippet,
- target: completionTarget,
- optype: optype,
- skipChildClass: false);
-
- if (optype.includeIdentifiers) {
- final varExtractor = new LocalVariablesExtractor();
- angularTarget.accept(varExtractor);
- if (varExtractor.variables != null) {
- addLocalVariables(
- collector,
- varExtractor.variables,
- optype,
- );
- }
-
- addExportedPrefixSuggestions(collector, template.view);
- }
-
- {
- final entity = completionTarget.entity;
- final containingNode = completionTarget.containingNode;
- if (entity is SimpleIdentifier &&
- containingNode is PrefixedIdentifier &&
- entity == containingNode?.identifier) {
- addExportSuggestions(collector, template.view, optype,
- prefix: containingNode.prefix.name);
- } else {
- addExportSuggestions(collector, template.view, optype);
- }
- }
- }
- }
- }
-
- OpType defineOpType(CompletionTarget target, int offset, AstNode entryPoint) {
- final optype = new OpType.forCompletion(target, offset);
-
- // if the containing node IS the AST, it means the context decides what's
- // completable. In that case, that's in our court only.
- if (target.containingNode == entryPoint) {
- optype
- ..includeReturnValueSuggestions = true
- ..includeTypeNameSuggestions = true
- // expressions always have nonvoid returns
- ..includeVoidReturnSuggestions = !(entryPoint is Expression);
- }
-
- // NG Expressions (not statements) always must return something. We have to
- // force that ourselves here.
- if (entryPoint is Expression) {
- optype.includeVoidReturnSuggestions = false;
- }
- return optype;
- }
-
- CompletionSuggestion _addExportedClassSuggestion(ExportedIdentifier export,
- DartType typeName, ElementKind elemKind, OpType optype,
- {int relevance: DART_RELEVANCE_DEFAULT, bool withPrefix: true}) =>
- _createExportSuggestion(
- export, relevance, typeName, _createExportElement(export, elemKind),
- withPrefix: withPrefix);
-
- CompletionSuggestion _addExportedFunctionSuggestion(ExportedIdentifier export,
- DartType typeName, ElementKind elemKind, OpType optype,
- {int relevance: DART_RELEVANCE_DEFAULT, bool withPrefix: true}) {
- final element = export.element as FunctionElement;
- // ignore: parameter_assignments
- relevance = optype.returnValueSuggestionsFilter(element.type, relevance) ??
- DART_RELEVANCE_DEFAULT;
- return _createExportSuggestion(
- export,
- relevance,
- typeName,
- _createExportFunctionElement(element, elemKind, typeName)
- ..returnType = typeName.toString(),
- withPrefix: withPrefix)
- ..returnType = element.returnType.toString()
- ..parameterNames = element.parameters.map((param) => param.name).toList()
- ..parameterTypes =
- element.parameters.map((param) => param.type.toString()).toList()
- ..requiredParameterCount =
- element.parameters.where((param) => param.hasRequired).length
- ..hasNamedParameters =
- element.parameters.any((param) => param.name != null);
- }
-
- CompletionSuggestion _addExportedGetterSuggestion(ExportedIdentifier export,
- DartType typeName, ElementKind elemKind, OpType optype,
- {int relevance: DART_RELEVANCE_DEFAULT, bool withPrefix: true}) {
- final element = export.element as PropertyAccessorElement;
- // ignore: parameter_assignments
- relevance =
- optype.returnValueSuggestionsFilter(element.variable.type, relevance) ??
- DART_RELEVANCE_DEFAULT;
- return _createExportSuggestion(
- export,
- relevance,
- typeName,
- _createExportElement(export, elemKind)
- ..returnType = typeName.toString(),
- withPrefix: withPrefix)
- ..returnType = element.returnType.toString();
- }
-
- CompletionSuggestion _addExportedPrefixSuggestion(
- String prefix, LibraryElement library) =>
- _createExportedPrefixSuggestion(prefix, DART_RELEVANCE_DEFAULT,
- _createExportedPrefixElement(prefix, library));
-
- CompletionSuggestion _addLocalVariableSuggestion(LocalVariable variable,
- DartType typeName, ElementKind elemKind, OpType optype,
- {int relevance: DART_RELEVANCE_DEFAULT}) {
- // ignore: parameter_assignments
- relevance = optype.returnValueSuggestionsFilter(
- variable.dartVariable.type, relevance) ??
- DART_RELEVANCE_DEFAULT;
- return _createLocalSuggestion(variable, relevance, typeName,
- _createLocalElement(variable, elemKind, typeName));
- }
-
- Element _createExportedPrefixElement(String prefix, LibraryElement library) {
- final flags = Element.makeFlags();
- final location = new Location(
- library.source.fullName, library.nameOffset, library.nameLength, 0, 0);
- return new Element(ElementKind.LIBRARY, prefix, flags, location: location);
- }
-
- CompletionSuggestion _createExportedPrefixSuggestion(
- String prefix, int defaultRelevance, Element element) =>
- new CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER,
- defaultRelevance, prefix, prefix.length, 0, false, false,
- element: element);
-
- Element _createExportElement(ExportedIdentifier export, ElementKind kind) {
- final name = export.identifier;
- final location = new Location(export.element.source.fullName,
- export.element.nameOffset, export.element.nameLength, 0, 0);
- final flags = Element.makeFlags();
- return new Element(kind, name, flags, location: location);
- }
-
- Element _createExportFunctionElement(
- FunctionElement element, ElementKind kind, DartType type) {
- final name = element.name;
- final parameterString = element.parameters.join(', ');
- final location = new Location(
- element.source.fullName, element.nameOffset, element.nameLength, 0, 0);
- final flags = Element.makeFlags();
- return new Element(kind, name, flags,
- location: location,
- returnType: type.toString(),
- parameters: '($parameterString)');
- }
-
- CompletionSuggestion _createExportSuggestion(ExportedIdentifier export,
- int defaultRelevance, DartType type, Element element,
- {bool withPrefix: true}) {
- final completion = export.prefix.isEmpty || !withPrefix
- ? export.identifier
- : '${export.prefix}.${export.identifier}';
- return new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
- defaultRelevance, completion, completion.length, 0, false, false,
- element: element);
- }
-
- Element _createLocalElement(
- LocalVariable localVar, ElementKind kind, DartType type) {
- final name = localVar.name;
- final location = new Location(localVar.source.fullName, localVar.nameOffset,
- localVar.nameLength, 0, 0);
- final flags = Element.makeFlags();
- return new Element(kind, name, flags,
- location: location, returnType: type.toString());
- }
-
- CompletionSuggestion _createLocalSuggestion(LocalVariable localVar,
- int defaultRelevance, DartType type, Element element) {
- final completion = localVar.name;
- return new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
- defaultRelevance, completion, completion.length, 0, false, false,
- returnType: type.toString(), element: element);
- }
-
- LibraryElement _getPrefixedImport(LibraryElement library, String prefix) =>
- library.imports
- .where((import) => import.prefix != null)
- .where((import) => import.prefix.name == prefix)
- .first
- .library;
-}
-
-class NgOffsetLengthContributor extends CompletionContributor {
- @override
- Future<Null> computeSuggestions(
- AngularCompletionRequest request, CompletionCollector collector) async {
- final replacementRangeCalculator = new ReplacementRangeCalculator(request);
- final dartSnippet = request.dartSnippet;
- request.angularTarget?.accept(replacementRangeCalculator);
- if (dartSnippet != null) {
- final range =
- request.completionTarget.computeReplacementRange(request.offset);
- collector
- ..offset = range.offset
- ..length = range.length;
- } else if (request.angularTarget != null) {
- collector
- ..offset = replacementRangeCalculator.offset
- ..length = replacementRangeCalculator.length;
- }
- }
-}
-
-/// Extension of [TypeMemberContributor] to allow for Dart-based
-/// completion within Angular context. Triggered in [StatementsBoundAttribute],
-/// [ExpressionsBoundAttribute], [Mustache], and [TemplateAttribute]
-/// on member variable completion.
-class NgTypeMemberContributor extends CompletionContributor {
- final TypeMemberContributor _typeMemberContributor =
- new TypeMemberContributor();
-
- @override
- Future<Null> computeSuggestions(
- AngularCompletionRequest request, CompletionCollector collector) async {
- final templates = request.templates;
-
- for (final template in templates) {
- final typeProvider = template.view.component.classElement.enclosingElement
- .enclosingElement.context.typeProvider;
- final dartSnippet = request.dartSnippet;
-
- if (dartSnippet != null) {
- final classElement = template.view.classElement;
- final libraryElement = classElement.library;
-
- final dartResolveResult = new _ResolveResultShell(request.path,
- libraryElement: libraryElement, typeProvider: typeProvider);
- final dartRequest = new DartCompletionRequestImpl(
- request.resourceProvider, request.offset, dartResolveResult);
- await _typeMemberContributor.computeSuggestionsWithEntryPoint(
- dartRequest, collector, dartSnippet);
- }
- }
- }
-}
-
-class ReplacementRangeCalculator implements AngularAstVisitor {
- int offset; // replacementOffset. Initially requestOffset.
- int length = 0; // replacementLength
-
- ReplacementRangeCalculator(CompletionRequest request) {
- offset = request.offset;
- }
-
- @override
- void visitDocumentInfo(DocumentInfo document) {}
-
- @override
- void visitElementInfo(ElementInfo element) {
- if (element.openingSpan == null) {
- return;
- }
- final nameSpanEnd =
- element.openingNameSpan.offset + element.openingNameSpan.length;
- if (offsetContained(offset, element.openingSpan.offset,
- nameSpanEnd - element.openingSpan.offset)) {
- offset = element.openingSpan.offset;
- length = element.localName.length + 1;
- }
- }
-
- @override
- void visitEmptyStarBinding(EmptyStarBinding binding) =>
- visitTextAttr(binding);
-
- @override
- void visitExpressionBoundAttr(ExpressionBoundAttribute attr) {
- if (offsetContained(
- offset, attr.originalNameOffset, attr.originalName.length)) {
- offset = attr.originalNameOffset;
- length = attr.originalName.length;
- }
- }
-
- @override
- void visitMustache(Mustache mustache) {}
-
- @override
- void visitStatementsBoundAttr(StatementsBoundAttribute attr) {
- if (offsetContained(
- offset, attr.originalNameOffset, attr.originalName.length)) {
- offset = attr.originalNameOffset;
- length = attr.originalName.length;
- }
- }
-
- @override
- void visitTemplateAttr(TemplateAttribute attr) {
- if (offsetContained(
- offset, attr.originalNameOffset, attr.originalName.length)) {
- offset = attr.originalNameOffset;
- length = attr.originalName.length;
- }
- }
-
- @override
- void visitTextAttr(TextAttribute attr) {
- if (attr.parent is TemplateAttribute && attr.name.startsWith('let-')) {
- return;
- }
- final inValueScope = attr.isReference &&
- attr.value != null &&
- offsetContained(offset, attr.valueOffset, attr.valueLength);
- offset = inValueScope ? attr.valueOffset : attr.offset;
- length = inValueScope ? attr.valueLength : attr.length;
- }
-
- @override
- void visitTextInfo(TextInfo textInfo) {
- if (offset > textInfo.offset &&
- textInfo.text[offset - textInfo.offset - 1] == '<') {
- offset--;
- length = 1;
- }
- }
-}
-
-class TemplateCompleter {
- static const int RELEVANCE_TRANSCLUSION = DART_RELEVANCE_DEFAULT + 10;
-
- Future<Null> computeSuggestions(
- AngularCompletionRequest request,
- CompletionCollector collector,
- Template template,
- List<OutputElement> standardHtmlEvents,
- Set<InputElement> standardHtmlAttributes,
- ) async {
- final typeProvider = template.view.component.classElement.enclosingElement
- .enclosingElement.context.typeProvider;
- final dartSnippet = request.dartSnippet;
- final target = request.angularTarget;
-
- if (dartSnippet != null) {
- return;
- }
-
- if (target is ElementInfo) {
- if (target.closingSpan != null &&
- offsetContained(request.offset, target.closingSpan.offset,
- target.closingSpan.length)) {
- if (request.offset ==
- (target.closingSpan.offset + target.closingSpan.length)) {
- // In closing tag, but could be directly after it; ex: '</div>^'.
- suggestHtmlTags(template, collector);
- if (target.parent != null && target.parent is! DocumentInfo) {
- suggestTransclusions(target.parent, collector);
- }
- }
- } else if (!offsetContained(request.offset, target.openingNameSpan.offset,
- target.openingNameSpan.length)) {
- // If request is not in [openingNameSpan], suggest decorators.
- suggestInputs(
- target.boundDirectives,
- collector,
- standardHtmlAttributes,
- target.boundStandardInputs,
- typeProvider,
- includePlainAttributes: true,
- );
- suggestOutputs(
- target.boundDirectives,
- collector,
- standardHtmlEvents,
- target.boundStandardOutputs,
- );
- suggestBananas(
- target.boundDirectives,
- collector,
- target.boundStandardInputs,
- target.boundStandardOutputs,
- );
- suggestFromAvailableDirectives(
- target.availableDirectives,
- collector,
- suggestPlainAttributes: true,
- suggestInputs: true,
- suggestBananas: true,
- );
- if (!target.isOrHasTemplateAttribute) {
- suggestStarAttrs(template, collector);
- }
- } else {
- // Otherwise, suggest HTML tags and transclusions.
- suggestHtmlTags(template, collector);
- if (target.parent != null || target.parent is! DocumentInfo) {
- suggestTransclusions(target.parent, collector);
- }
- }
- } else if (target is AttributeInfo && target.parent is TemplateAttribute) {
- final templateAttr = target.parent as TemplateAttribute;
- // `let foo`. Nothing to suggest.
- if (target is TextAttribute && target.name.startsWith("let-")) {
- return;
- }
-
- if (offsetContained(request.offset, target.originalNameOffset,
- target.originalName.length)) {
- suggestInputsInTemplate(templateAttr, collector, currentAttr: target);
- } else {
- suggestInputsInTemplate(templateAttr, collector);
- }
- } else if (target is ExpressionBoundAttribute &&
- offsetContained(request.offset, target.originalNameOffset,
- target.originalName.length)) {
- final _suggestInputs = target.bound == ExpressionBoundType.input;
- var _suggestBananas = target.bound == ExpressionBoundType.twoWay;
-
- if (_suggestInputs) {
- _suggestBananas = target.nameOffset == request.offset;
- suggestInputs(
- target.parent.boundDirectives,
- collector,
- standardHtmlAttributes,
- target.parent.boundStandardInputs,
- typeProvider,
- currentAttr: target);
- }
- if (_suggestBananas) {
- suggestBananas(
- target.parent.boundDirectives,
- collector,
- target.parent.boundStandardInputs,
- target.parent.boundStandardOutputs,
- currentAttr: target,
- );
- }
- suggestFromAvailableDirectives(
- target.parent.availableDirectives,
- collector,
- suggestBananas: _suggestBananas,
- suggestInputs: _suggestInputs,
- );
- } else if (target is StatementsBoundAttribute) {
- suggestOutputs(target.parent.boundDirectives, collector,
- standardHtmlEvents, target.parent.boundStandardOutputs,
- currentAttr: target);
- } else if (target is TemplateAttribute) {
- if (offsetContained(request.offset, target.originalNameOffset,
- target.originalName.length)) {
- suggestStarAttrs(template, collector);
- }
- suggestInputsInTemplate(target, collector);
- } else if (target is TextAttribute && target.nameOffset != null) {
- if (offsetContained(
- request.offset, target.nameOffset, target.name.length)) {
- suggestInputs(
- target.parent.boundDirectives,
- collector,
- standardHtmlAttributes,
- target.parent.boundStandardInputs,
- typeProvider,
- includePlainAttributes: true);
- suggestOutputs(target.parent.boundDirectives, collector,
- standardHtmlEvents, target.parent.boundStandardOutputs);
- suggestBananas(
- target.parent.boundDirectives,
- collector,
- target.parent.boundStandardInputs,
- target.parent.boundStandardOutputs,
- );
- suggestFromAvailableDirectives(
- target.parent.availableDirectives,
- collector,
- suggestPlainAttributes: true,
- suggestInputs: true,
- suggestBananas: true,
- );
- } else if (target.value != null &&
- target.isReference &&
- offsetContained(
- request.offset, target.valueOffset, target.value.length)) {
- suggestRefValues(target.parent.boundDirectives, collector);
- }
- } else if (target is TextInfo) {
- suggestHtmlTags(template, collector);
- suggestTransclusions(target.parent, collector);
- }
- }
-
- void suggestBananas(
- List<DirectiveBinding> directives,
- CompletionCollector collector,
- List<InputBinding> boundStandardAttributes,
- List<OutputBinding> boundStandardOutputs,
- {BoundAttributeInfo currentAttr}) {
- // Handle potential two-way found in bound directives
- // There are no standard event/attribute that fall under two-way binding.
- for (final directive in directives) {
- final usedInputs = new HashSet.from(directive.inputBindings
- .where((b) => b.attribute != currentAttr)
- .map((b) => b.boundInput)).toSet();
- final usedOutputs = new HashSet.from(directive.outputBindings
- .where((b) => b.attribute != currentAttr)
- .map((b) => b.boundOutput)).toSet();
-
- final availableInputs =
- new HashSet<InputElement>.from(directive.boundDirective.inputs)
- .difference(usedInputs);
- final availableOutputs =
- new HashSet<OutputElement>.from(directive.boundDirective.outputs)
- .difference(usedOutputs);
- for (final input in availableInputs) {
- final inputName = input.name;
- final complementName = '${inputName}Change';
- final output = availableOutputs
- .firstWhere((o) => o.name == complementName, orElse: () => null);
- if (output != null) {
- collector.addSuggestion(_createBananaSuggestion(
- input,
- DART_RELEVANCE_DEFAULT,
- _createBananaElement(input, ElementKind.SETTER)));
- }
- }
- }
- }
-
- /// Goes through all the available, but not yet-bound directives
- /// and extracts non-violating plain-text attribute-directives
- /// and inputs (if name overlaps with attribute-directive).
- void suggestFromAvailableDirectives(
- Map<AbstractDirective, List<AngularElement>> availableDirectives,
- CompletionCollector collector, {
- bool suggestInputs: false,
- bool suggestBananas: false,
- bool suggestPlainAttributes: false,
- }) {
- availableDirectives.forEach((directive, selectors) {
- final attributeSelectors = <String, AngularElement>{};
- final validInputs = <InputElement>[];
-
- for (final attribute in selectors) {
- attributeSelectors[attribute.name] = attribute;
- }
-
- for (final input in directive.inputs) {
- if (attributeSelectors.keys.contains(input.name)) {
- attributeSelectors.remove(input.name);
- validInputs.add(input);
- }
- }
-
- for (final input in validInputs) {
- final outputComplement = '${input.name}Change';
- final output = directive.outputs.firstWhere(
- (output) => output.name == outputComplement,
- orElse: () => null);
- if (output != null && suggestBananas) {
- collector.addSuggestion(_createBananaSuggestion(
- input,
- DART_RELEVANCE_DEFAULT,
- _createBananaElement(input, ElementKind.SETTER)));
- }
- if (suggestInputs) {
- collector.addSuggestion(_createInputSuggestion(
- input,
- DART_RELEVANCE_DEFAULT,
- _createInputElement(input, ElementKind.SETTER)));
- }
- }
-
- if (suggestPlainAttributes) {
- attributeSelectors.forEach((name, selector) {
- final nameOffset = selector.nameOffset;
- final locationSource = selector.source.fullName;
- collector.addSuggestion(_createPlainAttributeSuggestions(
- name,
- DART_RELEVANCE_DEFAULT,
- _createPlainAttributeElement(
- name, nameOffset, locationSource, ElementKind.SETTER)));
- });
- }
- });
- }
-
- void suggestHtmlTags(Template template, CompletionCollector collector) {
- final elementTagMap = template.view.elementTagsInfo;
- for (final elementTagName in elementTagMap.keys) {
- final currentSuggestion = _createHtmlTagSuggestion(
- '<$elementTagName',
- DART_RELEVANCE_DEFAULT,
- _createHtmlTagElement(
- elementTagName,
- elementTagMap[elementTagName].first,
- ElementKind.CLASS_TYPE_ALIAS));
- if (currentSuggestion != null) {
- collector.addSuggestion(currentSuggestion);
- }
- }
- }
-
- void suggestInputs(
- List<DirectiveBinding> directives,
- CompletionCollector collector,
- Set<InputElement> standardHtmlAttributes,
- List<InputBinding> boundStandardAttributes,
- TypeProvider typeProvider, {
- ExpressionBoundAttribute currentAttr,
- bool includePlainAttributes: false,
- }) {
- for (final directive in directives) {
- final usedInputs = new HashSet.from(directive.inputBindings
- .where((b) => b.attribute != currentAttr)
- .map((b) => b.boundInput)).toSet();
-
- for (final input in directive.boundDirective.inputs) {
- // don't recommend [name] [name] [name]
- if (usedInputs.contains(input)) {
- continue;
- }
-
- if (includePlainAttributes && typeProvider != null) {
- if (typeProvider.stringType.isAssignableTo(input.setterType)) {
- final relevance = input.setterType.displayName == 'String'
- ? DART_RELEVANCE_DEFAULT
- : DART_RELEVANCE_DEFAULT - 1;
- collector.addSuggestion(_createPlainAttributeSuggestions(
- input.name,
- relevance,
- _createPlainAttributeElement(
- input.name,
- input.nameOffset,
- input.source.fullName,
- ElementKind.SETTER,
- )));
- }
- }
- collector.addSuggestion(_createInputSuggestion(
- input,
- DART_RELEVANCE_DEFAULT,
- _createInputElement(input, ElementKind.SETTER)));
- }
- }
-
- final usedStdInputs = new HashSet.from(boundStandardAttributes
- .where((b) => b.attribute != currentAttr)
- .map((b) => b.boundInput)).toSet();
-
- for (final input in standardHtmlAttributes) {
- // TODO don't recommend [hidden] [hidden] [hidden]
- if (usedStdInputs.contains(input)) {
- continue;
- }
- if (includePlainAttributes && typeProvider != null) {
- if (typeProvider.stringType.isAssignableTo(input.setterType)) {
- final relevance = input.setterType.displayName == 'String'
- ? DART_RELEVANCE_DEFAULT - 2
- : DART_RELEVANCE_DEFAULT - 3;
- collector.addSuggestion(_createPlainAttributeSuggestions(
- input.name,
- relevance,
- _createPlainAttributeElement(
- input.name,
- input.nameOffset,
- input.source.fullName,
- ElementKind.SETTER,
- )));
- }
- }
- collector.addSuggestion(_createInputSuggestion(
- input,
- DART_RELEVANCE_DEFAULT - 2,
- _createInputElement(input, ElementKind.SETTER)));
- }
- }
-
- void suggestInputsInTemplate(
- TemplateAttribute templateAttr, CompletionCollector collector,
- {AttributeInfo currentAttr}) {
- final directives = templateAttr.boundDirectives;
- for (final binding in directives) {
- final usedInputs = new HashSet.from(binding.inputBindings
- .where((b) => b.attribute != currentAttr)
- .map((b) => b.boundInput)).toSet();
-
- for (final input in binding.boundDirective.inputs) {
- // don't recommend trackBy: x trackBy: x trackBy: x
- if (usedInputs.contains(input)) {
- continue;
- }
-
- // edge case. Don't think this comes up in standard.
- if (!input.name.startsWith(templateAttr.prefix)) {
- continue;
- }
-
- // Unlike ngForTrackBy becoming trackBy, ngFor can't become anything.
- if (input.name == templateAttr.prefix) {
- continue;
- }
-
- collector.addSuggestion(_createInputInTemplateSuggestion(
- templateAttr.prefix,
- input,
- DART_RELEVANCE_DEFAULT,
- _createInputElement(input, ElementKind.SETTER)));
- }
- }
- }
-
- void suggestOutputs(
- List<DirectiveBinding> directives,
- CompletionCollector collector,
- List<OutputElement> standardHtmlEvents,
- List<OutputBinding> boundStandardOutputs,
- {BoundAttributeInfo currentAttr}) {
- for (final directive in directives) {
- final usedOutputs = new HashSet.from(directive.outputBindings
- .where((b) => b.attribute != currentAttr)
- .map((b) => b.boundOutput)).toSet();
- for (final output in directive.boundDirective.outputs) {
- // don't recommend (close) (close) (close)
- if (usedOutputs.contains(output)) {
- continue;
- }
- collector.addSuggestion(_createOutputSuggestion(
- output,
- DART_RELEVANCE_DEFAULT,
- _createOutputElement(output, ElementKind.GETTER)));
- }
- }
-
- final usedStdOutputs = new HashSet.from(boundStandardOutputs
- .where((b) => b.attribute != currentAttr)
- .map((b) => b.boundOutput)).toSet();
-
- for (final output in standardHtmlEvents) {
- // don't recommend (click) (click) (click)
- if (usedStdOutputs.contains(output)) {
- continue;
- }
- collector.addSuggestion(_createOutputSuggestion(
- output,
- DART_RELEVANCE_DEFAULT - 1, // just below regular relevance
- _createOutputElement(output, ElementKind.GETTER)));
- }
- }
-
- void suggestRefValues(
- List<DirectiveBinding> directives, CompletionCollector collector) {
- // Keep map of all 'exportAs' name seen. Don't suggest same name twice.
- // If two directives share same exportAs, still suggest one of them
- // and if they use this, and error will flag - let user resolve
- // rather than not suggesting at all.
- final seen = new HashSet<String>();
- for (final directive in directives) {
- final exportAs = directive.boundDirective.exportAs;
- if (exportAs != null && exportAs.name.isNotEmpty) {
- final exportAsName = exportAs.name;
- if (!seen.contains(exportAsName)) {
- seen.add(exportAsName);
- collector.addSuggestion(_createRefValueSuggestion(
- exportAs,
- DART_RELEVANCE_DEFAULT,
- _createRefValueElement(exportAs, ElementKind.LABEL)));
- }
- }
- }
- }
-
- void suggestStarAttrs(Template template, CompletionCollector collector) {
- template.view.directives.where((d) => d.looksLikeTemplate).forEach(
- (directive) =>
- suggestStarAttrsForSelector(directive.selector, collector));
- }
-
- void suggestStarAttrsForSelector(
- Selector selector, CompletionCollector collector) {
- if (selector is OrSelector) {
- for (final subselector in selector.selectors) {
- suggestStarAttrsForSelector(subselector, collector);
- }
- } else if (selector is AndSelector) {
- for (final subselector in selector.selectors) {
- suggestStarAttrsForSelector(subselector, collector);
- }
- } else if (selector is AttributeSelector) {
- if (selector.nameElement.name == "ngForOf") {
- // `ngFor`'s selector includes `[ngForOf]`, but `*ngForOf=..` won't ever
- // work, because it then becomes impossible to satisfy the other half,
- // `[ngFor]`. Hardcode to filter this out, rather than using some kind
- // of complex heuristic.
- return;
- }
-
- collector.addSuggestion(_createStarAttrSuggestion(
- selector,
- DART_RELEVANCE_DEFAULT,
- _createStarAttrElement(selector, ElementKind.CLASS)));
- }
- }
-
- void suggestTransclusions(
- ElementInfo container, CompletionCollector collector) {
- for (final directive in container.directives) {
- if (directive is! Component) {
- continue;
- }
-
- final component = directive as Component;
- final view = component?.view;
- if (view == null) {
- continue;
- }
-
- for (final ngContent in component.ngContents) {
- if (ngContent.selector == null) {
- continue;
- }
-
- final tags = ngContent.selector.suggestTags();
- for (final tag in tags) {
- final location = new Location(view.templateSource.fullName,
- ngContent.offset, ngContent.length, 0, 0);
- collector.addSuggestion(_createHtmlTagSuggestion(
- tag.toString(),
- RELEVANCE_TRANSCLUSION,
- _createHtmlTagTransclusionElement(
- tag.toString(), ElementKind.CLASS_TYPE_ALIAS, location)));
- }
- }
- }
- }
-
- Element _createBananaElement(InputElement inputElement, ElementKind kind) {
- final name = '[(${inputElement.name})]';
- final location = new Location(inputElement.source.fullName,
- inputElement.nameOffset, inputElement.nameLength, 0, 0);
- final flags = Element.makeFlags();
- return new Element(kind, name, flags,
- location: location, returnType: inputElement.setterType.toString());
- }
-
- CompletionSuggestion _createBananaSuggestion(
- InputElement inputElement, int defaultRelevance, Element element) {
- final completion = '[(${inputElement.name})]';
- return new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
- defaultRelevance, completion, completion.length, 0, false, false,
- element: element, returnType: inputElement.setterType.toString());
- }
-
- Element _createHtmlTagElement(
- String elementTagName, AbstractDirective directive, ElementKind kind) {
- final selector = directive.elementTags.firstWhere(
- (currSelector) => currSelector.toString() == elementTagName);
- final offset = selector.nameElement.nameOffset;
- final length = selector.nameElement.nameLength;
-
- final location =
- new Location(directive.source.fullName, offset, length, 0, 0);
- final flags = Element.makeFlags(
- isAbstract: false, isDeprecated: false, isPrivate: false);
- return new Element(kind, '<$elementTagName', flags, location: location);
- }
-
- CompletionSuggestion _createHtmlTagSuggestion(
- String elementTagName, int defaultRelevance, Element element) =>
- new CompletionSuggestion(
- CompletionSuggestionKind.INVOCATION,
- defaultRelevance,
- elementTagName,
- elementTagName.length,
- 0,
- false,
- false,
- element: element);
-
- Element _createHtmlTagTransclusionElement(
- String elementTagName, ElementKind kind, Location location) {
- final flags = Element.makeFlags(
- isAbstract: false, isDeprecated: false, isPrivate: false);
- return new Element(kind, elementTagName, flags, location: location);
- }
-
- Element _createInputElement(InputElement inputElement, ElementKind kind) {
- final name = '[${inputElement.name}]';
- final location = new Location(inputElement.source.fullName,
- inputElement.nameOffset, inputElement.nameLength, 0, 0);
- final flags = Element.makeFlags(
- isAbstract: false, isDeprecated: false, isPrivate: false);
- return new Element(kind, name, flags, location: location);
- }
-
- CompletionSuggestion _createInputInTemplateSuggestion(String prefix,
- InputElement inputElement, int defaultRelevance, Element element) {
- final capitalized = inputElement.name.substring(prefix.length);
- final firstLetter = capitalized.substring(0, 1).toLowerCase();
- final remaining = capitalized.substring(1);
- final completion = '$firstLetter$remaining:';
- return new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
- defaultRelevance, completion, completion.length, 0, false, false,
- element: element);
- }
-
- CompletionSuggestion _createInputSuggestion(
- InputElement inputElement, int defaultRelevance, Element element) {
- final completion = '[${inputElement.name}]';
- return new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
- defaultRelevance, completion, completion.length, 0, false, false,
- element: element);
- }
-
- Element _createOutputElement(OutputElement outputElement, ElementKind kind) {
- final name = '(${outputElement.name})';
- // Note: We use `?? 0` below because focusin/out don't have ranges but we
- // still want to suggest them.
- final location = new Location(outputElement.source.fullName,
- outputElement.nameOffset ?? 0, outputElement.nameLength ?? 0, 0, 0);
- final flags = Element.makeFlags();
- return new Element(kind, name, flags,
- location: location, returnType: outputElement.eventType.toString());
- }
-
- CompletionSuggestion _createOutputSuggestion(
- OutputElement outputElement, int defaultRelevance, Element element) {
- final completion = '(${outputElement.name})';
- return new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
- defaultRelevance, completion, completion.length, 0, false, false,
- element: element, returnType: outputElement.eventType.toString());
- }
-
- Element _createPlainAttributeElement(
- String name, int nameOffset, String locationSource, ElementKind kind) {
- final location =
- new Location(locationSource, nameOffset, name.length, 0, 0);
- final flags = Element.makeFlags(
- isAbstract: false, isDeprecated: false, isPrivate: false);
- return new Element(kind, name, flags, location: location);
- }
-
- CompletionSuggestion _createPlainAttributeSuggestions(
- String completion, int defaultRelevance, Element element) =>
- new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
- defaultRelevance, completion, completion.length, 0, false, false,
- element: element);
-
- Element _createRefValueElement(AngularElement exportAs, ElementKind kind) {
- final name = exportAs.name;
- final location = new Location(exportAs.source.fullName, exportAs.nameOffset,
- exportAs.nameLength, 0, 0);
- final flags = Element.makeFlags();
- return new Element(kind, name, flags, location: location);
- }
-
- CompletionSuggestion _createRefValueSuggestion(
- AngularElement exportAs, int defaultRelevance, Element element) {
- final completion = exportAs.name;
- return new CompletionSuggestion(CompletionSuggestionKind.INVOCATION,
- defaultRelevance, completion, completion.length, 0, false, false,
- element: element);
- }
-
- Element _createStarAttrElement(AttributeSelector selector, ElementKind kind) {
- final name = '*${selector.nameElement.name}';
- final location = new Location(
- selector.nameElement.source.fullName,
- selector.nameElement.nameOffset,
- selector.nameElement.name.length,
- 0,
- 0);
- final flags = Element.makeFlags();
- return new Element(kind, name, flags, location: location);
- }
-
- CompletionSuggestion _createStarAttrSuggestion(
- AttributeSelector selector, int defaultRelevance, Element element) {
- final completion = '*${selector.nameElement.name}';
- return new CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER,
- defaultRelevance, completion, completion.length, 0, false, false,
- element: element);
- }
-}
-
-/// Used to create a shell [ResolvedUnitResult] class for usage in
-/// [TypeMemberContributor] and [InheritedReferenceContributor].
-class _ResolveResultShell implements ResolvedUnitResult {
- @override
- LibraryElement libraryElement;
-
- @override
- TypeProvider typeProvider;
-
- @override
- TypeSystem typeSystem;
-
- @override
- final String path;
-
- _ResolveResultShell(this.path,
- {this.libraryElement, this.typeProvider, this.typeSystem});
-
- @override
- String get content => null;
-
- @override
- List<AnalysisError> get errors => const [];
-
- @override
- bool get isPart => false;
-
- @override
- LineInfo get lineInfo => null;
-
- @override
- AnalysisSession get session => null;
-
- @override
- ResultState get state => null;
-
- @override
- CompilationUnit get unit => null;
-
- @override
- Uri get uri => null;
-}
diff --git a/angular_analyzer_plugin/lib/src/completion_request.dart b/angular_analyzer_plugin/lib/src/completion_request.dart
deleted file mode 100644
index 7aea4e0..0000000
--- a/angular_analyzer_plugin/lib/src/completion_request.dart
+++ /dev/null
@@ -1,214 +0,0 @@
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_ast_factory.dart';
-import 'package:analyzer/dart/ast/token.dart' show TokenType;
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/ast/token.dart'
- show SyntheticBeginToken, SyntheticToken;
-import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
-import 'package:analyzer_plugin/utilities/completion/completion_core.dart';
-import 'package:angular_analyzer_plugin/ast.dart';
-import 'package:angular_analyzer_plugin/src/converter.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/standard_components.dart';
-
-class AngularCompletionRequest extends CompletionRequest {
- final List<Template> templates;
- final StandardHtml standardHtml;
- final String path;
-
- // These values are guaranteed to be unique (if they exist) for the
- // given completion request. As a result, lazy-calculate these fields.
- AstNode _dartSnippet;
- AngularAstNode _angularTarget;
- CompletionTarget _completionTarget;
- var _entryPointCalculated = false;
-
- @override
- final int offset;
-
- @override
- final ResourceProvider resourceProvider;
-
- /// Flag indicating if completion has been aborted.
- bool _aborted = false;
-
- AngularCompletionRequest(this.offset, this.path, this.resourceProvider,
- List<Template> templates, this.standardHtml)
- : templates = templates
- .where((t) =>
- t.view.templateUriSource != null ||
- (t.view.templateOffset <= offset && offset < t.view.end))
- .toList() {
- for (final template in templates) {
- _calculateDartSnippet(template);
- }
- }
-
- AngularAstNode get angularTarget => _angularTarget;
-
- CompletionTarget get completionTarget => _completionTarget;
-
- AstNode get dartSnippet => _dartSnippet;
-
- /// Abort the current completion request.
- void abort() {
- _aborted = true;
- }
-
- @override
- void checkAborted() {
- if (_aborted) {
- // ignore: only_throw_errors
- throw new AbortCompletion();
- }
- }
-
- AstNode _calculateDartSnippet(Template template) {
- if (!_entryPointCalculated) {
- _entryPointCalculated = true;
- final extractor = new _CompletionTargetExtractor(offset);
- template.ast.accept(extractor);
- _dartSnippet = extractor.dartSnippet;
- _angularTarget = extractor.target;
- if (_dartSnippet != null) {
- if (_dartSnippet is Expression) {
- // wrap dart snippet in a ParenthesizedExpression, because the dart
- // completion engine expects all expressions to have parents.
- _dartSnippet = astFactory.parenthesizedExpression(
- new SyntheticBeginToken(TokenType.OPEN_PAREN, _dartSnippet.offset)
- ..next = _dartSnippet.beginToken,
- _dartSnippet as Expression, // requires cast because reassigned
- new SyntheticToken(TokenType.CLOSE_PAREN, _dartSnippet.end));
- }
- _completionTarget = new CompletionTarget.forOffset(null, offset,
- entryPoint: _dartSnippet);
- }
- }
- return _dartSnippet;
- }
-}
-
-class IgnoringAnalysisErrorListener implements AnalysisErrorListener {
- @override
- void onError(AnalysisError error) {}
-}
-
-class _CompletionTargetExtractor implements AngularAstVisitor {
- AstNode dartSnippet;
- AngularAstNode target;
- final int offset;
-
- _CompletionTargetExtractor(this.offset);
-
- /// Check if the [node] contains a [child] node which contains the completion
- /// [offset]. If so, visit the [child] which likely will call this again.
- /// Otherwise, mark [node] as the [target].
- ///
- /// returns true if a [child] was selected, otherwise false.
- bool recurseToTarget(AngularAstNode node) {
- for (final child in node.children) {
- if (_offsetContained(offset, child.offset, child.length)) {
- child.accept(this);
- return true;
- }
- }
-
- target = node;
- return false;
- }
-
- @override
- void visitDocumentInfo(DocumentInfo document) {
- recurseToTarget(document);
- }
-
- @override
- void visitElementInfo(ElementInfo element) {
- // Don't choose tag two in `<tag-one<tag-two></tag-one>`
- if (_offsetContained(offset, element.openingNameSpan.offset,
- element.openingNameSpan.length)) {
- target = element;
- return;
- }
-
- recurseToTarget(element);
- }
-
- @override
- void visitEmptyStarBinding(EmptyStarBinding binding) {
- if (binding.isPrefix) {
- target = binding.parent;
- } else {
- visitTextAttr(binding);
- }
- }
-
- @override
- void visitExpressionBoundAttr(ExpressionBoundAttribute attr) {
- target = attr;
- if (attr.expression != null &&
- _offsetContained(
- offset, attr.expression.offset, attr.expression.length)) {
- dartSnippet = attr.expression;
- }
- }
-
- @override
- void visitMustache(Mustache mustache) {
- target = mustache;
-
- if (_offsetContained(
- offset, mustache.exprBegin, mustache.exprEnd - mustache.exprBegin)) {
- dartSnippet = mustache.expression;
- }
- }
-
- @override
- void visitStatementsBoundAttr(StatementsBoundAttribute attr) {
- target = attr;
- for (final statement in attr.statements) {
- if (_offsetContained(offset, statement.offset, statement.length)) {
- dartSnippet = statement;
- }
- }
- }
-
- @override
- void visitTemplateAttr(TemplateAttribute attr) {
- if (recurseToTarget(attr)) {
- return;
- }
-
- // if we visit this, we're in a template but after one of its attributes.
- AttributeInfo attributeToAppendTo;
- for (final subAttribute in attr.virtualAttributes) {
- if (subAttribute.valueOffset == null && subAttribute.offset < offset) {
- attributeToAppendTo = subAttribute;
- }
- }
-
- if (attributeToAppendTo != null &&
- attributeToAppendTo is EmptyStarBinding) {
- final analysisErrorListener = new IgnoringAnalysisErrorListener();
- final dartParser =
- new EmbeddedDartParser(null, analysisErrorListener, null);
- dartSnippet =
- dartParser.parseDartExpression(offset, '', detectTrailing: false);
- }
- }
-
- @override
- void visitTextAttr(TextAttribute attr) {
- recurseToTarget(attr);
- }
-
- @override
- void visitTextInfo(TextInfo textInfo) {
- recurseToTarget(textInfo);
- }
-
- bool _offsetContained(int offset, int start, int length) =>
- start <= offset && start + length >= offset;
-}
diff --git a/angular_analyzer_plugin/lib/src/converter.dart b/angular_analyzer_plugin/lib/src/converter.dart
deleted file mode 100644
index 9019dae..0000000
--- a/angular_analyzer_plugin/lib/src/converter.dart
+++ /dev/null
@@ -1,870 +0,0 @@
-import 'dart:math';
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/token.dart' hide SimpleToken;
-import 'package:analyzer/src/dart/scanner/reader.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/ast.dart';
-import 'package:angular_analyzer_plugin/errors.dart';
-import 'package:angular_analyzer_plugin/src/ignoring_error_listener.dart';
-import 'package:angular_analyzer_plugin/src/ng_expr_parser.dart';
-import 'package:angular_analyzer_plugin/src/strings.dart';
-import 'package:angular_analyzer_plugin/src/tuple.dart';
-import 'package:angular_ast/angular_ast.dart';
-import 'package:meta/meta.dart';
-
-class EmbeddedDartParser {
- final Source templateSource;
- final AnalysisErrorListener errorListener;
- final ErrorReporter errorReporter;
-
- EmbeddedDartParser(
- this.templateSource, this.errorListener, this.errorReporter);
-
- /// Scan the given [text] staring at the given [offset] and resolve all of
- /// its embedded expressions.
- List<Mustache> findMustaches(String text, int fileOffset) {
- final mustaches = <Mustache>[];
- if (text == null || text.length < 2) {
- return mustaches;
- }
-
- var textOffset = 0;
- while (true) {
- // begin
- final begin = text.indexOf('{{', textOffset);
- final nextBegin = text.indexOf('{{', begin + 2);
- final end = text.indexOf('}}', textOffset);
-
- int exprBegin, exprEnd;
- var detectTrailing = false;
-
- // Absolutely no mustaches - simple text.
- if (begin == -1 && end == -1) {
- break;
- }
-
- if (end == -1) {
- // Begin mustache exists, but no end mustache.
- errorListener.onError(new AnalysisError(templateSource,
- fileOffset + begin, 2, AngularWarningCode.UNTERMINATED_MUSTACHE));
- // Move the cursor ahead and keep looking for more unmatched mustaches.
- textOffset = begin + 2;
- exprBegin = textOffset;
- exprEnd = _startsWithWhitespace(text.substring(exprBegin))
- ? exprBegin
- : text.length;
- } else if (begin == -1 || end < begin) {
- // Both exists, but there is an end before a begin.
- // Example: blah }} {{ mustache ...
- errorListener.onError(new AnalysisError(templateSource,
- fileOffset + end, 2, AngularWarningCode.UNOPENED_MUSTACHE));
- // Move the cursor ahead and keep looking for more unmatched mustaches.
- textOffset = end + 2;
- continue;
- } else if (nextBegin != -1 && nextBegin < end) {
- // Two open mustaches, but both opens are in sequence before an end.
- // Example: {{ blah {{ mustache }}
- errorListener.onError(new AnalysisError(templateSource,
- fileOffset + begin, 2, AngularWarningCode.UNTERMINATED_MUSTACHE));
- // Skip this open mustache, check the next open we found
- textOffset = begin + 2;
- exprBegin = textOffset;
- exprEnd = nextBegin;
- } else {
- // Proper open and close mustache exists and in correct order.
- exprBegin = begin + 2;
- exprEnd = end;
- textOffset = end + 2;
- detectTrailing = true;
- }
- // resolve
- final code = text.substring(exprBegin, exprEnd);
- final expression = parseDartExpression(fileOffset + exprBegin, code,
- detectTrailing: detectTrailing);
-
- final offset = fileOffset + begin;
-
- int length;
- if (end == -1) {
- length = expression.offset + expression.length - offset;
- } else {
- length = end + 2 - begin;
- }
-
- mustaches.add(new Mustache(
- offset,
- length,
- expression,
- fileOffset + exprBegin,
- fileOffset + exprEnd,
- ));
- }
- return mustaches;
- }
-
- /// Parse the given Dart [code] that starts at [offset].
- Expression parseDartExpression(int offset, String code,
- {@required bool detectTrailing}) {
- if (code == null) {
- return null;
- }
-
- final token = _scanDartCode(offset, code);
- Expression expression;
-
- // suppress errors for this. But still parse it so we can analyze it and stuff
- if (code.trim().isEmpty) {
- expression = _parseDartExpressionAtToken(token,
- errorListener: new IgnoringAnalysisErrorListener());
- } else {
- expression = _parseDartExpressionAtToken(token);
- }
-
- if (detectTrailing && expression.endToken.next.type != TokenType.EOF) {
- final trailingExpressionBegin = expression.endToken.next.offset;
- errorListener.onError(new AnalysisError(
- templateSource,
- trailingExpressionBegin,
- offset + code.length - trailingExpressionBegin,
- AngularWarningCode.TRAILING_EXPRESSION));
- }
-
- return expression;
- }
-
- /// Parse the given Dart [code] that starts ot [offset].
- /// Also removes and reports dangling closing brackets.
- List<Statement> parseDartStatements(int offset, String code) {
- final allStatements = <Statement>[];
- if (code == null) {
- return allStatements;
- }
-
- // ignore: parameter_assignments, prefer_interpolation_to_compose_strings
- code = code + ';';
-
- var token = _scanDartCode(offset, code);
-
- while (token.type != TokenType.EOF) {
- final currentStatements = _parseDartStatementsAtToken(token);
-
- if (currentStatements.isNotEmpty) {
- allStatements.addAll(currentStatements);
- token = currentStatements.last.endToken.next;
- }
- if (token.type == TokenType.EOF) {
- break;
- }
- if (token.type == TokenType.CLOSE_CURLY_BRACKET) {
- final startCloseBracket = token.offset;
- while (token.type == TokenType.CLOSE_CURLY_BRACKET) {
- token = token.next;
- }
- final length = token.offset - startCloseBracket;
- errorListener.onError(new AnalysisError(
- templateSource,
- startCloseBracket,
- length,
- ParserErrorCode.UNEXPECTED_TOKEN,
- ["}"]));
- continue;
- } else {
- //Nothing should trigger here, but just in case to prevent infinite loop
- token = token.next;
- }
- }
- return allStatements;
- }
-
- /// Desugar a template="" or *blah="" attribute into its list of virtual
- /// [AttributeInfo]s
- Tuple2<String, List<AttributeInfo>> parseTemplateVirtualAttributes(
- int offset, String code) {
- final attributes = <AttributeInfo>[];
-
- var token = _scanDartCode(offset, code);
- String prefix;
- while (token.type != TokenType.EOF) {
- // skip optional comma or semicolons
- if (_isDelimiter(token)) {
- token = token.next;
- continue;
- }
- // maybe a local variable
- if (_isTemplateVarBeginToken(token)) {
- final originalVarOffset = token.offset;
- if (token.type == TokenType.HASH) {
- errorReporter.reportErrorForToken(
- AngularWarningCode.UNEXPECTED_HASH_IN_TEMPLATE, token);
- }
-
- var originalName = token.lexeme;
-
- // get the local variable name
- token = token.next;
- var localVarName = "";
- var localVarOffset = token.offset;
- if (!_tokenMatchesIdentifier(token)) {
- errorReporter.reportErrorForToken(
- AngularWarningCode.EXPECTED_IDENTIFIER, token);
- } else {
- localVarOffset = token.offset;
- localVarName = token.lexeme;
- // ignore: prefer_interpolation_to_compose_strings
- originalName +=
- ' ' * (token.offset - originalVarOffset - 'let'.length) +
- localVarName;
- token = token.next;
- }
-
- // get an optional internal variable
- int internalVarOffset;
- String internalVarName;
- if (token.type == TokenType.EQ) {
- token = token.next;
- // get the internal variable
- if (!_tokenMatchesIdentifier(token)) {
- errorReporter.reportErrorForToken(
- AngularWarningCode.EXPECTED_IDENTIFIER, token);
- break;
- }
- internalVarOffset = token.offset;
- internalVarName = token.lexeme;
- token = token.next;
- }
- // declare the local variable
- // Note the care that the varname's offset is preserved in place.
- attributes.add(new TextAttribute.synthetic(
- 'let-$localVarName',
- localVarOffset - 'let-'.length,
- internalVarName,
- internalVarOffset,
- originalName,
- originalVarOffset, []));
- continue;
- }
-
- // key
- String key;
- final keyBuffer = new StringBuffer();
- final keyOffset = token.offset;
- String originalName;
- final originalNameOffset = keyOffset;
- if (_tokenMatchesIdentifier(token)) {
- // scan for a full attribute name
- var lastEnd = token.offset;
- while (token.offset == lastEnd &&
- (_tokenMatchesIdentifier(token) || token.type == TokenType.MINUS)) {
- keyBuffer.write(token.lexeme);
- lastEnd = token.end;
- token = token.next;
- }
-
- originalName = keyBuffer.toString();
-
- // add the prefix
- if (prefix == null) {
- prefix = keyBuffer.toString();
- key = keyBuffer.toString();
- } else {
- // ignore: prefer_interpolation_to_compose_strings
- key = prefix + capitalize(keyBuffer.toString());
- }
- } else {
- errorReporter.reportErrorForToken(
- AngularWarningCode.EXPECTED_IDENTIFIER, token);
- break;
- }
- // skip optional ':' or '='
- if (token.type == TokenType.COLON || token.type == TokenType.EQ) {
- token = token.next;
- }
- // expression
- if (!_isTemplateVarBeginToken(token) &&
- !_isDelimiter(token) &&
- token.type != TokenType.EOF) {
- final expression = _parseDartExpressionAtToken(token);
- final start = token.offset - offset;
-
- token = expression.endToken.next;
- // The tokenizer isn't perfect always. Ensure [end] <= [code.length].
- final end = min(token.offset - offset, code.length);
- final exprCode = code.substring(start, end);
- attributes.add(new ExpressionBoundAttribute(
- key,
- keyOffset,
- exprCode,
- expression.offset,
- originalName,
- originalNameOffset,
- expression,
- ExpressionBoundType.input));
- } else {
- // A special kind of TextAttr that signifies its special.
- final binding = new EmptyStarBinding(
- key, keyOffset, originalName, originalNameOffset,
- isPrefix: attributes.isEmpty);
-
- attributes.add(binding);
-
- // Check for empty `of` and `trackBy` bindings, but NOT empty `ngIf`!
- // NgFor (and other star directives) often result in a harmless, empty
- // first attr. Don't flag it unless it matches an input (like `ngIf`
- // does), which is checked by [SingleScopeResolver].
- if (!binding.isPrefix) {
- errorReporter.reportErrorForOffset(AngularWarningCode.EMPTY_BINDING,
- originalNameOffset, originalName.length, [originalName]);
- }
- }
- }
-
- return new Tuple2(prefix, attributes);
- }
-
- /// Parse the Dart expression starting at the given [token].
- Expression _parseDartExpressionAtToken(Token token,
- {AnalysisErrorListener errorListener}) {
- errorListener ??= this.errorListener;
- final parser = new NgExprParser(templateSource, errorListener);
- return parser.parseExpression(token);
- }
-
- /// Parse the Dart statement starting at the given [token].
- List<Statement> _parseDartStatementsAtToken(Token token) {
- final parser = new Parser.withoutFasta(templateSource, errorListener);
- return parser.parseStatements(token);
- }
-
- /// Scan the given Dart [code] that starts at [offset].
- Token _scanDartCode(int offset, String code) {
- // Warning: we lexically and unintelligently "accept" `===` for now by
- // replacing it with `==`. This is actually OK for us since we can butcher
- // string literal contents fine, and it won't affect analysis.
- final noTripleEquals =
- code.replaceAll('===', '== ').replaceAll('!==', '!= ');
-
- // ignore: prefer_interpolation_to_compose_strings
- final text = ' ' * offset + noTripleEquals;
- final reader = new CharSequenceReader(text);
- final scanner = new Scanner(templateSource, reader, errorListener);
- return scanner.tokenize();
- }
-
- bool _startsWithWhitespace(String string) =>
- // trim returns the original string when no changes were made
- !identical(string.trimLeft(), string);
-
- static bool _isDelimiter(Token token) =>
- token.type == TokenType.COMMA || token.type == TokenType.SEMICOLON;
-
- static bool _isTemplateVarBeginToken(Token token) =>
- token is KeywordToken && token.keyword == Keyword.VAR ||
- (token.type == TokenType.IDENTIFIER && token.lexeme == 'let') ||
- token.type == TokenType.HASH;
-
- static bool _tokenMatchesBuiltInIdentifier(Token token) =>
- token is KeywordToken && token.keyword.isBuiltInOrPseudo;
-
- static bool _tokenMatchesIdentifier(Token token) =>
- token.type == TokenType.IDENTIFIER ||
- _tokenMatchesBuiltInIdentifier(token);
-}
-
-class HtmlTreeConverter {
- final EmbeddedDartParser dartParser;
- final Source templateSource;
- final AnalysisErrorListener errorListener;
-
- HtmlTreeConverter(this.dartParser, this.templateSource, this.errorListener);
-
- NodeInfo convert(
- StandaloneTemplateAst node, {
- @required ElementInfo parent,
- }) {
- if (node is ElementAst) {
- final attributes = _convertAttributes(
- attributes: node.attributes,
- bananas: node.bananas,
- events: node.events,
- properties: node.properties,
- references: node.references,
- stars: node.stars,
- )..sort((a, b) => a.offset.compareTo(b.offset));
-
- return _elementInfoFromNodeAndCloseComplement(
- node,
- node.name,
- attributes,
- node.closeComplement,
- parent,
- );
- } else if (node is ContainerAst) {
- final attributes = _convertAttributes(
- stars: node.stars,
- )..sort((a, b) => a.offset.compareTo(b.offset));
-
- return _elementInfoFromNodeAndCloseComplement(
- node,
- 'ng-container',
- attributes,
- node.closeComplement,
- parent,
- );
- } else if (node is EmbeddedContentAst) {
- final attributes = <AttributeInfo>[];
-
- if (node is ParsedEmbeddedContentAst) {
- final valueToken = node.selectorValueToken;
- if (node.selectToken != null) {
- attributes.add(new TextAttribute(
- 'select',
- node.selectToken.offset,
- valueToken?.innerValue?.lexeme,
- valueToken?.innerValue?.offset,
- [],
- ));
- }
- }
-
- return _elementInfoFromNodeAndCloseComplement(
- node,
- 'ng-content',
- attributes,
- node.closeComplement,
- parent,
- );
- } else if (node is EmbeddedTemplateAst) {
- final attributes = _convertAttributes(
- attributes: node.attributes,
- events: node.events,
- properties: node.properties,
- references: node.references,
- letBindings: node.letBindings,
- );
-
- return _elementInfoFromNodeAndCloseComplement(
- node,
- 'template',
- attributes,
- node.closeComplement,
- parent,
- );
- } else if (node is TextAst) {
- final offset = node.sourceSpan.start.offset;
- final text = node.value;
- return new TextInfo(
- offset, text, parent, dartParser.findMustaches(text, offset));
- } else if (node is InterpolationAst) {
- final offset = node.sourceSpan.start.offset;
- final text = '{{${node.value}}}';
- return new TextInfo(
- offset, text, parent, dartParser.findMustaches(text, offset));
- } else {
- assert(
- node is CommentAst, 'Unknown node type ${node.runtimeType} ($node)');
- }
- return null;
- }
-
- DocumentInfo convertFromAstList(List<StandaloneTemplateAst> asts) {
- final root = new DocumentInfo();
- if (asts.isEmpty) {
- root.childNodes.add(new TextInfo(0, '', root, []));
- }
- for (final node in asts) {
- final convertedNode = convert(node, parent: root);
- if (convertedNode != null) {
- root.childNodes.add(convertedNode);
- }
- }
- return root;
- }
-
- TemplateAttribute findTemplateAttribute(List<AttributeInfo> attributes) {
- for (final attribute in attributes) {
- if (attribute is TemplateAttribute) {
- return attribute;
- }
- }
- return null;
- }
-
- List<AttributeInfo> _convertAttributes({
- List<AttributeAst> attributes: const [],
- List<BananaAst> bananas: const [],
- List<EventAst> events: const [],
- List<PropertyAst> properties: const [],
- List<ReferenceAst> references: const [],
- List<StarAst> stars: const [],
- List<LetBindingAst> letBindings: const [],
- }) {
- final returnAttributes = <AttributeInfo>[];
-
- for (final attribute in attributes) {
- if (attribute is ParsedAttributeAst) {
- if (attribute.name == 'template') {
- returnAttributes.add(_convertTemplateAttribute(attribute));
- } else {
- String value;
- int valueOffset;
- if (attribute.valueToken != null) {
- value = attribute.valueToken.innerValue.lexeme;
- valueOffset = attribute.valueToken.innerValue.offset;
- }
- returnAttributes.add(new TextAttribute(
- attribute.name,
- attribute.nameOffset,
- value,
- valueOffset,
- dartParser.findMustaches(value, valueOffset),
- ));
- }
- }
- }
-
- bananas.map(_convertExpressionBoundAttribute).forEach(returnAttributes.add);
- events.map(_convertStatementsBoundAttribute).forEach(returnAttributes.add);
- properties
- .map(_convertExpressionBoundAttribute)
- .forEach(returnAttributes.add);
-
- for (final reference in references) {
- if (reference is ParsedReferenceAst) {
- String value;
- int valueOffset;
- if (reference.valueToken != null) {
- value = reference.valueToken.innerValue.lexeme;
- valueOffset = reference.valueToken.innerValue.offset;
- }
- returnAttributes.add(new TextAttribute(
- '${reference.prefixToken.lexeme}${reference.nameToken.lexeme}',
- reference.prefixToken.offset,
- value,
- valueOffset, const <Mustache>[]));
- }
- }
-
- // Guaranteed to be empty for non-template elements.
- for (final letBinding in letBindings) {
- if (letBinding is ParsedLetBindingAst) {
- String value;
- int valueOffset;
- if (letBinding.valueToken != null) {
- value = letBinding.valueToken.innerValue.lexeme;
- valueOffset = letBinding.valueToken.innerValue.offset;
- }
- returnAttributes.add(new TextAttribute(
- '${letBinding.prefixToken.lexeme}${letBinding.nameToken.lexeme}',
- letBinding.prefixToken.offset,
- value,
- valueOffset, <Mustache>[]));
- }
- }
-
- stars.map(_convertTemplateAttribute).forEach(returnAttributes.add);
-
- return returnAttributes;
- }
-
- List<NodeInfo> _convertChildren(
- StandaloneTemplateAst node, ElementInfo parent) {
- final children = <NodeInfo>[];
- for (final child in node.childNodes) {
- final childNode = convert(child, parent: parent);
- if (childNode != null) {
- children.add(childNode);
- if (childNode is ElementInfo) {
- parent.childNodesMaxEnd = childNode.childNodesMaxEnd;
- } else {
- parent.childNodesMaxEnd = childNode.offset + childNode.length;
- }
- }
- }
- return children;
- }
-
- ExpressionBoundAttribute _convertExpressionBoundAttribute(TemplateAst ast) {
- // Default starting.
- var bound = ExpressionBoundType.input;
-
- final parsed = ast as ParsedDecoratorAst;
- final suffixToken = parsed.suffixToken;
- final nameToken = parsed.nameToken;
- final prefixToken = parsed.prefixToken;
-
- String origName;
- {
- final _prefix = prefixToken.errorSynthetic ? '' : prefixToken.lexeme;
- final _suffix = (suffixToken == null || suffixToken.errorSynthetic)
- ? ''
- : suffixToken.lexeme;
- origName = '$_prefix${nameToken.lexeme}$_suffix';
- }
- final origNameOffset = prefixToken.offset;
-
- var propName = nameToken.lexeme;
- var propNameOffset = nameToken.offset;
-
- if (ast is ParsedPropertyAst) {
- // For some inputs, like `[class.foo]`, the [ast.name] here is actually
- // not a name, but a prefix. If so, use the [ast.postfix] as the [name] of
- // the [ExpressionBoundAttribute] we're creating here, by changing
- // [propName].
- final nameOrPrefix = ast.name;
-
- if (ast.postfix != null) {
- var usePostfixForName = false;
- var preserveUnitInName = false;
-
- if (nameOrPrefix == 'class') {
- bound = ExpressionBoundType.clazz;
- usePostfixForName = true;
- preserveUnitInName = true;
- } else if (nameOrPrefix == 'attr') {
- if (ast.unit == 'if') {
- bound = ExpressionBoundType.attrIf;
- } else {
- bound = ExpressionBoundType.attr;
- }
- usePostfixForName = true;
- } else if (nameOrPrefix == 'style') {
- bound = ExpressionBoundType.style;
- usePostfixForName = true;
- preserveUnitInName = ast.unit != null;
- }
-
- if (usePostfixForName) {
- final _unitName =
- preserveUnitInName && ast.unit != null ? '.${ast.unit}' : '';
- propName = '${ast.postfix}$_unitName';
- propNameOffset = nameToken.offset + ast.name.length + '.'.length;
- } else {
- assert(!preserveUnitInName);
- }
- }
- } else {
- bound = ExpressionBoundType.twoWay;
- }
-
- final value = parsed.valueToken?.innerValue?.lexeme;
- if ((value == null || value.isEmpty) &&
- !prefixToken.errorSynthetic &&
- (suffixToken == null ? true : !suffixToken.errorSynthetic)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- origNameOffset,
- origName.length,
- AngularWarningCode.EMPTY_BINDING,
- [origName],
- ));
- }
- final valueOffset = parsed.valueToken?.innerValue?.offset;
-
- return new ExpressionBoundAttribute(
- propName,
- propNameOffset,
- value,
- valueOffset,
- origName,
- origNameOffset,
- dartParser.parseDartExpression(valueOffset, value,
- detectTrailing: true),
- bound);
- }
-
- StatementsBoundAttribute _convertStatementsBoundAttribute(EventAst eventAst) {
- final ast = eventAst as ParsedEventAst;
- final prefixToken = ast.prefixToken;
- final nameToken = ast.nameToken;
- final suffixToken = ast.suffixToken;
-
- final prefixComponent =
- (prefixToken.errorSynthetic ? '' : prefixToken.lexeme);
- final suffixComponent =
- ((suffixToken == null) || suffixToken.errorSynthetic)
- ? ''
- : suffixToken.lexeme;
- final origName = '$prefixComponent${ast.name}$suffixComponent';
- final origNameOffset = prefixToken.offset;
-
- final value = ast.value;
- if ((value == null || value.isEmpty) &&
- !prefixToken.errorSynthetic &&
- (suffixToken == null ? true : !suffixToken.errorSynthetic)) {
- errorListener.onError(new AnalysisError(templateSource, origNameOffset,
- origName.length, AngularWarningCode.EMPTY_BINDING, [ast.name]));
- }
- final valueOffset = ast.valueOffset;
-
- final propName = ast.name;
- final propNameOffset = nameToken.offset;
-
- return new StatementsBoundAttribute(
- propName,
- propNameOffset,
- value,
- valueOffset,
- origName,
- origNameOffset,
- ast.reductions,
- dartParser.parseDartStatements(valueOffset, value));
- }
-
- TemplateAttribute _convertTemplateAttribute(TemplateAst ast) {
- String name;
- String prefix;
- int nameOffset;
-
- String value;
- int valueOffset;
-
- String origName;
- int origNameOffset;
-
- var virtualAttributes = <AttributeInfo>[];
-
- if (ast is ParsedStarAst) {
- value = ast.value;
- valueOffset = ast.valueOffset;
-
- origName = '${ast.prefixToken.lexeme}${ast.nameToken.lexeme}';
- origNameOffset = ast.prefixToken.offset;
-
- name = ast.nameToken.lexeme;
- nameOffset = ast.nameToken.offset;
-
- String fullAstName;
- if (value != null) {
- final whitespacePad =
- ' ' * (ast.valueToken.innerValue.offset - ast.nameToken.end);
- fullAstName = "${ast.name}$whitespacePad${value ?? ''}";
- } else {
- fullAstName = '${ast.name} ';
- }
-
- final tuple =
- dartParser.parseTemplateVirtualAttributes(nameOffset, fullAstName);
- virtualAttributes = tuple.item2;
- prefix = tuple.item1;
- }
- if (ast is ParsedAttributeAst) {
- value = ast.value;
- valueOffset = ast.valueOffset;
-
- origName = ast.name;
- origNameOffset = ast.nameOffset;
-
- name = origName;
- nameOffset = origNameOffset;
-
- if (value == null || value.isEmpty) {
- errorListener.onError(new AnalysisError(templateSource, origNameOffset,
- origName.length, AngularWarningCode.EMPTY_BINDING, [origName]));
- } else {
- virtualAttributes =
- dartParser.parseTemplateVirtualAttributes(valueOffset, value).item2;
- }
- }
-
- final templateAttribute = new TemplateAttribute(name, nameOffset, value,
- valueOffset, origName, origNameOffset, virtualAttributes,
- prefix: prefix);
-
- for (final virtualAttribute in virtualAttributes) {
- virtualAttribute.parent = templateAttribute;
- }
-
- return templateAttribute;
- }
-
- /// There are four types of "tags" in angular_ast which don't implement a
- /// common interface. But we need to generate source spans for all of them.
- /// We can do this if we have the [node] (we can use its [beginToken]) and its
- /// [closeComplement]. So this takes that info, plus a few other structural
- /// things ([attributes], [parent], [tagName]), to handle all four cases.
- ElementInfo _elementInfoFromNodeAndCloseComplement(
- StandaloneTemplateAst node,
- String tagName,
- List<AttributeInfo> attributes,
- CloseElementAst closeComplement,
- ElementInfo parent) {
- final isTemplate = tagName == 'template';
- SourceRange openingSpan;
- SourceRange openingNameSpan;
- SourceRange closingSpan;
- SourceRange closingNameSpan;
-
- if (node.isSynthetic && closeComplement != null) {
- // This code assumes that a synthetic node is a close tag with no open
- // tag, ie, a dangling `</div>`.
- openingSpan = _toSourceRange(closeComplement.beginToken.offset, 0);
- openingNameSpan ??= openingSpan;
- } else {
- openingSpan = _toSourceRange(
- node.beginToken.offset, node.endToken.end - node.beginToken.offset);
- openingNameSpan ??=
- new SourceRange(node.beginToken.offset + '<'.length, tagName.length);
- }
-
- if (closeComplement != null) {
- if (!closeComplement.isSynthetic) {
- closingSpan = _toSourceRange(closeComplement.beginToken.offset,
- closeComplement.endToken.end - closeComplement.beginToken.offset);
- closingNameSpan =
- new SourceRange(closingSpan.offset + '</'.length, tagName.length);
- } else {
- // TODO(mfairhurst): generate a closingSpan for synthetic tags too. This
- // can mess up autocomplete if we do it wrong.
- }
- }
-
- final element = new ElementInfo(
- tagName,
- openingSpan,
- closingSpan,
- openingNameSpan,
- closingNameSpan,
- attributes,
- findTemplateAttribute(attributes),
- parent,
- isTemplate: isTemplate,
- );
-
- for (final attribute in attributes) {
- attribute.parent = element;
- }
-
- final children = _convertChildren(node, element);
- element.childNodes.addAll(children);
-
- // For empty tags, ie, `<div></div>`, generate a synthetic text entry
- // between the two tags. This simplifies later autocomplete code.
- if (!element.isSynthetic &&
- element.openingSpanIsClosed &&
- closingSpan != null &&
- (openingSpan.offset + openingSpan.length) == closingSpan.offset) {
- element.childNodes.add(new TextInfo(
- openingSpan.offset + openingSpan.length, '', element, [],
- synthetic: true));
- }
-
- return element;
- }
-
- SourceRange _toSourceRange(int offset, int length) =>
- new SourceRange(offset, length);
-}
-
-class IgnorableHtmlInternalException implements Exception {
- String msg;
- IgnorableHtmlInternalException(this.msg);
-
- @override
- String toString() => "IgnorableHtmlInternalException: $msg";
-}
diff --git a/angular_analyzer_plugin/lib/src/directive_extraction.dart b/angular_analyzer_plugin/lib/src/directive_extraction.dart
deleted file mode 100644
index 836702f..0000000
--- a/angular_analyzer_plugin/lib/src/directive_extraction.dart
+++ /dev/null
@@ -1,536 +0,0 @@
-import 'package:analyzer/dart/ast/ast.dart' as ast;
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/errors.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-import 'package:angular_analyzer_plugin/src/tasks.dart';
-import 'package:angular_analyzer_plugin/src/tuple.dart';
-
-class AttributeAnnotationValidator {
- final ErrorReporter errorReporter;
-
- AttributeAnnotationValidator(this.errorReporter);
-
- void validate(AbstractClassDirective directive) {
- final classElement = directive.classElement;
- for (final constructor in classElement.constructors) {
- for (final parameter in constructor.parameters) {
- for (final annotation in parameter.metadata) {
- if (annotation.element?.enclosingElement?.name != "Attribute") {
- continue;
- }
-
- final attributeName = annotation
- .computeConstantValue()
- ?.getField("attributeName")
- ?.toStringValue();
- if (attributeName == null) {
- continue;
- // TODO do we ever need to report an error here, or will DAS?
- }
-
- if (parameter.type.name != "String") {
- errorReporter.reportErrorForOffset(
- AngularWarningCode.ATTRIBUTE_PARAMETER_MUST_BE_STRING,
- parameter.nameOffset,
- parameter.name.length);
- }
-
- directive.attributes.add(new AngularElementImpl(attributeName,
- parameter.nameOffset, parameter.nameLength, parameter.source));
- }
- }
- }
- }
-}
-
-class BindingTypeSynthesizer {
- final InterfaceType _instantiatedClassType;
- final TypeProvider _typeProvider;
- final AnalysisContext _context;
- final ErrorReporter _errorReporter;
-
- BindingTypeSynthesizer(ClassElement classElem, TypeProvider typeProvider,
- this._context, this._errorReporter)
- : _instantiatedClassType = _instantiateClass(classElem, typeProvider),
- _typeProvider = typeProvider;
-
- DartType getEventType(PropertyAccessorElement getter, String name) {
- if (getter != null) {
- // ignore: parameter_assignments
- getter = _instantiatedClassType.lookUpInheritedGetter(getter.name,
- thisType: true);
- }
-
- if (getter != null && getter.type != null) {
- final returnType = getter.type.returnType;
- if (returnType != null && returnType is InterfaceType) {
- final streamType = _typeProvider.streamType;
- final streamedType = _context.typeSystem
- .mostSpecificTypeArgument(returnType, streamType);
- if (streamedType != null) {
- return streamedType;
- } else {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.OUTPUT_MUST_BE_STREAM,
- getter.nameOffset,
- getter.name.length,
- [name]);
- }
- } else {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.OUTPUT_MUST_BE_STREAM,
- getter.nameOffset,
- getter.name.length,
- [name]);
- }
- }
-
- return _typeProvider.dynamicType;
- }
-
- DartType getSetterType(PropertyAccessorElement setter) {
- if (setter != null) {
- // ignore: parameter_assignments
- setter = _instantiatedClassType.lookUpInheritedSetter(setter.name,
- thisType: true);
- }
-
- if (setter != null && setter.type.parameters.length == 1) {
- return setter.type.parameters[0].type;
- }
-
- return null;
- }
-
- static InterfaceType _instantiateClass(
- ClassElement classElement, TypeProvider typeProvider) {
- // TODO use `insantiateToBounds` for better all around support
- // See #91 for discussion about bugs related to bounds
- DartType getBound(TypeParameterElement p) => p.bound == null
- ? typeProvider.dynamicType
- : p.bound.resolveToBound(typeProvider.dynamicType);
-
- final bounds = classElement.typeParameters.map(getBound).toList();
- return classElement.type.instantiate(bounds);
- }
-}
-
-class DirectiveExtractor extends AnnotationProcessorMixin {
- final TypeProvider _typeProvider;
- final ast.CompilationUnit _unit;
- final Source _source;
- final AnalysisContext _context;
-
- /// Since <my-comp></my-comp> represents an instantiation of MyComp,
- /// especially when MyComp is generic or its superclasses are, we need
- /// this. Cache instead of passing around everywhere.
- BindingTypeSynthesizer _bindingTypeSynthesizer;
-
- /// The [ClassElement] being used to create the current component,
- /// stored here instead of passing around everywhere.
- ClassElement _currentClassElement;
-
- DirectiveExtractor(
- this._unit, this._typeProvider, this._source, this._context) {
- initAnnotationProcessor(_source);
- }
-
- List<AngularTopLevel> getAngularTopLevels() {
- final declarations = <AngularTopLevel>[];
- for (final unitMember in _unit.declarations) {
- if (unitMember is ast.ClassDeclaration) {
- final directive = _getAngularAnnotatedClass(unitMember);
- if (directive != null) {
- declarations.add(directive);
- }
- } else if (unitMember is ast.FunctionDeclaration) {
- final directive = _getFunctionalDirective(unitMember);
- if (directive != null) {
- declarations.add(directive);
- }
- }
- }
-
- return declarations;
- }
-
- /// Returns an Angular [AbstractDirective] for to the given [node].
- /// Returns `null` if not an Angular annotation.
- AngularAnnotatedClass _getAngularAnnotatedClass(
- ast.ClassDeclaration classDeclaration) {
- _currentClassElement = classDeclaration.declaredElement;
- _bindingTypeSynthesizer = new BindingTypeSynthesizer(
- _currentClassElement, _typeProvider, _context, errorReporter);
- // TODO(scheglov) add support for all the arguments
- final componentNode = classDeclaration.metadata.firstWhere(
- (ann) => isAngularAnnotation(ann, 'Component'),
- orElse: () => null);
- final directiveNode = classDeclaration.metadata.firstWhere(
- (ann) => isAngularAnnotation(ann, 'Directive'),
- orElse: () => null);
- final annotationNode = componentNode ?? directiveNode;
-
- final inputElements = <InputElement>[];
- final outputElements = <OutputElement>[];
- final contentChilds = <ContentChildField>[];
- final contentChildrens = <ContentChildField>[];
- _parseContentChilds(classDeclaration, contentChilds, contentChildrens);
-
- if (annotationNode != null) {
- // Don't fail to create a Component just because of a broken or missing
- // selector, that results in cascading errors.
- final selector = _parseSelector(annotationNode) ?? new AndSelector([]);
- final exportAs = _parseExportAs(annotationNode);
- final elementTags = <ElementNameSelector>[];
- _parseMemberInputsAndOutputs(
- classDeclaration, inputElements, outputElements);
- selector.recordElementNameSelectors(elementTags);
- if (componentNode != null) {
- return new Component(_currentClassElement,
- exportAs: exportAs,
- inputs: inputElements,
- outputs: outputElements,
- selector: selector,
- elementTags: elementTags,
- isHtml: false,
- contentChildFields: contentChilds,
- contentChildrenFields: contentChildrens);
- }
- if (directiveNode != null) {
- return new Directive(_currentClassElement,
- exportAs: exportAs,
- inputs: inputElements,
- outputs: outputElements,
- selector: selector,
- elementTags: elementTags,
- contentChildFields: contentChilds,
- contentChildrenFields: contentChildrens);
- }
- }
-
- _parseMemberInputsAndOutputs(
- classDeclaration, inputElements, outputElements);
- if (inputElements.isNotEmpty ||
- outputElements.isNotEmpty ||
- contentChilds.isNotEmpty ||
- contentChildrens.isNotEmpty) {
- return new AngularAnnotatedClass(_currentClassElement,
- inputs: inputElements,
- outputs: outputElements,
- contentChildFields: contentChilds,
- contentChildrenFields: contentChildrens);
- }
-
- return null;
- }
-
- /// Returns an Angular [FunctionalDirective] for to the given [node].
- /// Returns `null` if not an Angular annotation.
- FunctionalDirective _getFunctionalDirective(
- ast.FunctionDeclaration functionDeclaration) {
- final functionElement = functionDeclaration.declaredElement;
- if (functionElement is FunctionElement) {
- final annotationNode = functionDeclaration.metadata.firstWhere(
- (ann) => isAngularAnnotation(ann, 'Directive'),
- orElse: () => null);
-
- if (annotationNode != null) {
- // Don't fail to create a directive just because of a broken or missing
- // selector, that results in cascading errors.
- final selector = _parseSelector(annotationNode) ?? new AndSelector([]);
- final elementTags = <ElementNameSelector>[];
- final exportAs = getNamedArgument(annotationNode, 'exportAs');
- if (exportAs != null) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.FUNCTIONAL_DIRECTIVES_CANT_BE_EXPORTED,
- exportAs);
- }
- selector.recordElementNameSelectors(elementTags);
- return new FunctionalDirective(functionElement, selector, elementTags);
- }
- }
-
- return null;
- }
-
- /// Return the first named argument with one of the given names, or
- /// `null` if this argument is not [ast.ListLiteral] or no such arguments.
- ast.ListLiteral _getListLiteralNamedArgument(
- ast.Annotation node, List<String> names) {
- for (final name in names) {
- // ignore: omit_local_variable_types
- final ast.Expression expression = getNamedArgument(node, name);
- if (expression != null) {
- return expression is ast.ListLiteral ? expression : null;
- }
- }
- return null;
- }
-
- /// Find all fields labeled with @ContentChild and the ranges of the type
- /// argument. We will use this to create an unlinked summary which can, at link
- /// time, check for errors and highlight the correct range. This is all we need
- /// from the AST itself, so all we should do here.
- void _parseContentChilds(
- ast.ClassDeclaration node,
- List<ContentChildField> contentChilds,
- List<ContentChildField> contentChildrens) {
- for (final member in node.members) {
- for (final annotation in member.metadata) {
- List<ContentChildField> targetList;
- if (isAngularAnnotation(annotation, 'ContentChild')) {
- targetList = contentChilds;
- } else if (isAngularAnnotation(annotation, 'ContentChildren')) {
- targetList = contentChildrens;
- } else {
- continue;
- }
-
- final annotationArgs = annotation?.arguments?.arguments;
- if (annotationArgs == null) {
- // This happens for invalid dart code. Ignore
- continue;
- }
-
- if (annotationArgs.isEmpty) {
- // No need to report an error, dart does that already.
- continue;
- }
-
- final offset = annotationArgs[0].offset;
- final length = annotationArgs[0].length;
- var setterTypeOffset = member.offset; // fallback option
- var setterTypeLength = member.length; // fallback option
-
- String name;
- if (member is ast.FieldDeclaration) {
- name = member.fields.variables[0].name.toString();
-
- if (member.fields.type != null) {
- setterTypeOffset = member.fields.type.offset;
- setterTypeLength = member.fields.type.length;
- }
- } else if (member is ast.MethodDeclaration) {
- name = member.name.toString();
-
- final parameters = member.parameters?.parameters;
- if (parameters != null && parameters.isNotEmpty) {
- final parameter = parameters[0];
- if (parameter is ast.SimpleFormalParameter &&
- parameter.type != null) {
- setterTypeOffset = parameter.type.offset;
- setterTypeLength = parameter.type.length;
- }
- }
- }
-
- if (name != null) {
- targetList.add(new ContentChildField(name,
- nameRange: new SourceRange(offset, length),
- typeRange: new SourceRange(setterTypeOffset, setterTypeLength)));
- }
- }
- }
- }
-
- AngularElement _parseExportAs(ast.Annotation node) {
- // Find the "exportAs" argument.
- // ignore: omit_local_variable_types
- final ast.Expression expression = getNamedArgument(node, 'exportAs');
- if (expression == null) {
- return null;
- }
-
- // Extract its content.
- final name = getExpressionString(expression);
- if (name == null) {
- return null;
- }
-
- int offset;
- if (expression is ast.SimpleStringLiteral) {
- offset = expression.contentsOffset;
- } else {
- offset = expression.offset;
- }
- // Create a new element.
- return new AngularElementImpl(name, offset, name.length, _source);
- }
-
- /// Create a new input or output for the given class member [node] with
- /// the given `@Input` or `@Output` [annotation], and add it to the
- /// [inputElements] or [outputElements] array.
- void _parseMemberInputOrOutput(
- ast.ClassMember node,
- ast.Annotation annotation,
- List<InputElement> inputElements,
- List<OutputElement> outputElements) {
- // analyze the annotation
- final isInput = isAngularAnnotation(annotation, 'Input');
- final isOutput = isAngularAnnotation(annotation, 'Output');
- if ((!isInput && !isOutput) || annotation.arguments == null) {
- return null;
- }
-
- // analyze the class member
- PropertyAccessorElement property;
- if (node is ast.FieldDeclaration && node.fields.variables.length == 1) {
- final variable = node.fields.variables.first;
- final fieldElement = variable.declaredElement as FieldElement;
- property = isInput ? fieldElement.setter : fieldElement.getter;
- } else if (node is ast.MethodDeclaration) {
- if (isInput && node.isSetter) {
- property = node.declaredElement as PropertyAccessorElement;
- } else if (isOutput && node.isGetter) {
- property = node.declaredElement as PropertyAccessorElement;
- }
- }
-
- if (property == null) {
- errorReporter.reportErrorForOffset(
- isInput
- ? AngularWarningCode.INPUT_ANNOTATION_PLACEMENT_INVALID
- : AngularWarningCode.OUTPUT_ANNOTATION_PLACEMENT_INVALID,
- annotation.offset,
- annotation.length);
- return null;
- }
-
- final setterOffset = property.nameOffset;
- final setterLength = property.nameLength;
- final arguments = annotation.arguments.arguments;
-
- // prepare the input name
- String name;
- int nameOffset;
- int nameLength;
- if (arguments.isEmpty) {
- final propertyName = property.displayName;
- name = propertyName;
- nameOffset = property.nameOffset;
- nameLength = name.length;
- } else {
- // ignore: omit_local_variable_types
- final ast.Expression nameArgument = arguments[0];
- if (nameArgument is ast.SimpleStringLiteral) {
- name = nameArgument.value;
- nameOffset = nameArgument.contentsOffset;
- nameLength = name.length;
- } else {
- errorReporter.reportErrorForNode(
- AngularWarningCode.STRING_VALUE_EXPECTED, nameArgument);
- }
- if (name == null) {
- return null;
- }
- }
-
- if (isInput) {
- inputElements.add(new InputElement(
- name,
- nameOffset,
- nameLength,
- _source,
- property,
- new SourceRange(setterOffset, setterLength),
- _bindingTypeSynthesizer.getSetterType(property)));
- } else {
- final eventType = _bindingTypeSynthesizer.getEventType(property, name);
- outputElements.add(new OutputElement(
- name,
- nameOffset,
- nameLength,
- _source,
- property,
- new SourceRange(setterOffset, setterLength),
- eventType));
- }
- }
-
- /// Collect inputs and outputs for all class members with `@Input`
- /// or `@Output` annotations.
- void _parseMemberInputsAndOutputs(ast.ClassDeclaration node,
- List<InputElement> inputElements, List<OutputElement> outputElements) {
- for (final member in node.members) {
- for (final annotation in member.metadata) {
- _parseMemberInputOrOutput(
- member, annotation, inputElements, outputElements);
- }
- }
- }
-
- Selector _parseSelector(ast.Annotation node) {
- // Find the "selector" argument.
- // ignore: omit_local_variable_types
- final ast.Expression expression = getNamedArgument(node, 'selector');
- if (expression == null) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.ARGUMENT_SELECTOR_MISSING, node);
- return null;
- }
- // Compute the selector text. Careful! Offsets may not be valid after this,
- // however, at the moment we don't use them anyway.
- // ignore: omit_local_variable_types
- final OffsettingConstantEvaluator constantEvaluation =
- calculateStringWithOffsets(expression);
- if (constantEvaluation == null || constantEvaluation.value is! String) {
- return null;
- }
-
- final selectorStr = constantEvaluation.value as String;
- final selectorOffset = expression.offset;
- // Parse the selector text.
- try {
- final selector =
- new SelectorParser(_source, selectorOffset, selectorStr).parse();
- if (selector == null) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.CANNOT_PARSE_SELECTOR,
- expression,
- [selectorStr]);
- }
- return selector;
- } on SelectorParseError catch (e) {
- errorReporter.reportErrorForOffset(
- AngularWarningCode.CANNOT_PARSE_SELECTOR,
- e.offset,
- e.length,
- [e.message]);
- }
-
- return null;
- }
-
- /// Resolve the output getter with the given [name] in [_currentClassElement].
- /// If undefined, report a warning and return `null`.
- PropertyAccessorElement _resolveGetter(
- ast.SimpleStringLiteral literal, String name) {
- final getter =
- _currentClassElement.lookUpGetter(name, _currentClassElement.library);
- if (getter == null) {
- errorReporter.reportErrorForNode(StaticTypeWarningCode.UNDEFINED_GETTER,
- literal, [name, _currentClassElement.displayName]);
- }
- return getter;
- }
-
- /// Resolve the input setter with the given [name] in [_currentClassElement].
- /// If undefined, report a warning and return `null`.
- PropertyAccessorElement _resolveSetter(
- ast.SimpleStringLiteral literal, String name) {
- final setter =
- _currentClassElement.lookUpSetter(name, _currentClassElement.library);
- if (setter == null) {
- errorReporter.reportErrorForNode(StaticTypeWarningCode.UNDEFINED_SETTER,
- literal, [name, _currentClassElement.displayName]);
- }
- return setter;
- }
-}
diff --git a/angular_analyzer_plugin/lib/src/directive_linking.dart b/angular_analyzer_plugin/lib/src/directive_linking.dart
deleted file mode 100644
index b95276f..0000000
--- a/angular_analyzer_plugin/lib/src/directive_linking.dart
+++ /dev/null
@@ -1,965 +0,0 @@
-import 'dart:async';
-
-import 'package:analyzer/dart/ast/ast.dart'
- show SimpleIdentifier, PrefixedIdentifier, Identifier;
-import 'package:analyzer/dart/ast/standard_ast_factory.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/constant/value.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
-import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart' show SourceRange, Source;
-import 'package:angular_analyzer_plugin/errors.dart';
-import 'package:angular_analyzer_plugin/src/directive_extraction.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-import 'package:angular_analyzer_plugin/src/standard_components.dart';
-
-import 'summary/idl.dart';
-
-typedef DartType TransformSetterTypeFn(
- DartType setterType, ContentChildField field, String annotationName);
-
-class ChildDirectiveLinker implements DirectiveMatcher {
- final FileDirectiveProvider _fileDirectiveProvider;
- final FilePipeProvider _filePipeProvider;
- final ErrorReporter _errorReporter;
- final StandardAngular _standardAngular;
- final StandardHtml _standardHtml;
-
- ChildDirectiveLinker(this._fileDirectiveProvider, this._filePipeProvider,
- this._standardAngular, this._standardHtml, this._errorReporter);
-
- Future linkDirectivesAndPipes(
- List<AbstractDirective> directivesToLink,
- List<Pipe> pipesToLink,
- LibraryElement library,
- ) async {
- final scope = new LibraryScope(library);
- final exportLinker = new ExportLinker(scope, _errorReporter);
- for (final directive in directivesToLink) {
- if (directive is Component && directive.view != null) {
- // Link directive references to actual directive definition.
- await directive.view.directivesStrategy.resolve((references) async {
- for (final reference in references) {
- final referent = lookupDirectiveByName(reference, directivesToLink);
- if (referent != null) {
- directive.view.directives.add(await linkedAsChild(referent));
- } else {
- await lookupDirectiveFromLibrary(
- reference, scope, directive.view.directives);
- }
- }
- }, (constValue, sourceRange) async {
- if (constValue == null) {
- return;
- }
-
- if (constValue.toListValue() != null) {
- await _addDirectivesAndElementTagsForDartObject(
- directive.view.directives,
- constValue.toListValue(),
- sourceRange);
- }
-
- // Note: We don't have to report an error here, because if a non-list
- // was used for the directives parameter, that's a type error in the
- // analyzer.
- });
-
- // Link pipe references to actual pipe definition.
- for (final reference in directive.view.pipeReferences) {
- final referent = lookupPipeByName(reference, pipesToLink);
- if (referent != null) {
- directive.view.pipes.add(referent);
- } else {
- await lookupPipeFromLibrary(reference, scope, directive.view.pipes);
- }
- }
- }
-
- exportLinker.linkExportsFor(directive);
- if (directive is AbstractClassDirective) {
- await new InheritedMetadataLinker(directive, _fileDirectiveProvider)
- .link();
-
- await new ContentChildLinker(directive, this, _standardAngular,
- _standardHtml, _errorReporter)
- .linkContentChildren();
- }
- }
- }
-
- Future<AbstractDirective> linkedAsChild(AbstractDirective directive) async {
- if (directive is Component && directive?.view?.templateUriSource != null) {
- final source = directive.view.templateUriSource;
- directive.ngContents.addAll(
- await _fileDirectiveProvider.getHtmlNgContent(source.fullName));
- }
-
- // NOTE: Require the Exact type TemplateRef because that's what the
- // injector does.
- directive.looksLikeTemplate = directive is FunctionalDirective
- ? directive.functionElement.parameters
- .any((param) => param.type == _standardAngular.templateRef.type)
- : (directive as AbstractClassDirective).classElement.constructors.any(
- (constructor) => constructor.parameters.any(
- (param) => param.type == _standardAngular.templateRef.type));
-
- if (directive is AbstractClassDirective) {
- // Important: Link inherited metadata before content child fields, as
- // the directive may import unlinked content childs
- await new InheritedMetadataLinker(directive, _fileDirectiveProvider)
- .link();
-
- // ignore errors from linking subcomponents content childs
- final errorIgnorer =
- new ErrorReporter(new IgnoringErrorListener(), directive.source);
- await new ContentChildLinker(
- directive, this, _standardAngular, _standardHtml, errorIgnorer)
- .linkContentChildren();
- }
-
- return directive;
- }
-
- AbstractDirective lookupDirectiveByName(
- DirectiveReference reference, List<AbstractDirective> directivesToLink) {
- if (reference.prefix != "") {
- return null;
- }
- final options = directivesToLink.where((d) => d.name == reference.name);
- if (options.length == 1) {
- return options.first;
- }
- return null;
- }
-
- Future lookupDirectiveFromLibrary(DirectiveReference reference,
- LibraryScope scope, List<AbstractDirective> directives) async {
- final element = scope.lookup(
- astFactory.simpleIdentifier(
- new StringToken(TokenType.IDENTIFIER, reference.name, 0)),
- null);
-
- if (element != null && element.source != null) {
- if (element is ClassElement || element is FunctionElement) {
- final directive = await matchDirectiveByElement(element);
-
- if (directive != null) {
- directives.add(await linkedAsChild(directive));
- } else {
- _errorReporter.reportErrorForOffset(
- element is ClassElement
- ? AngularWarningCode.TYPE_IS_NOT_A_DIRECTIVE
- : AngularWarningCode.FUNCTION_IS_NOT_A_DIRECTIVE,
- reference.range.offset,
- reference.range.length,
- [element.name]);
- }
- return;
- } else if (element is PropertyAccessorElement) {
- element.variable.computeConstantValue();
- final values = element.variable.constantValue?.toListValue();
- if (values != null) {
- await _addDirectivesAndElementTagsForDartObject(
- directives, values, reference.range);
- return;
- }
-
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.TYPE_IS_NOT_A_DIRECTIVE,
- reference.range.offset,
- reference.range.length,
- [element.variable.constantValue.toString()]);
-
- return;
- }
- }
-
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.TYPE_LITERAL_EXPECTED,
- reference.range.offset,
- reference.range.length);
- }
-
- Pipe lookupPipeByName(PipeReference reference, List<Pipe> pipesToLink) {
- if (reference.prefix != '') {
- return null;
- }
- final options =
- pipesToLink.where((p) => p.classElement.name == reference.identifier);
- if (options.length == 1) {
- return options.first;
- }
- return null;
- }
-
- Future lookupPipeFromLibrary(
- PipeReference reference, LibraryScope scope, List<Pipe> pipes) async {
- final type = scope.lookup(
- astFactory.simpleIdentifier(
- new StringToken(TokenType.IDENTIFIER, reference.identifier, 0)),
- null);
- if (type != null && type.source != null) {
- if (type is ClassElement) {
- final pipe = await matchPipe(type);
-
- if (pipe != null) {
- pipes.add(pipe);
- } else {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.TYPE_IS_NOT_A_PIPE,
- reference.span.offset,
- reference.span.length,
- [type.name]);
- }
- return;
- } else if (type is PropertyAccessorElement) {
- type.variable.computeConstantValue();
- final values = type.variable.constantValue?.toListValue();
- if (values != null) {
- await _addPipesForDartObject(pipes, values, reference.span);
- return;
- }
-
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.TYPE_IS_NOT_A_PIPE,
- reference.span.offset,
- reference.span.length,
- [type.variable.constantValue.toString()]);
-
- return;
- }
- }
-
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.TYPE_LITERAL_EXPECTED,
- reference.span.offset,
- reference.span.length);
- }
-
- @override
- Future<AbstractDirective> matchDirectiveByElement(Element element) async {
- final fileDirectives = await _fileDirectiveProvider
- .getUnlinkedAngularTopLevels(element.source.fullName);
- final options = fileDirectives
- .whereType<AbstractDirective>()
- .where((d) => d.name == element.name);
-
- if (options.length == 1) {
- return options.first;
- }
-
- return null;
- }
-
- @override
- Future<Pipe> matchPipe(ClassElement clazz) async {
- final filePipes =
- await _filePipeProvider.getUnlinkedPipes(clazz.source.fullName);
- final options = filePipes.where((p) => p.classElement.name == clazz.name);
- if (options.length == 1) {
- return options.first;
- }
- return null;
- }
-
- /// Walk the given [value] and add directives into [directives].
- /// Return `true` if success, or `false` the [value] has items that don't
- /// correspond to a directive.
- Future _addDirectivesAndElementTagsForDartObject(
- List<AbstractDirective> directives,
- List<DartObject> values,
- SourceRange errorRange) async {
- for (final listItem in values) {
- final typeValue = listItem.toTypeValue();
- if (typeValue is InterfaceType && typeValue.element is ClassElement) {
- final directive = await matchDirectiveByElement(typeValue.element);
- if (directive != null) {
- directives.add(await linkedAsChild(directive));
- } else {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.TYPE_IS_NOT_A_DIRECTIVE,
- errorRange.offset,
- errorRange.length,
- [typeValue.name]);
- }
- continue;
- }
-
- final listValue = listItem.toListValue();
- if (listValue != null) {
- await _addDirectivesAndElementTagsForDartObject(
- directives, listValue, errorRange);
- continue;
- }
-
- final element = listItem.type?.element;
- if (element is FunctionElement) {
- final directive = await matchDirectiveByElement(element);
- if (directive != null) {
- directives.add(await linkedAsChild(directive));
- } else {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.FUNCTION_IS_NOT_A_DIRECTIVE,
- errorRange.offset,
- errorRange.length,
- [element.name]);
- }
- continue;
- }
-
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.TYPE_LITERAL_EXPECTED,
- errorRange.offset,
- errorRange.length,
- );
- }
- }
-
- /// Walk the given [value] and add pipes into [pipes].
- /// Return `true` if success, or `false` the [value] has items
- /// that don't correspond to a pipe.
- Future _addPipesForDartObject(
- List<Pipe> pipes, List<DartObject> values, SourceRange errorRange) async {
- for (final listItem in values) {
- final typeValue = listItem.toTypeValue();
- if (typeValue is InterfaceType && typeValue.element is ClassElement) {
- final pipe = await matchPipe(typeValue.element);
- if (pipe != null) {
- pipes.add(pipe);
- } else {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.TYPE_IS_NOT_A_PIPE,
- errorRange.offset,
- errorRange.length,
- [typeValue.name]);
- }
- } else {
- final listValue = listItem.toListValue();
- if (listValue != null) {
- await _addPipesForDartObject(pipes, listValue, errorRange);
- } else {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.TYPE_LITERAL_EXPECTED,
- errorRange.offset,
- errorRange.length,
- );
- }
- }
- }
- }
-}
-
-class ContentChildLinker {
- final AnalysisContext _context;
- final ErrorReporter _errorReporter;
- final AbstractClassDirective _directive;
- final DirectiveMatcher _directiveMatcher;
- final StandardAngular _standardAngular;
- final StandardHtml _standardHtml;
-
- final htmlTypes = new Set.from(['ElementRef', 'Element', 'HtmlElement']);
-
- ContentChildLinker(AbstractClassDirective directive, this._directiveMatcher,
- this._standardAngular, this._standardHtml, this._errorReporter)
- : _context =
- directive.classElement.enclosingElement.enclosingElement.context,
- _directive = directive;
-
- void checkQueriedTypeAssignableTo(DartType setterType, DartType annotatedType,
- ContentChildField field, String annotationName) {
- if (setterType != null && !setterType.isSupertypeOf(annotatedType)) {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY,
- field.typeRange.offset,
- field.typeRange.length,
- [field.fieldName, annotationName, annotatedType, setterType]);
- }
- }
-
- /// ConstantValue.getField() doesn't look up the inheritance tree. Rather than
- /// hardcoding the inheritance tree in our code, look up the inheritance tree
- /// until either it ends, or we find a "selector" field.
- DartObject getFieldWithInheritance(DartObject value, String field) {
- final selector = value.getField(field);
- if (selector != null) {
- return selector;
- }
-
- final _super = value.getField('(super)');
- if (_super != null) {
- return getFieldWithInheritance(_super, field);
- }
-
- return null;
- }
-
- /// See [getFieldWithInheritance]
- DartType getReadWithInheritance(DartObject value) {
- final constantVal = getFieldWithInheritance(value, 'read');
- if (constantVal.isNull) {
- return null;
- }
-
- return constantVal.toTypeValue();
- }
-
- /// See [getFieldWithInheritance]
- DartObject getSelectorWithInheritance(DartObject value) =>
- getFieldWithInheritance(value, 'selector');
-
- Future linkContentChildren() async {
- final unit = _directive.classElement.enclosingElement.enclosingElement;
- final bindingSynthesizer = new BindingTypeSynthesizer(
- _directive.classElement,
- unit.context.typeProvider,
- unit.context,
- _errorReporter);
-
- for (final childField in _directive.contentChildFields) {
- await recordContentChildOrChildren(childField, unit.library,
- bindingSynthesizer, transformSetterTypeSingular,
- annotationName: "ContentChild",
- destinationArray: _directive.contentChilds);
- }
- for (final childrenField in _directive.contentChildrenFields) {
- await recordContentChildOrChildren(childrenField, unit.library,
- bindingSynthesizer, transformSetterTypeMultiple,
- annotationName: "ContentChildren",
- destinationArray: _directive.contentChildren);
- }
- }
-
- Future recordContentChildOrChildren(
- ContentChildField field,
- LibraryElement library,
- BindingTypeSynthesizer bindingSynthesizer,
- TransformSetterTypeFn transformSetterTypeFn,
- {List<ContentChild> destinationArray,
- String annotationName}) async {
- final member =
- _directive.classElement.lookUpSetter(field.fieldName, library);
- if (member == null) {
- return;
- }
-
- final metadata = new List<ElementAnnotation>.from(member.metadata)
- ..addAll(member.variable.metadata);
- final annotations = metadata.where((annotation) =>
- annotation.element?.enclosingElement?.name == annotationName);
-
- // This can happen for invalid dart
- if (annotations.length != 1) {
- return;
- }
-
- final annotation = annotations.first;
- final annotationValue = annotation.computeConstantValue();
-
- // `constantValue.getField()` doesn't do inheritance. Do that ourself.
- final value = getSelectorWithInheritance(annotationValue);
- final read = getReadWithInheritance(annotationValue);
- final transformedType = transformSetterTypeFn(
- bindingSynthesizer.getSetterType(member), field, annotationName);
-
- if (read != null) {
- checkQueriedTypeAssignableTo(
- transformedType, read, field, '$annotationName(read: $read)');
- }
-
- if (value?.toStringValue() != null) {
- if (transformedType == _standardHtml.elementClass.type ||
- transformedType == _standardHtml.htmlElementClass.type ||
- read == _standardHtml.elementClass.type ||
- read == _standardHtml.htmlElementClass.type) {
- if (read == null) {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.CHILD_QUERY_TYPE_REQUIRES_READ,
- field.nameRange.offset,
- field.nameRange.length,
- [field.fieldName, annotationName, transformedType.name]);
- }
- destinationArray.add(new ContentChild(
- field, new LetBoundQueriedChildType(value.toStringValue(), read),
- read: read));
- return;
- }
-
- // Take the type -- except, we can't validate DI symbols via `read`.
- final setterType =
- read == null ? transformedType : _context.typeProvider.dynamicType;
-
- destinationArray.add(new ContentChild(field,
- new LetBoundQueriedChildType(value.toStringValue(), setterType),
- read: read));
- } else if (value?.toTypeValue() != null) {
- final type = value.toTypeValue();
- final referencedDirective =
- await _directiveMatcher.matchDirectiveByElement(type.element);
-
- AbstractQueriedChildType query;
- if (referencedDirective != null) {
- query = new DirectiveQueriedChildType(referencedDirective);
- } else if (htmlTypes.contains(type.element.name)) {
- query = new ElementQueriedChildType();
- } else if (type.element.name == 'TemplateRef') {
- query = new TemplateRefQueriedChildType();
- } else {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.UNKNOWN_CHILD_QUERY_TYPE,
- field.nameRange.offset,
- field.nameRange.length,
- [field.fieldName, annotationName]);
- return;
- }
-
- destinationArray.add(new ContentChild(field, query, read: read));
-
- checkQueriedTypeAssignableTo(
- transformedType, read ?? type, field, annotationName);
- } else {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.UNKNOWN_CHILD_QUERY_TYPE,
- field.nameRange.offset,
- field.nameRange.length,
- [field.fieldName, annotationName]);
- }
- }
-
- DartType transformSetterTypeMultiple(
- DartType setterType, ContentChildField field, String annotationName) {
- // construct List<Bottom>, which is a supertype of all List<T>
- // NOTE: In most languages, you'd need List<Object>, but not dart.
- final listBottom = _context.typeProvider.listType
- .instantiate([_context.typeProvider.bottomType]);
- // Temporarily check QueryList, which is deprecated, but allowed.
- // CAREFUL: QueryList may be NULL, handle that gracefully.
- final queryListBottom = _standardAngular.queryList?.type
- ?.instantiate([_context.typeProvider.bottomType]);
-
- final isList = setterType.isSupertypeOf(listBottom);
- final isQueryList =
- queryListBottom != null && setterType.isSupertypeOf(queryListBottom);
-
- if (!isList && !isQueryList) {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.CONTENT_OR_VIEW_CHILDREN_REQUIRES_LIST,
- field.typeRange.offset,
- field.typeRange.length,
- [field.fieldName, annotationName, setterType]);
-
- return _context.typeProvider.dynamicType;
- }
-
- final iterableType = _context.typeProvider.iterableType;
-
- // get T for setterTypes that extend Iterable<T>
- return _context.typeSystem
- .mostSpecificTypeArgument(setterType, iterableType);
- }
-
- DartType transformSetterTypeSingular(DartType setterType,
- ContentChildField field, String annotationName) =>
- setterType;
-}
-
-class DirectiveLinker {
- final DirectiveLinkerEnablement _directiveLinkerEnablement;
- final StandardAngular standardAngular;
-
- DirectiveLinker(this._directiveLinkerEnablement, this.standardAngular);
-
- List<ContentChildField> deserializeContentChildFields(
- List<SummarizedContentChildField> fieldSums) =>
- fieldSums
- .map((fieldSum) => new ContentChildField(fieldSum.fieldName,
- nameRange:
- new SourceRange(fieldSum.nameOffset, fieldSum.nameLength),
- typeRange:
- new SourceRange(fieldSum.typeOffset, fieldSum.typeLength)))
- .toList();
-
- List<ExportedIdentifier> deserializeExports(
- List<SummarizedExportedIdentifier> exports) =>
- exports
- .map((export) => new ExportedIdentifier(
- export.name, new SourceRange(export.offset, export.length),
- prefix: export.prefix))
- .toList();
-
- List<InputElement> deserializeInputs(
- SummarizedClassAnnotations annotations,
- ClassElement classElem,
- Source source,
- BindingTypeSynthesizer bindingSynthesizer) {
- final inputs = <InputElement>[];
- for (final inputSum in annotations.inputs) {
- // is this correct lookup?
- final setter =
- classElem.lookUpSetter(inputSum.propName, classElem.library);
- if (setter == null) {
- continue;
- }
- inputs.add(new InputElement(
- inputSum.name,
- inputSum.nameOffset,
- inputSum.name.length,
- source,
- setter,
- new SourceRange(inputSum.propNameOffset, inputSum.propName.length),
- bindingSynthesizer
- .getSetterType(setter))); // Don't think type is correct
- }
-
- return inputs;
- }
-
- List<NgContent> deserializeNgContents(
- List<SummarizedNgContent> ngContentSums, Source source) =>
- ngContentSums.map((ngContentSum) {
- final selector = ngContentSum.selectorStr == ""
- ? null
- : new SelectorParser(source, ngContentSum.selectorOffset,
- ngContentSum.selectorStr)
- .parse();
- return new NgContent.withSelector(
- ngContentSum.offset,
- ngContentSum.length,
- selector,
- selector?.offset,
- ngContentSum.selectorStr.length);
- }).toList();
-
- List<OutputElement> deserializeOutputs(
- SummarizedClassAnnotations annotations,
- ClassElement classElem,
- Source source,
- BindingTypeSynthesizer bindingSynthesizer) {
- final outputs = <OutputElement>[];
- for (final outputSum in annotations.outputs) {
- // is this correct lookup?
- final getter =
- classElem.lookUpGetter(outputSum.propName, classElem.library);
- if (getter == null) {
- continue;
- }
- outputs.add(new OutputElement(
- outputSum.name,
- outputSum.nameOffset,
- outputSum.name.length,
- source,
- getter,
- new SourceRange(outputSum.propNameOffset, outputSum.propName.length),
- bindingSynthesizer.getEventType(getter, getter.name)));
- }
-
- return outputs;
- }
-
- List<PipeReference> deserializePipes(List<SummarizedPipesUse> pipesUse) =>
- pipesUse
- .map((pipeUse) => new PipeReference(
- pipeUse.name, new SourceRange(pipeUse.offset, pipeUse.length),
- prefix: pipeUse.prefix))
- .toList();
-
- Future<List<AngularTopLevel>> resynthesizeDirectives(
- UnlinkedDartSummary unlinked, String path) async {
- if (unlinked == null) {
- return [];
- }
-
- final unit = await _directiveLinkerEnablement.getUnit(path);
-
- final source = unit.source;
-
- final annotatedClasses = <AngularTopLevel>[];
-
- for (final dirSum in unlinked.directiveSummaries) {
- final selector =
- new SelectorParser(source, dirSum.selectorOffset, dirSum.selectorStr)
- .parse();
- final elementTags = <ElementNameSelector>[];
- selector.recordElementNameSelectors(elementTags);
- if (dirSum.functionName != "") {
- assert(dirSum.classAnnotations == null);
- assert(dirSum.exportAs == "");
- assert(dirSum.isComponent == false);
- final functionElem =
- unit.functions.singleWhere((f) => f.name == dirSum.functionName);
- annotatedClasses
- .add(new FunctionalDirective(functionElem, selector, elementTags));
- continue;
- }
- final classElem = unit.getType(dirSum.classAnnotations.className);
- final bindingSynthesizer = new BindingTypeSynthesizer(
- classElem,
- unit.context.typeProvider,
- unit.context,
- new ErrorReporter(new IgnoringErrorListener(), unit.source));
- final exportAs = dirSum.exportAs == ""
- ? null
- : new AngularElementImpl(dirSum.exportAs, dirSum.exportAsOffset,
- dirSum.exportAs.length, source);
- final inputs = deserializeInputs(
- dirSum.classAnnotations, classElem, source, bindingSynthesizer);
- final outputs = deserializeOutputs(
- dirSum.classAnnotations, classElem, source, bindingSynthesizer);
- final contentChildFields = deserializeContentChildFields(
- dirSum.classAnnotations.contentChildFields);
- final contentChildrenFields = deserializeContentChildFields(
- dirSum.classAnnotations.contentChildrenFields);
- if (dirSum.isComponent) {
- final ngContents = deserializeNgContents(dirSum.ngContents, source);
- final exports = deserializeExports(dirSum.exports);
- final pipeRefs = deserializePipes(dirSum.pipesUse);
- final component = new Component(classElem,
- exportAs: exportAs,
- selector: selector,
- inputs: inputs,
- outputs: outputs,
- isHtml: false,
- ngContents: ngContents,
- elementTags: elementTags,
- contentChildFields: contentChildFields,
- contentChildrenFields: contentChildrenFields);
- annotatedClasses.add(component);
- final subDirectives = <DirectiveReference>[];
- for (final useSum in dirSum.subdirectives) {
- subDirectives.add(new DirectiveReference(useSum.name, useSum.prefix,
- new SourceRange(useSum.offset, useSum.length)));
- }
- Source templateUriSource;
- SourceRange templateUrlRange;
- if (dirSum.templateUrl != '') {
- templateUriSource =
- _directiveLinkerEnablement.getSource(dirSum.templateUrl);
- templateUrlRange = new SourceRange(
- dirSum.templateUrlOffset, dirSum.templateUrlLength);
- }
- component.view = new View(classElem, component, [], [],
- templateText: dirSum.templateText,
- templateOffset: dirSum.templateOffset,
- templateUriSource: templateUriSource,
- templateUrlRange: templateUrlRange,
- directivesStrategy: dirSum.usesArrayOfDirectiveReferencesStrategy
- ? new ArrayOfDirectiveReferencesStrategy(subDirectives)
- : new UseConstValueStrategy(
- classElem,
- standardAngular,
- new SourceRange(dirSum.constDirectiveStrategyOffset,
- dirSum.constDirectiveStrategyLength)),
- exports: exports,
- pipeReferences: pipeRefs);
- } else {
- annotatedClasses.add(new Directive(classElem,
- exportAs: exportAs,
- selector: selector,
- inputs: inputs,
- outputs: outputs,
- elementTags: elementTags,
- contentChildFields: contentChildFields,
- contentChildrenFields: contentChildrenFields));
- }
- }
-
- for (final annotations in unlinked.annotatedClasses) {
- final classElem = unit.getType(annotations.className);
- final bindingSynthesizer = new BindingTypeSynthesizer(
- classElem,
- unit.context.typeProvider,
- unit.context,
- new ErrorReporter(new IgnoringErrorListener(), unit.source));
- final inputs =
- deserializeInputs(annotations, classElem, source, bindingSynthesizer);
- final outputs = deserializeOutputs(
- annotations, classElem, source, bindingSynthesizer);
- final contentChildFields =
- deserializeContentChildFields(annotations.contentChildFields);
- final contentChildrenFields =
- deserializeContentChildFields(annotations.contentChildrenFields);
- annotatedClasses.add(new AngularAnnotatedClass(classElem,
- inputs: inputs,
- outputs: outputs,
- contentChildFields: contentChildFields,
- contentChildrenFields: contentChildrenFields));
- }
-
- return annotatedClasses;
- }
-}
-
-abstract class DirectiveLinkerEnablement {
- Source getSource(String path);
- Future<CompilationUnitElement> getUnit(String path);
-}
-
-abstract class DirectiveMatcher {
- Future<AbstractDirective> matchDirectiveByElement(Element element);
- Future<Pipe> matchPipe(ClassElement clazz);
-}
-
-class ExportLinker {
- final LibraryScope _scope;
- final ErrorReporter _errorReporter;
-
- ExportLinker(this._scope, this._errorReporter);
-
- Identifier getIdentifier(ExportedIdentifier export) => export.prefix == ''
- ? getSimpleIdentifier(export)
- : getPrefixedIdentifier(export);
-
- SimpleIdentifier getPrefixAsSimpleIdentifier(ExportedIdentifier export) =>
- astFactory.simpleIdentifier(new StringToken(
- TokenType.IDENTIFIER, export.prefix, export.span.offset));
-
- PrefixedIdentifier getPrefixedIdentifier(ExportedIdentifier export) =>
- astFactory.prefixedIdentifier(
- getPrefixAsSimpleIdentifier(export),
- new SimpleToken(
- TokenType.PERIOD, export.span.offset + export.prefix.length),
- getSimpleIdentifier(export, offset: export.prefix.length + 1));
-
- SimpleIdentifier getSimpleIdentifier(ExportedIdentifier export,
- {int offset: 0}) =>
- astFactory.simpleIdentifier(new StringToken(TokenType.IDENTIFIER,
- export.identifier, export.span.offset + offset));
-
- /// Only report false for known non-import-prefix prefixes, the rest get
- /// flagged by the dart analyzer already.
- bool hasWrongTypeOfPrefix(ExportedIdentifier export) {
- if (export.prefix == '') {
- return false;
- }
-
- final prefixElement =
- _scope.lookup(getPrefixAsSimpleIdentifier(export), null);
-
- return prefixElement != null && prefixElement is! PrefixElement;
- }
-
- void linkExportsFor(AbstractDirective directive) {
- if (directive is! Component) {
- return;
- }
-
- final component = directive as Component;
-
- if (component?.view?.exports == null) {
- return;
- }
-
- for (final export in component.view.exports) {
- if (hasWrongTypeOfPrefix(export)) {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.EXPORTS_MUST_BE_PLAIN_IDENTIFIERS,
- export.span.offset,
- export.span.length);
- continue;
- }
-
- final element = _scope.lookup(getIdentifier(export), null);
- if (element == component.classElement) {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.COMPONENTS_CANT_EXPORT_THEMSELVES,
- export.span.offset,
- export.span.length);
- continue;
- }
-
- export.element = element;
- }
- }
-}
-
-abstract class FileDirectiveProvider {
- Future<List<NgContent>> getHtmlNgContent(String path);
- Future<List<AngularTopLevel>> getUnlinkedAngularTopLevels(String path);
-}
-
-abstract class FilePipeProvider {
- Future<List<Pipe>> getUnlinkedPipes(String path);
-}
-
-class IgnoringErrorListener implements AnalysisErrorListener {
- @override
- void onError(Object o) {}
-}
-
-class InheritedMetadataLinker {
- AbstractClassDirective directive;
- FileDirectiveProvider _fileDirectiveProvider;
- BindingTypeSynthesizer bindingSynthesizer;
-
- InheritedMetadataLinker(this.directive, this._fileDirectiveProvider)
- : bindingSynthesizer = new BindingTypeSynthesizer(
- directive.classElement,
- directive.classElement.library.definingCompilationUnit.context
- .typeProvider,
- directive.classElement.library.definingCompilationUnit.context,
- new ErrorReporter(new IgnoringErrorListener(), directive.source));
-
- Future link() async {
- for (final supertype in directive.classElement.allSupertypes) {
- final result = await _fileDirectiveProvider
- .getUnlinkedAngularTopLevels(supertype.element.source.fullName);
- final match = result.firstWhere(
- (c) =>
- c is AngularAnnotatedClass && c.classElement == supertype.element,
- orElse: () => null);
-
- if (match == null) {
- continue;
- }
-
- directive.inputs.addAll(match.inputs.map(reresolveInput));
- directive.outputs.addAll(match.outputs.map(reresolveOutput));
- directive.contentChildFields.addAll(match.contentChildFields);
- directive.contentChildrenFields.addAll(match.contentChildrenFields);
- }
- }
-
- InputElement reresolveInput(InputElement input) {
- final setter = directive.classElement
- .lookUpSetter(input.setter.displayName, directive.classElement.library);
- if (setter == null) {
- // Happens when an interface with an input isn't implemented correctly.
- // This will be accompanied by a dart error, so we can just return the
- // original without transformation to prevent cascading errors.
- return input;
- }
- return new InputElement(
- input.name,
- input.nameOffset,
- input.nameLength,
- input.source,
- setter,
- new SourceRange(setter.nameOffset, setter.nameLength),
- bindingSynthesizer.getSetterType(setter));
- }
-
- OutputElement reresolveOutput(OutputElement output) {
- final getter = directive.classElement
- .lookUpGetter(output.getter.name, directive.classElement.library);
- if (getter == null) {
- // Happens when an interface with an output isn't implemented correctly.
- // This will be accompanied by a dart error, so we can just return the
- // original without transformation to prevent cascading errors.
- return output;
- }
- return new OutputElement(
- output.name,
- output.nameOffset,
- output.nameLength,
- output.source,
- getter,
- new SourceRange(getter.nameOffset, getter.nameLength),
- bindingSynthesizer.getEventType(getter, output.name));
- }
-}
diff --git a/angular_analyzer_plugin/lib/src/file_tracker.dart b/angular_analyzer_plugin/lib/src/file_tracker.dart
deleted file mode 100644
index 11f7c32..0000000
--- a/angular_analyzer_plugin/lib/src/file_tracker.dart
+++ /dev/null
@@ -1,205 +0,0 @@
-import 'dart:async';
-import 'dart:collection';
-
-import 'package:analyzer/src/summary/api_signature.dart';
-import 'package:angular_analyzer_plugin/src/options.dart';
-
-abstract class FileHasher {
- ApiSignature getContentHash(String path);
- Future<String> getUnitElementSignature(String path);
-}
-
-class FileTracker {
- static const int salt = 5;
-
- final FileHasher _fileHasher;
- final AngularOptions _options;
-
- final _dartToDart = new _RelationshipTracker();
-
- final _dartToHtml = new _RelationshipTracker();
- final _dartFilesWithDartTemplates = new HashSet<String>();
-
- final contentHashes = <String, _FileHash>{};
-
- FileTracker(this._fileHasher, this._options);
-
- /// Add tag names to the signature. Note: in the future when there are more
- /// lists of strings in options to add, we must be careful that they are
- /// properly delimited/differentiated!
- void addCustomEvents(ApiSignature signature) {
- final hashString = _options.customEventsHashString;
- if (hashString != null && hashString.isNotEmpty) {
- signature.addString(hashString);
- }
- }
-
- /// Add tag names to the signature. Note: in the future when there are more
- /// lists of strings in options to add, we must be careful that they are
- /// properly delimited/differentiated!
- void addTags(ApiSignature signature) {
- for (final tagname in _options.customTagNames) {
- signature.addString('t:$tagname');
- }
- }
-
- ApiSignature getContentSignature(String path) {
- if (contentHashes[path] == null) {
- rehashContents(path);
- }
- return contentHashes[path].saltedSignature;
- }
-
- // ignore: avoid_positional_boolean_parameters
- List<String> getDartPathsAffectedByHtml(String htmlPath) => _dartToHtml
- .getFilesReferencingFile(htmlPath)
- .map(_dartToDart.getFilesReferencingFile)
- .fold<List<String>>(<String>[], (list, acc) => list..addAll(acc))
- .where(_dartFilesWithDartTemplates.contains)
- .toList();
-
- List<String> getDartPathsReferencingHtml(String htmlPath) =>
- _dartToHtml.getFilesReferencingFile(htmlPath);
-
- Future<ApiSignature> getDartSignature(String dartPath) async {
- final signature = new ApiSignature()
- ..addInt(salt)
- ..addString(await _fileHasher.getUnitElementSignature(dartPath));
- for (final htmlPath in getHtmlPathsAffectingDart(dartPath)) {
- signature.addBytes(_getContentHash(htmlPath));
- }
-
- // Note, options which affect ng-content extraction should not be hashed
- // here. Those should be hashed into ContentSignature.
- addTags(signature);
- addCustomEvents(signature);
-
- return signature;
- }
-
- List<String> getHtmlPathsAffectingDart(String dartPath) {
- if (_dartFilesWithDartTemplates.contains(dartPath)) {
- return getHtmlPathsAffectingDartContext(dartPath);
- }
-
- return [];
- }
-
- List<String> getHtmlPathsAffectingDartContext(String dartPath) => _dartToDart
- .getFilesReferencedBy(dartPath)
- .map(_dartToHtml.getFilesReferencedBy)
- .fold<List<String>>(
- <String>[], (list, acc) => list..addAll(acc)).toList();
-
- List<String> getHtmlPathsReferencedByDart(String dartPath) =>
- _dartToHtml.getFilesReferencedBy(dartPath);
-
- List<String> getHtmlPathsReferencingHtml(String htmlPath) => _dartToHtml
- .getFilesReferencingFile(htmlPath)
- .map(_dartToDart.getFilesReferencingFile)
- .fold<List<String>>(<String>[], (list, acc) => list..addAll(acc))
- .map(_dartToHtml.getFilesReferencedBy)
- .fold<List<String>>(<String>[], (list, acc) => list..addAll(acc))
- .toList();
-
- Future<ApiSignature> getHtmlSignature(String htmlPath) async {
- final signature = new ApiSignature()
- ..addInt(salt)
- ..addBytes(_getContentHash(htmlPath));
- for (final dartPath in getDartPathsReferencingHtml(htmlPath)) {
- signature.addString(await _fileHasher.getUnitElementSignature(dartPath));
- for (final subHtmlPath in getHtmlPathsAffectingDartContext(dartPath)) {
- signature.addBytes(_getContentHash(subHtmlPath));
- }
- }
-
- // Note, options which affect directive/view extraction should not be hashed
- // here. Those should probably be hashed into ElementSignature.
- addTags(signature);
- addCustomEvents(signature);
-
- return signature;
- }
-
- Future<ApiSignature> getUnitElementSignature(String path) async =>
- new ApiSignature()
- ..addInt(salt)
- ..addString(await _fileHasher.getUnitElementSignature(path));
-
- void rehashContents(String path) {
- final signature = _fileHasher.getContentHash(path);
- final bytes = signature.toByteList();
- contentHashes[path] = new _FileHash(
- bytes,
- new ApiSignature()
- ..addInt(salt)
- ..addBytes(bytes));
- }
-
- void setDartHasTemplate(String dartPath, bool hasTemplate) {
- if (hasTemplate) {
- _dartFilesWithDartTemplates.add(dartPath);
- } else {
- _dartFilesWithDartTemplates.remove(dartPath);
- }
- }
-
- void setDartHtmlTemplates(String dartPath, List<String> htmlPaths) =>
- _dartToHtml.setFileReferencesFiles(dartPath, htmlPaths);
-
- void setDartImports(String dartPath, List<String> imports) {
- _dartToDart.setFileReferencesFiles(dartPath, imports);
- }
-
- List<int> _getContentHash(String path) {
- if (contentHashes[path] == null) {
- rehashContents(path);
- }
- return contentHashes[path].unsaltedBytes;
- }
-}
-
-class _FileHash {
- final List<int> unsaltedBytes;
- final ApiSignature saltedSignature;
-
- _FileHash(this.unsaltedBytes, this.saltedSignature);
-}
-
-class _RelationshipTracker {
- final _filesReferencedByFile = <String, List<String>>{};
- final _filesReferencingFile = <String, List<String>>{};
-
- List<String> getFilesReferencedBy(String filePath) =>
- _filesReferencedByFile[filePath] ?? [];
-
- List<String> getFilesReferencingFile(String usesPath) =>
- _filesReferencingFile[usesPath] ?? [];
-
- void setFileReferencesFiles(String filePath, List<String> referencesPaths) {
- final priorRelationships = new HashSet<String>();
- if (_filesReferencedByFile.containsKey(filePath)) {
- for (final referencesPath in _filesReferencedByFile[filePath]) {
- if (!referencesPaths.contains(referencesPath)) {
- _filesReferencingFile[referencesPath].remove(filePath);
- } else {
- priorRelationships.add(referencesPath);
- }
- }
- }
-
- _filesReferencedByFile[filePath] = referencesPaths;
-
- for (final referencesPath in referencesPaths) {
- if (priorRelationships.contains(referencesPath)) {
- continue;
- }
-
- if (!_filesReferencingFile.containsKey(referencesPath)) {
- _filesReferencingFile[referencesPath] = [filePath];
- } else {
- _filesReferencingFile[referencesPath].add(filePath);
- }
- }
- }
-}
diff --git a/angular_analyzer_plugin/lib/src/from_file_prefixed_error.dart b/angular_analyzer_plugin/lib/src/from_file_prefixed_error.dart
deleted file mode 100644
index c5df49f..0000000
--- a/angular_analyzer_plugin/lib/src/from_file_prefixed_error.dart
+++ /dev/null
@@ -1,69 +0,0 @@
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-// A wrapper around AnalysisError which also links back to a "from" file and
-// classname for context.
-//
-// Is a wrapper, not just an extension, so that it can have a different hashCode
-// than the error without a "from" path, in the case that a file is included
-// both sanely and strangely (which is common: prod and test).
-class FromFilePrefixedError implements AnalysisError {
- final String fromSourcePath;
- final String classname;
- final String originalMessage;
- final AnalysisError originalError;
- String _message;
-
- FromFilePrefixedError(
- Source fromSource, String classname, AnalysisError originalError)
- : this.fromPath(fromSource.fullName, classname, originalError);
-
- FromFilePrefixedError.fromPath(
- this.fromSourcePath, this.classname, AnalysisError originalError)
- : originalMessage = originalError.message,
- originalError = originalError,
- assert(classname != null),
- assert(classname.isNotEmpty),
- assert(fromSourcePath != null),
- assert(fromSourcePath.isNotEmpty) {
- _message = "In $classname: $originalMessage (from $fromSourcePath)";
- }
-
- @override
- String get correction => originalError.correction;
-
- @override
- ErrorCode get errorCode => originalError.errorCode;
-
- @override
- int get hashCode {
- var hashCode = offset;
- hashCode ^= (_message != null) ? _message.hashCode : 0;
- hashCode ^= (source != null) ? source.hashCode : 0;
- return hashCode;
- }
-
- @override
- bool get isStaticOnly => originalError.isStaticOnly;
-
- @override
- set isStaticOnly(bool v) => originalError.isStaticOnly = v;
-
- @override
- int get length => originalError.length;
-
- @override
- set length(int v) => originalError.length = v;
-
- @override
- String get message => _message;
-
- @override
- int get offset => originalError.offset;
-
- @override
- set offset(int v) => originalError.offset = v;
-
- @override
- Source get source => originalError.source;
-}
diff --git a/angular_analyzer_plugin/lib/src/ignoring_error_listener.dart b/angular_analyzer_plugin/lib/src/ignoring_error_listener.dart
deleted file mode 100644
index 3b6fe4b..0000000
--- a/angular_analyzer_plugin/lib/src/ignoring_error_listener.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-
-class IgnoringAnalysisErrorListener implements AnalysisErrorListener {
- @override
- void onError(AnalysisError error) {}
-}
diff --git a/angular_analyzer_plugin/lib/src/model.dart b/angular_analyzer_plugin/lib/src/model.dart
deleted file mode 100644
index 3aa6e56..0000000
--- a/angular_analyzer_plugin/lib/src/model.dart
+++ /dev/null
@@ -1,754 +0,0 @@
-library angular2.src.analysis.analyzer_plugin.src.model;
-
-import 'dart:collection';
-
-import 'package:analyzer/dart/ast/ast.dart' as dart;
-import 'package:analyzer/dart/element/element.dart' as dart;
-import 'package:analyzer/dart/element/type.dart' as dart;
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/source.dart' show Source, SourceRange;
-import 'package:analyzer/src/generated/utilities_general.dart';
-import 'package:angular_analyzer_plugin/ast.dart';
-import 'package:angular_analyzer_plugin/errors.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-import 'package:angular_analyzer_plugin/src/standard_components.dart';
-
-abstract class AbstractClassDirective extends AngularAnnotatedClass
- implements AbstractDirective {
- @override
- final Selector selector;
-
- @override
- final AngularElement exportAs;
-
- @override
- final List<ElementNameSelector> elementTags;
-
- AbstractClassDirective(dart.ClassElement classElement,
- {this.exportAs,
- List<InputElement> inputs,
- List<OutputElement> outputs,
- this.selector,
- this.elementTags,
- List<ContentChildField> contentChildFields,
- List<ContentChildField> contentChildrenFields})
- : super(classElement,
- inputs: inputs,
- outputs: outputs,
- contentChildFields: contentChildFields,
- contentChildrenFields: contentChildrenFields);
-
- @override
- String get name => classElement.name;
-}
-
-abstract class AbstractDirective extends AngularTopLevel {
- List<ElementNameSelector> get elementTags;
-
- AngularElement get exportAs;
-
- String get name;
-
- Selector get selector;
-}
-
-abstract class AbstractQueriedChildType {
- bool match(ElementInfo element, StandardAngular angular,
- StandardHtml standardHtml, ErrorReporter reporter);
-}
-
-/// Might be a directive, or a component, or neither. It might simply have
-/// annotated @Inputs, @Outputs() intended to be inherited.
-class AngularAnnotatedClass extends AngularTopLevel {
- /// The [ClassElement] this annotation is associated with.
- final dart.ClassElement classElement;
-
- @override
- final contentChilds = <ContentChild>[];
-
- @override
- final contentChildren = <ContentChild>[];
-
- /// Which fields have been marked `@ContentChild`, and the range of the type
- /// argument. The element model contains the rest. This should be stored in the
- /// summary, so that at link time we can report errors discovered in the model
- /// against the range we saw it the AST.
- @override
- List<ContentChildField> contentChildrenFields;
-
- @override
- List<ContentChildField> contentChildFields;
-
- AngularAnnotatedClass(this.classElement,
- {List<InputElement> inputs,
- List<OutputElement> outputs,
- this.contentChildFields,
- this.contentChildrenFields})
- : super(inputs: inputs, outputs: outputs);
-
- @override
- int get hashCode => classElement.hashCode;
-
- // See [contentChildrenFields]. These are the linked versions.
- @override
- bool get isHtml => false;
-
- /// The source that contains this directive.
- @override
- Source get source => classElement.source;
-
- @override
- bool operator ==(Object other) =>
- other is AngularAnnotatedClass && other.classElement == classElement;
- @override
- String toString() => '$runtimeType(${classElement.displayName} '
- 'inputs=$inputs '
- 'outputs=$outputs '
- 'attributes=$attributes)';
-}
-
-/// The base class for all Angular elements.
-abstract class AngularElement {
- dart.CompilationUnitElement get compilationElement;
-
- /// Return the name of this element, not `null`.
- String get name;
-
- /// Return the length of the name of this element in the file that contains
- /// the declaration of this element.
- int get nameLength;
-
- /// Return the offset of the name of this element in the file that contains
- /// the declaration of this element.
- int get nameOffset;
-
- /// Return the [Source] of this element.
- Source get source;
-}
-
-/// The base class for concrete implementations of an [AngularElement].
-class AngularElementImpl implements AngularElement {
- @override
- final String name;
-
- @override
- final int nameOffset;
-
- @override
- final int nameLength;
-
- @override
- final Source source;
-
- AngularElementImpl(this.name, this.nameOffset, this.nameLength, this.source);
-
- @override
- dart.CompilationUnitElement get compilationElement => null;
-
- @override
- int get hashCode => JenkinsSmiHash.hash4(
- name.hashCode, nameOffset ?? -1, nameLength ?? -1, source.hashCode);
-
- @override
- bool operator ==(Object other) =>
- other is AngularElement &&
- other.runtimeType == runtimeType &&
- other.nameOffset == nameOffset &&
- other.nameLength == nameLength &&
- other.name == name &&
- other.source == source;
-
- @override
- String toString() => name;
-}
-
-/// An abstract model of an Angular top level construct.
-///
-/// This may be a functional directive, component, or normal directive...or even
-/// an [AngularAnnotatedClass] which is a class that defines component/directive
-/// behavior for the sake of being inherited.
-abstract class AngularTopLevel {
- final attributes = <AngularElement>[];
-
- /// Its very hard to tell which directives are meant to be used with a *star.
- /// However, any directives which have a `TemplateRef` as a constructor
- /// parameter are almost certainly meant to be used with one. We use this for
- /// whatever validation we can, and autocomplete suggestions.
- bool looksLikeTemplate = false;
- final List<InputElement> inputs;
-
- final List<OutputElement> outputs;
-
- AngularTopLevel({
- this.inputs,
- this.outputs,
- });
- List<ContentChildField> get contentChildFields;
-
- List<ContentChild> get contentChildren;
-
- /// See [AngularAnnotatedClassMembers.contentChildrenFields]
- List<ContentChildField> get contentChildrenFields;
-
- /// See [AngularAnnotatedClassMembers.contentChildren]
- List<ContentChild> get contentChilds;
- bool get isHtml;
-
- Source get source;
-}
-
-class ArrayOfDirectiveReferencesStrategy implements DirectivesStrategy {
- final List<DirectiveReference> directiveReferences;
-
- ArrayOfDirectiveReferencesStrategy(this.directiveReferences);
-
- @override
- T resolve<T>(T Function(List<DirectiveReference>) arrayStrategyHandler,
- T Function(Null, Null) _) =>
- arrayStrategyHandler(directiveReferences);
-}
-
-/// The model of an Angular component.
-class Component extends AbstractClassDirective {
- View view;
- @override
- final bool isHtml;
-
- /// List of <ng-content> selectors in this component's view
- final ngContents = <NgContent>[];
-
- Component(dart.ClassElement classElement,
- {AngularElement exportAs,
- List<InputElement> inputs,
- List<OutputElement> outputs,
- Selector selector,
- List<ElementNameSelector> elementTags,
- this.isHtml,
- List<NgContent> ngContents,
- List<Pipe> pipes,
- List<ContentChildField> contentChildFields,
- List<ContentChildField> contentChildrenFields})
- : super(classElement,
- exportAs: exportAs,
- inputs: inputs,
- outputs: outputs,
- selector: selector,
- elementTags: elementTags,
- contentChildFields: contentChildFields,
- contentChildrenFields: contentChildrenFields) {
- this.ngContents.addAll(ngContents ?? []);
- }
-
- List<ExportedIdentifier> get exports => view?.exports ?? [];
-}
-
-// Represents both Element and HtmlElement, since the difference between them
-// is SVG which we don't yet analyze. Also represent ElementRef which will soon
-// be deprecated/removed.
-class ContentChild {
- final ContentChildField field;
- final AbstractQueriedChildType query;
-
- /// Look up a symbol from the injector. We don't track the injector yet.
- final dart.DartType read;
-
- ContentChild(this.field, this.query, {this.read});
-}
-
-class ContentChildField {
- final String fieldName;
- final SourceRange nameRange;
- final SourceRange typeRange;
-
- ContentChildField(this.fieldName, {this.nameRange, this.typeRange});
-}
-
-/// An [AngularElement] representing a [dart.Element].
-class DartElement extends AngularElementImpl {
- final dart.Element element;
-
- DartElement(dart.Element element)
- : element = element,
- super(element.name, element.nameOffset, element.nameLength,
- element.source);
-
- @override
- dart.CompilationUnitElement get compilationElement =>
- element.getAncestor((e) => e is dart.CompilationUnitElement);
-}
-
-/// The model of an Angular directive.
-class Directive extends AbstractClassDirective {
- Directive(dart.ClassElement classElement,
- {AngularElement exportAs,
- List<InputElement> inputs,
- List<OutputElement> outputs,
- Selector selector,
- List<ElementNameSelector> elementTags,
- List<ContentChildField> contentChildFields,
- List<ContentChildField> contentChildrenFields})
- : super(classElement,
- exportAs: exportAs,
- inputs: inputs,
- outputs: outputs,
- selector: selector,
- elementTags: elementTags,
- contentChildFields: contentChildFields,
- contentChildrenFields: contentChildrenFields);
-
- @override
- bool get isHtml => false;
-}
-
-class DirectiveQueriedChildType extends AbstractQueriedChildType {
- final AbstractDirective directive;
- DirectiveQueriedChildType(this.directive);
- @override
- bool match(NodeInfo element, StandardAngular _, StandardHtml __,
- ErrorReporter ___) =>
- element is ElementInfo &&
- element.directives.any((boundDirective) => boundDirective == directive);
-}
-
-class DirectiveReference {
- String name;
- String prefix;
- SourceRange range;
-
- DirectiveReference(this.name, this.prefix, this.range);
-}
-
-abstract class DirectivesStrategy {
- // A low-level sort of visitor strategy.
- T resolve<T>(T Function(List<DirectiveReference>) arrayStrategyHandler,
- T Function(DartObject, SourceRange) constStrategyHandler);
-}
-
-class ElementQueriedChildType extends AbstractQueriedChildType {
- @override
- bool match(NodeInfo element, StandardAngular _, StandardHtml __,
- ErrorReporter ___) =>
- element is ElementInfo &&
- element.localName != 'template' &&
- !element.directives.any((boundDirective) =>
- boundDirective is Component && !boundDirective.isHtml);
-}
-
-class ExportedIdentifier {
- final String prefix;
- final String identifier;
- final SourceRange span;
- dart.Element element;
-
- ExportedIdentifier(this.identifier, this.span,
- {this.element, this.prefix: ''});
-
- @override
- String toString() => '{$prefix, $identifier}';
-}
-
-/// A functional directive is applied when the directive is linked, but does
-/// nothing later in the program. Thus it cannot have inputs, outputs, etc. But
-/// for the sake of clean code, those methods are implemented to return null,
-/// empty list, etc.
-class FunctionalDirective implements AbstractDirective {
- final dart.FunctionElement functionElement;
- @override
- final Selector selector;
- @override
- final List<ElementNameSelector> elementTags;
-
- /// @See [AbstractSelectable.looksLikeTemplate]
- @override
- bool looksLikeTemplate = false;
-
- FunctionalDirective(this.functionElement, this.selector, this.elementTags);
-
- @override
- List<AngularElement> get attributes => const [];
- @override
- List<ContentChildField> get contentChildFields => const [];
- @override
- List<ContentChild> get contentChildren => const [];
- @override
- List<ContentChildField> get contentChildrenFields => const [];
- @override
- List<ContentChild> get contentChilds => const [];
- @override
- AngularElement get exportAs => null;
- @override
- int get hashCode => functionElement.hashCode;
- @override
- List<InputElement> get inputs => const [];
- @override
- bool get isHtml => false;
-
- @override
- String get name => functionElement.name;
-
- @override
- List<OutputElement> get outputs => const [];
-
- /// The source that contains this directive.
- @override
- Source get source => functionElement.source;
-
- @override
- bool operator ==(Object other) =>
- other is FunctionalDirective && other.functionElement == functionElement;
-
- @override
- String toString() => 'FunctionalDirective(${functionElement.displayName} '
- 'selector=$selector ';
-}
-
-/// An Angular template in an HTML file.
-class HtmlTemplate extends Template {
- /// The [Source] of the template.
- final Source source;
-
- HtmlTemplate(View view, this.source) : super(view);
-}
-
-/// The model for an Angular input.
-class InputElement extends AngularElementImpl {
- final dart.PropertyAccessorElement setter;
-
- final dart.DartType setterType;
-
- /// The [SourceRange] where [setter] is referenced in the input declaration.
- /// May be the same as this element offset/length in shorthand variants where
- /// names of a input and the setter are the same.
- final SourceRange setterRange;
-
- /// A given input can have an alternative name, or more 'conventional' name
- /// that differs from the name provided by dart:html source.
- /// For example: source -> 'className', but prefer 'class'.
- /// In this case, name = 'class' and originalName = 'originalName'.
- /// This should be null if there is no alternative name.
- final String originalName;
-
- /// Native inputs vulnerable to XSS (such as a.href and *.innerHTML) may have
- /// a security context. The secure type of that context should be assignable
- /// to this input, and if the security context does not allow sanitization
- /// then it will always throw otherwise and thus should be treated as an
- /// assignment error.
- final SecurityContext securityContext;
-
- InputElement(String name, int nameOffset, int nameLength, Source source,
- this.setter, this.setterRange, this.setterType,
- {this.originalName, this.securityContext})
- : super(name, nameOffset, nameLength, source);
-
- @override
- String toString() => 'InputElement($name, $nameOffset, $nameLength, $setter)';
-}
-
-class LetBoundQueriedChildType extends AbstractQueriedChildType {
- final String letBoundName;
- final dart.DartType containerType;
- LetBoundQueriedChildType(this.letBoundName, this.containerType);
- @override
- bool match(NodeInfo element, StandardAngular angular,
- StandardHtml standardHtml, ErrorReporter errorReporter) =>
- element is ElementInfo &&
- element.attributes.any((attribute) {
- if (attribute is TextAttribute && attribute.name == '#$letBoundName') {
- _validateMatch(
- element, attribute, angular, standardHtml, errorReporter);
- return true;
- }
- return false;
- });
-
- /// Validate against a matching [TextAttribute] on a matching [ElementInfo],
- /// for assignability to [containerType] errors.
- void _validateMatch(
- ElementInfo element,
- TextAttribute attr,
- StandardAngular angular,
- StandardHtml standardHtml,
- ErrorReporter errorReporter) {
- // For Html, the possible match types is plural. So use a list in all cases
- // instead of a single value for most and then have some exceptional code.
- final matchTypes = <dart.DartType>[];
-
- if (attr.value != "" && attr.value != null) {
- final possibleDirectives = new List<AbstractClassDirective>.from(
- element.directives.where((d) =>
- d.exportAs.name == attr.value &&
- d is AbstractClassDirective)); // No functional directives
- if (possibleDirectives.isEmpty || possibleDirectives.length > 1) {
- // Don't validate based on an invalid state (that's reported as such).
- return;
- }
- // TODO instantiate this type to bounds
- matchTypes.add(possibleDirectives.first.classElement.type);
- } else if (element.localName == 'template') {
- matchTypes.add(angular.templateRef.type);
- } else {
- final possibleComponents = new List<Component>.from(
- element.directives.where((d) => d is Component && !d.isHtml));
- if (possibleComponents.length > 1) {
- // Don't validate based on an invalid state (that's reported as such).
- return;
- }
-
- if (possibleComponents.isEmpty) {
- // TODO differentiate between SVG (Element) and HTML (HtmlElement)
- matchTypes
- ..add(angular.elementRef.type)
- ..add(standardHtml.elementClass.type)
- ..add(standardHtml.htmlElementClass.type);
- } else {
- // TODO instantiate this type to bounds
- matchTypes.add(possibleComponents.first.classElement.type);
- }
- }
-
- // Don't do isAssignable. Because we KNOW downcasting makes no sense here.
- if (!matchTypes.any(containerType.isSupertypeOf)) {
- errorReporter.reportErrorForOffset(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- element.offset,
- element.length,
- [letBoundName, containerType, matchTypes]);
- }
- }
-}
-
-class NgContent {
- final int offset;
- final int length;
-
- /// NOTE: May contain Null. Null in this case means no selector (all content).
- final Selector selector;
- final int selectorOffset;
- final int selectorLength;
-
- NgContent(this.offset, this.length)
- : selector = null,
- selectorOffset = null,
- selectorLength = null;
-
- NgContent.withSelector(this.offset, this.length, this.selector,
- this.selectorOffset, this.selectorLength);
-
- bool get matchesAll => selector == null;
-}
-
-/// The model for an Angular output.
-class OutputElement extends AngularElementImpl {
- final dart.PropertyAccessorElement getter;
-
- final dart.DartType eventType;
-
- /// The [SourceRange] where [getter] is referenced in the input declaration.
- /// May be the same as this element offset/length in shorthand variants where
- /// names of a input and the getter are the same.
- final SourceRange getterRange;
-
- OutputElement(String name, int nameOffset, int nameLength, Source source,
- this.getter, this.getterRange, this.eventType)
- : super(name, nameOffset, nameLength, source);
-
- @override
- String toString() =>
- 'OutputElement($name, $nameOffset, $nameLength, $getter)';
-}
-
-class Pipe {
- final String pipeName;
- final int pipeNameOffset;
- final dart.ClassElement classElement;
- final bool isPure;
-
- dart.DartType requiredArgumentType;
- dart.DartType transformReturnType;
- List<dart.DartType> optionalArgumentTypes = <dart.DartType>[];
-
- Pipe(this.pipeName, this.pipeNameOffset, this.classElement,
- {this.isPure: true});
-}
-
-class PipeReference {
- final String prefix;
- final String identifier;
- final SourceRange span;
-
- PipeReference(this.identifier, this.span, {this.prefix: ''});
-}
-
-/// A pair of an [SourceRange] and the referenced [AngularElement].
-class ResolvedRange {
- /// The [SourceRange] where [element] is referenced.
- final SourceRange range;
-
- /// The [AngularElement] referenced at [range].
- final AngularElement element;
-
- ResolvedRange(this.range, this.element);
-
- @override
- String toString() => '$range=[$element, '
- 'nameOffset=${element.nameOffset}, '
- 'nameLength=${element.nameLength}, '
- 'source=${element.source}]';
-}
-
-/// An Angular template.
-/// Templates can be embedded into Dart.
-class Template {
- /// The [View] that describes the template.
- final View view;
-
- /// The [ResolvedRange]s of the template.
- final ranges = <ResolvedRange>[];
-
- /// The [ElementInfo] that begins the AST of the resolved template
- ElementInfo _ast;
-
- /// The errors that are ignored in this template
- final ignoredErrors = new HashSet<String>();
-
- Template(this.view);
-
- ElementInfo get ast => _ast;
-
- set ast(ElementInfo ast) {
- if (_ast != null) {
- throw new StateError("AST is already set, shouldn't be set again");
- }
-
- _ast = ast;
- }
-
- /// Records that the given [element] is referenced at the given [range].
- void addRange(SourceRange range, AngularElement element) {
- assert(range != null);
- assert(range.offset != null);
- assert(range.offset >= 0);
- ranges.add(new ResolvedRange(range, element));
- }
-
- @override
- String toString() => 'Template(ranges=$ranges)';
-}
-
-class TemplateRefQueriedChildType extends AbstractQueriedChildType {
- @override
- bool match(NodeInfo element, StandardAngular _, StandardHtml __,
- ErrorReporter ___) =>
- element is ElementInfo && element.localName == 'template';
-}
-
-class UseConstValueStrategy implements DirectivesStrategy {
- final dart.ClassElement annotatedObject;
- final StandardAngular standardAngular;
- final SourceRange sourceRange;
-
- UseConstValueStrategy(
- this.annotatedObject, this.standardAngular, this.sourceRange) {
- assert(standardAngular != null);
- }
-
- @override
- T resolve<T>(T Function(Null) _,
- T Function(DartObject, SourceRange) constStrategyHandler) =>
- constStrategyHandler(
- annotatedObject.metadata
- .where((m) => _isComponent(m.element?.enclosingElement))
- .map((m) => _getDirectives(m.computeConstantValue()))
- // TODO(mfairhurst): report error for double definition
- .firstWhere((directives) => !(directives?.isNull ?? true),
- orElse: () => null),
- sourceRange);
-
- /// Traverse the inheritance hierarchy in the constant value, looking for the
- /// 'directives' field at the highest level it occurs.
- DartObject _getDirectives(DartObject value) {
- do {
- final directives = value.getField('directives');
- if (directives != null) {
- return directives;
- }
- // ignore: parameter_assignments
- value = value.getField('(super)');
- } while (value != null);
-
- return null;
- }
-
- /// Check if an element is a Component
- bool _isComponent(dart.Element element) =>
- element is dart.ClassElement &&
- element.type.isSubtypeOf(standardAngular.component.type);
-}
-
-/// The model of an Angular view.
-class View {
- /// The [ClassElement] this view is associated with.
- final dart.ClassElement classElement;
-
- final Component component;
- final List<AbstractDirective> directives;
- final List<Pipe> pipes;
- final DirectivesStrategy directivesStrategy;
- final List<PipeReference> pipeReferences;
- final String templateText;
- final int templateOffset;
- final Source templateUriSource;
- final SourceRange templateUrlRange;
- final dart.Annotation annotation;
-
- final List<ExportedIdentifier> exports;
-
- Map<String, List<AbstractDirective>> _elementTagsInfo;
-
- /// The [Template] of this view, `null` until built.
- Template template;
-
- View(this.classElement, this.component, this.directives, this.pipes,
- {this.templateText,
- this.templateOffset: 0,
- this.templateUriSource,
- this.templateUrlRange,
- this.annotation,
- this.directivesStrategy,
- this.exports,
- this.pipeReferences}) {
- // stability/error-recovery: @Component can be missing
- component?.view = this;
- }
-
- Map<String, List<AbstractDirective>> get elementTagsInfo {
- if (_elementTagsInfo == null) {
- _elementTagsInfo = <String, List<AbstractDirective>>{};
- for (final directive in directives) {
- if (directive.elementTags != null && directive.elementTags.isNotEmpty) {
- for (final elementTag in directive.elementTags) {
- final tagName = elementTag.toString();
- _elementTagsInfo.putIfAbsent(tagName, () => <AbstractDirective>[]);
- _elementTagsInfo[tagName].add(directive);
- }
- }
- }
- }
- return _elementTagsInfo;
- }
-
- int get end => templateOffset + templateText.length;
-
- /// The source that contains this view.
- Source get source => classElement.source;
-
- /// The source that contains this template, [source] or [templateUriSource].
- Source get templateSource => templateUriSource ?? source;
-
- @override
- String toString() => 'View('
- 'classElement=$classElement, '
- 'component=$component, '
- 'directives=$directives)';
-}
diff --git a/angular_analyzer_plugin/lib/src/navigation.dart b/angular_analyzer_plugin/lib/src/navigation.dart
deleted file mode 100644
index 6b82b12..0000000
--- a/angular_analyzer_plugin/lib/src/navigation.dart
+++ /dev/null
@@ -1,138 +0,0 @@
-import 'package:analyzer/dart/element/element.dart' as engine;
-import 'package:analyzer/src/dart/analysis/file_state.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
-import 'package:analyzer_plugin/protocol/protocol_constants.dart' as protocol;
-import 'package:analyzer_plugin/utilities/analyzer_converter.dart' as protocol;
-import 'package:analyzer_plugin/utilities/navigation/navigation.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/navigation_request.dart';
-
-class AngularNavigation implements NavigationContributor {
- final FileContentOverlay _contentOverlay;
-
- AngularNavigation(this._contentOverlay);
-
- @override
- void computeNavigation(
- NavigationRequest baseRequest, NavigationCollector collector,
- {bool templatesOnly: false}) {
- // cast this
- final request = baseRequest as AngularNavigationRequest;
- final length = request.length;
- final offset = request.offset;
- final result = request.result;
-
- if (result == null) {
- return;
- }
-
- final span = offset != null && length != null
- ? new SourceRange(offset, length)
- : null;
- final directives = result.directives;
- final views = directives
- .map((d) => d is Component ? d.view : null)
- .where((v) => v != null);
-
- if (!templatesOnly) {
- // special dart navigable regions
- for (final directive in directives) {
- _addDirectiveRegions(collector, directive, span);
- }
- for (final view in views) {
- _addViewRegions(collector, view, span);
- }
- }
-
- final resolvedTemplates = result.fullyResolvedDirectives
- .map((d) => d is Component ? d.view?.template : null)
- .where((v) => v != null);
- for (final template in resolvedTemplates) {
- _addTemplateRegions(collector, template, span);
- }
- }
-
- /// A null target range indicates everything is targeted. Otherwise, intersect
- bool isTargeted(SourceRange toTest, {SourceRange targetRange}) =>
- // <a><b></b></a> or <a><b></a></b>, but not <a></a><b></b>.
- targetRange == null || targetRange.intersects(toTest);
-
- void _addDirectiveRegions(NavigationCollector collector,
- AbstractDirective directive, SourceRange targetRange) {
- for (final input in directive.inputs) {
- if (!isTargeted(input.setterRange, targetRange: targetRange)) {
- continue;
- }
- final setter = input.setter;
- if (setter == null) {
- continue;
- }
-
- final compilationElement =
- setter.getAncestor((e) => e is engine.CompilationUnitElement);
- final lineInfo =
- (compilationElement as engine.CompilationUnitElement).lineInfo;
-
- final offsetLineLocation = lineInfo.getLocation(setter.nameOffset);
- collector.addRegion(
- input.setterRange.offset,
- input.setterRange.length,
- new protocol.AnalyzerConverter().convertElementKind(setter.kind),
- new protocol.Location(
- setter.source.fullName,
- setter.nameOffset,
- setter.nameLength,
- offsetLineLocation.lineNumber,
- offsetLineLocation.columnNumber));
- }
- }
-
- void _addTemplateRegions(NavigationCollector collector, Template template,
- SourceRange targetRange) {
- for (final resolvedRange in template.ranges) {
- if (!isTargeted(resolvedRange.range, targetRange: targetRange)) {
- continue;
- }
-
- final offset = resolvedRange.range.offset;
- final element = resolvedRange.element;
-
- if (element.nameOffset == null) {
- continue;
- }
-
- final lineInfo = element.compilationElement?.lineInfo ??
- new LineInfo.fromContent(
- _contentOverlay[element.source.fullName] ?? "");
-
- if (lineInfo == null) {
- continue;
- }
-
- final offsetLineLocation = lineInfo.getLocation(element.nameOffset);
- collector.addRegion(
- offset,
- resolvedRange.range.length,
- protocol.ElementKind.UNKNOWN,
- new protocol.Location(
- element.source.fullName,
- element.nameOffset,
- element.nameLength,
- offsetLineLocation.lineNumber,
- offsetLineLocation.columnNumber));
- }
- }
-
- void _addViewRegions(
- NavigationCollector collector, View view, SourceRange targetRange) {
- if (view.templateUriSource != null &&
- isTargeted(view.templateUrlRange, targetRange: targetRange)) {
- collector.addRegion(
- view.templateUrlRange.offset,
- view.templateUrlRange.length,
- protocol.ElementKind.UNKNOWN,
- new protocol.Location(view.templateUriSource.fullName, 0, 0, 1, 1));
- }
- }
-}
diff --git a/angular_analyzer_plugin/lib/src/navigation_request.dart b/angular_analyzer_plugin/lib/src/navigation_request.dart
deleted file mode 100644
index aa52716..0000000
--- a/angular_analyzer_plugin/lib/src/navigation_request.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer_plugin/utilities/navigation/navigation.dart';
-import 'package:angular_analyzer_plugin/src/angular_driver.dart';
-
-class AngularNavigationRequest extends NavigationRequest {
- @override
- final String path;
- @override
- final int length;
- @override
- final int offset;
- final DirectivesResult result;
-
- AngularNavigationRequest(this.path, this.length, this.offset, this.result);
-
- @override
- ResourceProvider get resourceProvider => null;
-}
diff --git a/angular_analyzer_plugin/lib/src/ng_expr_parser.dart b/angular_analyzer_plugin/lib/src/ng_expr_parser.dart
deleted file mode 100644
index a3f01c4..0000000
--- a/angular_analyzer_plugin/lib/src/ng_expr_parser.dart
+++ /dev/null
@@ -1,76 +0,0 @@
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_ast_factory.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-class NgExprParser extends Parser {
- NgExprParser(Source source, AnalysisErrorListener errorListener)
- : super.withoutFasta(source, errorListener);
-
- Token get _currentToken => super.currentToken;
-
- /// Override the bitwise or operator to parse pipes instead
- @override
- Expression parseBitwiseOrExpression() => parsePipeExpression();
-
- /// Parse pipe expression. Return the result as a cast expression `as dynamic`
- /// with _ng_pipeXXX properties to be resolved specially later.
- ///
- /// bitwiseOrExpression ::=
- /// bitwiseXorExpression ('|' pipeName [: arg]*)*
- Expression parsePipeExpression() {
- Expression expression;
- Token beforePipeToken;
- expression = parseBitwiseXorExpression();
- while (_currentToken.type == TokenType.BAR) {
- beforePipeToken ??= _currentToken.previous;
- getAndAdvance();
- final pipeEntities = parsePipeExpressionEntities();
- final asToken = new KeywordToken(Keyword.AS, 0);
- final dynamicIdToken = new SyntheticStringToken(TokenType.IDENTIFIER,
- "dynamic", _currentToken.offset - "dynamic".length);
-
- beforePipeToken.setNext(asToken);
- asToken.setNext(dynamicIdToken);
- dynamicIdToken.setNext(_currentToken);
-
- final dynamicIdentifier = astFactory.simpleIdentifier(dynamicIdToken);
-
- // TODO(mfairhurst) Now that we are resolving pipes, probably should store
- // the result in a different expression type -- a function call, most
- // likely. This will be required so that the pipeArgs become part of the
- // tree, but it may create secondary fallout inside the analyzer
- // resolution code if done wrong.
- expression = astFactory.asExpression(
- expression, asToken, astFactory.typeName(dynamicIdentifier, null))
- ..setProperty('_ng_pipeName', pipeEntities.name)
- ..setProperty('_ng_pipeArgs', pipeEntities.arguments);
- }
- return expression;
- }
-
- /// Parse a bitwise or expression to be treated as a pipe.
- /// Return the resolved left-hand expression as a dynamic type.
- ///
- /// pipeExpression ::= identifier[':' expression]*
- _PipeEntities parsePipeExpressionEntities() {
- final identifier = parseSimpleIdentifier();
- final expressions = <Expression>[];
- while (_currentToken.type == TokenType.COLON) {
- getAndAdvance();
- expressions.add(parseExpression2());
- }
-
- return _PipeEntities(identifier, expressions);
- }
-}
-
-class _PipeEntities {
- final SimpleIdentifier name;
- final List<Expression> arguments;
-
- _PipeEntities(this.name, this.arguments);
-}
diff --git a/angular_analyzer_plugin/lib/src/notification_manager.dart b/angular_analyzer_plugin/lib/src/notification_manager.dart
deleted file mode 100644
index 9fd5f09..0000000
--- a/angular_analyzer_plugin/lib/src/notification_manager.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/notification_manager.dart';
-
-// TODO(mfairhurst) remove NotificationManager & old plugin loader.
-class NoopNotificationManager implements NotificationManager {
- NoopNotificationManager();
-
- @override
- void recordAnalysisErrors(
- String path, LineInfo lineInfo, List<AnalysisError> analysisErrors) {}
-}
diff --git a/angular_analyzer_plugin/lib/src/occurrences.dart b/angular_analyzer_plugin/lib/src/occurrences.dart
deleted file mode 100644
index 7d16240..0000000
--- a/angular_analyzer_plugin/lib/src/occurrences.dart
+++ /dev/null
@@ -1,101 +0,0 @@
-// TODO get this code working with new plugin arch
-//class AngularOccurrencesContributor implements OccurrencesContributor {
-// @override
-// void computeOccurrences(
-// OccurrencesCollector collector, AnalysisContext context, Source source) {
-// //List<Source> librarySources = context.getLibrariesContaining(source);
-// //for (Source librarySource in librarySources) {
-// // // directives
-// // {
-// // List<AbstractDirective> directives = context.getResult(
-// // new LibrarySpecificUnit(librarySource, source), DIRECTIVES_IN_UNIT);
-// // for (AbstractDirective directive in directives) {
-// // _addDirectiveOccurrences(collector, directive);
-// // }
-// // }
-// // // templates
-// // {
-// // List<Template> templates = context.getResult(
-// // new LibrarySpecificUnit(librarySource, source), DART_TEMPLATES);
-// // for (Template template in templates) {
-// // _addTemplateOccurrences(collector, template);
-// // }
-// // }
-// //}
-// }
-//
-// void addDirectiveOccurrences(
-// OccurrencesCollector collector, AbstractDirective directive) {
-// final elementsOffsets = <engine.PropertyAccessorElement, List<int>>{};
-// for (final input in directive.inputs) {
-// final setter = input.setter;
-// if (setter == null) {
-// continue;
-// }
-// var offsets = elementsOffsets[setter];
-// if (offsets == null) {
-// offsets = <int>[setter.nameOffset];
-// elementsOffsets[setter] = offsets;
-// }
-// offsets.add(input.setterRange.offset);
-// }
-// // convert map into Occurrences
-// elementsOffsets.forEach((setter, offsets) {
-// final protocolElement = _newProtocolElementForEngine(setter);
-// final length = protocolElement.location.length;
-// final occurrences =
-// new protocol.Occurrences(protocolElement, offsets, length);
-// collector.addOccurrences(occurrences);
-// });
-// }
-//
-// void addTemplateOccurrences(
-// OccurrencesCollector collector, Template template) {
-// final elementsOffsets = <AngularElement, List<int>>{};
-// for (final resolvedRange in template.ranges) {
-// final element = resolvedRange.element;
-// var offsets = elementsOffsets[element];
-// if (offsets == null) {
-// offsets = <int>[element.nameOffset];
-// elementsOffsets[element] = offsets;
-// }
-// offsets.add(resolvedRange.range.offset);
-// }
-// // convert map into Occurrences
-// elementsOffsets.forEach((angularElement, offsets) {
-// final length = angularElement.nameLength;
-// final protocolElement = _newProtocolElement(angularElement);
-// final occurrences =
-// new protocol.Occurrences(protocolElement, offsets, length);
-// collector.addOccurrences(occurrences);
-// });
-// }
-//
-// engine.Element _canonicalizeElement(engine.Element element) {
-// var canonical = element;
-// if (canonical is engine.PropertyAccessorElement) {
-// canonical = (canonical as engine.PropertyAccessorElement).variable;
-// }
-// if (canonical is Member) {
-// canonical = (canonical as Member).baseElement;
-// }
-// return canonical;
-// }
-//
-// protocol.Element _newProtocolElement(AngularElement angularElement) {
-// final name = angularElement.name;
-// final length = name.length;
-// if (angularElement is DartElement) {
-// final dartElement = angularElement.element;
-// return _newProtocolElementForEngine(dartElement);
-// }
-// return new protocol.Element(protocol.ElementKind.UNKNOWN, name, 0,
-// location: new protocol.Location(angularElement.source.fullName,
-// angularElement.nameOffset, length, -1, -1));
-// }
-//
-// protocol.Element _newProtocolElementForEngine(engine.Element dartElement) {
-// final cannonical = _canonicalizeElement(dartElement);
-// return protocol.convertElement(cannonical);
-// }
-//}
diff --git a/angular_analyzer_plugin/lib/src/options.dart b/angular_analyzer_plugin/lib/src/options.dart
deleted file mode 100644
index f27dd70..0000000
--- a/angular_analyzer_plugin/lib/src/options.dart
+++ /dev/null
@@ -1,163 +0,0 @@
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:meta/meta.dart';
-import 'package:yaml/yaml.dart';
-
-class AngularOptions {
- final List<String> customTagNames;
- final Map<String, CustomEvent> customEvents;
- final Source source;
-
- String _customEventsHashString;
-
- AngularOptions({this.customTagNames, this.customEvents, this.source});
- factory AngularOptions.defaults() => new _OptionsBuilder.empty().build();
- factory AngularOptions.from(Source source) =>
- new _OptionsBuilder(null, source).build();
-
- /// For tests, its easier to pass the Source's contents directly rather than
- /// creating mocks that returned mocked data that mocked contents.
- @visibleForTesting
- factory AngularOptions.fromString(String content, Source source) =>
- new _OptionsBuilder(content, source).build();
-
- /// A unique signature based on the events for hashing the settings into the
- /// resolution hashes.
- String get customEventsHashString =>
- _customEventsHashString ??= _computeCustomEventsHashString();
-
- /// When events are present, generate a string in the form of
- /// 'e:name,type,path,name,type,path'. Take care we sort before emitting. And
- /// in theory we could/should escape colon and comma, but the only one of
- /// those that should appear in a valid config is the colon in 'package:',
- /// and due to its position between the fixed placement of commas, it should
- /// not be able to make one signature look like another.
- String _computeCustomEventsHashString() {
- if (customEvents.isEmpty) {
- return '';
- }
-
- final buffer = new StringBuffer()..write('e:');
- for (final key in customEvents.keys.toList()..sort()) {
- final event = customEvents[key];
- buffer
- ..write(event.name ?? '')
- ..write(',')
- ..write(event.typeName ?? '')
- ..write(',')
- ..write(event.typePath ?? '')
- ..write(',');
- }
- return buffer.toString();
- }
-}
-
-class CustomEvent {
- final String name;
- final String typeName;
- final String typePath;
- final int nameOffset;
-
- DartType resolvedType;
-
- CustomEvent(this.name, this.typeName, this.typePath, this.nameOffset);
-}
-
-class _OptionsBuilder {
- dynamic analysisOptions;
- dynamic angularOptions;
-
- List<String> customTagNames = const [];
- Map<String, CustomEvent> customEvents = {};
- final Source source;
-
- _OptionsBuilder(String content, Source source)
- : source = source,
- analysisOptions = loadYaml(content ?? source.contents.data) {
- load();
- }
- _OptionsBuilder.empty() : source = null;
-
- AngularOptions build() => new AngularOptions(
- customTagNames: customTagNames, customEvents: customEvents);
-
- T getOption<T>(String key, bool validator(input)) {
- if (angularOptions != null && validator(angularOptions[key])) {
- return angularOptions[key] as T;
- }
- return null;
- }
-
- bool isListOfStrings(values) =>
- values is List && values.every((value) => value is String);
-
- bool isMapOfObjects(values) =>
- values is YamlMap &&
- values.values.every((value) => value is YamlMap || value == null);
-
- void load() {
- if (analysisOptions['analyzer'] == null ||
- analysisOptions['analyzer']['plugins'] == null) {
- return;
- }
-
- if (loadTopLevelSection() ||
- loadPluginSection('angular') ||
- loadPluginSection('angular_analyzer_plugin')) {
- resolve();
- }
- }
-
- /// Look for a plugin enabled by name [key], which for historical purposes is
- /// allowed via "angular" or "angular_analyzer_plugin." Return true if that
- /// plugin is specified, and as an edge case, it may have config to load into
- /// [angularOptions]. This will soon be removed.
- bool loadPluginSection(String key) {
- final pluginsSection = analysisOptions['analyzer']['plugins'];
-
- // This is common. This means the plugin is turned on but has no config.
- if (pluginsSection is List) {
- return pluginsSection.contains(key);
- }
-
- // Protect against confusing configs
- if (pluginsSection is! Map) {
- return false;
- }
-
- // Outdated edge case, support a map of options under `plugins: x: ...`.
- final specified = (pluginsSection as Map).containsKey(key);
- if (specified) {
- angularOptions = pluginsSection[key];
- }
- return specified;
- }
-
- /// Attempt to load the top level `angular` config section into
- /// [angularOptions]. If the section exists and is a map, return true. This is
- /// the going-forward default case.
- bool loadTopLevelSection() {
- if (analysisOptions['angular'] is Map) {
- angularOptions = analysisOptions['angular'];
- return true;
- }
- return false;
- }
-
- void resolve() {
- customTagNames = new List<String>.from(
- getOption<List>('custom_tag_names', isListOfStrings) ?? []);
- getOption<YamlMap>('custom_events', isMapOfObjects)
- ?.nodes
- ?.forEach((nameNodeKey, props) {
- final nameNode = nameNodeKey as YamlScalar;
- final name = nameNode.value as String;
- final offset = nameNode.span.start.offset;
- customEvents[name] = props is YamlMap
- ? new CustomEvent(
- name, props['type'] as String, props['path'] as String, offset)
- // Handle `event:` with no value, a shortcut for dynamic.
- : new CustomEvent(name, null, null, offset);
- });
- }
-}
diff --git a/angular_analyzer_plugin/lib/src/pipe_extraction.dart b/angular_analyzer_plugin/lib/src/pipe_extraction.dart
deleted file mode 100644
index d7d632b..0000000
--- a/angular_analyzer_plugin/lib/src/pipe_extraction.dart
+++ /dev/null
@@ -1,135 +0,0 @@
-import 'package:analyzer/dart/ast/ast.dart' as ast;
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart' as utils;
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/errors.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/standard_components.dart';
-import 'package:angular_analyzer_plugin/src/tasks.dart';
-
-class PipeExtractor extends AnnotationProcessorMixin {
- final ast.CompilationUnit _unit;
- final Source _source;
- final StandardAngular _standardAngular;
-
- /// The [ClassElement] being used to create the current component,
- /// stored here instead of passing around everywhere.
- ClassElement _currentClassElement;
-
- PipeExtractor(this._unit, this._source, this._standardAngular) {
- initAnnotationProcessor(_source);
- }
-
- List<Pipe> getPipes() {
- final pipes = <Pipe>[];
- for (final unitMember in _unit.declarations) {
- if (unitMember is ast.ClassDeclaration) {
- for (final annotationNode in unitMember.metadata) {
- final pipe = _createPipe(unitMember, annotationNode);
- if (pipe != null) {
- pipes.add(loadTransformInformation(pipe));
- }
- }
- }
- }
- return pipes;
- }
-
- /// Looks for a 'transform' function, and if found, finds all the
- /// important type information needed for resolution of pipe.
- Pipe loadTransformInformation(Pipe pipe) {
- final classElement = pipe.classElement;
- if (classElement == null) {
- return pipe;
- }
-
- final transformMethod =
- classElement.lookUpMethod('transform', classElement.library);
- if (transformMethod == null) {
- errorReporter.reportErrorForElement(
- AngularWarningCode.PIPE_REQUIRES_TRANSFORM_METHOD, classElement);
- return pipe;
- }
-
- pipe.transformReturnType = transformMethod.returnType;
- final parameters = transformMethod.parameters;
- if (parameters == null || parameters.isEmpty) {
- errorReporter.reportErrorForElement(
- AngularWarningCode.PIPE_TRANSFORM_REQ_ONE_ARG, transformMethod);
- }
- for (final parameter in parameters) {
- // If named or positional
- if (parameter.isNamed) {
- errorReporter.reportErrorForElement(
- AngularWarningCode.PIPE_TRANSFORM_NO_NAMED_ARGS, parameter);
- continue;
- }
- if (parameters.first == parameter) {
- pipe.requiredArgumentType = parameter.type;
- } else {
- pipe.optionalArgumentTypes.add(parameter.type);
- }
- }
- return pipe;
- }
-
- /// Returns an Angular [Pipe] for the given [node].
- /// Returns `null` if not an Angular @Pipe annotation.
- Pipe _createPipe(ast.ClassDeclaration classDeclaration, ast.Annotation node) {
- _currentClassElement = classDeclaration.declaredElement;
- if (isAngularAnnotation(node, 'Pipe')) {
- String pipeName;
- int pipeNameOffset;
- ast.Expression pipeNameExpression;
- var isPure = true;
- ast.Expression isPureExpression;
-
- if (node.arguments != null && node.arguments.arguments.isNotEmpty) {
- final arguments = node.arguments.arguments;
- if (arguments.first is! ast.NamedExpression) {
- pipeNameExpression = arguments.first;
- }
- isPureExpression = getNamedArgument(node, 'pure');
- }
- if (pipeNameExpression != null) {
- final constantEvaluation =
- calculateStringWithOffsets(pipeNameExpression);
- if (constantEvaluation != null && constantEvaluation.value is String) {
- pipeName = (constantEvaluation.value as String).trim();
- pipeNameOffset = pipeNameExpression.offset;
- }
- }
- if (isPureExpression != null) {
- final isPureValue =
- isPureExpression.accept(new utils.ConstantEvaluator());
- if (isPureValue != null && isPureValue is bool) {
- isPure = isPureValue;
- }
- }
- if (pipeName == null) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.PIPE_SINGLE_NAME_REQUIRED, node);
- }
-
- // Check if 'extends PipeTransform' exists.
- var allSupertypes = _currentClassElement.allSupertypes ?? [];
- allSupertypes = allSupertypes
- .where((t) => _standardAngular.pipeTransform.type.isSupertypeOf(t))
- .toList();
- if (allSupertypes.isEmpty) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.PIPE_REQUIRES_PIPETRANSFORM, node);
- }
-
- // Check if abstract
- if (_currentClassElement.isAbstract) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.PIPE_CANNOT_BE_ABSTRACT, node);
- }
-
- return new Pipe(pipeName, pipeNameOffset, _currentClassElement,
- isPure: isPure);
- }
- return null;
- }
-}
diff --git a/angular_analyzer_plugin/lib/src/resolver.dart b/angular_analyzer_plugin/lib/src/resolver.dart
deleted file mode 100644
index 7e046b6..0000000
--- a/angular_analyzer_plugin/lib/src/resolver.dart
+++ /dev/null
@@ -1,2039 +0,0 @@
-import 'dart:collection';
-
-import 'package:analyzer/dart/ast/ast.dart' hide Directive;
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/element/builder.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/error_verifier.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/ast.dart';
-import 'package:angular_analyzer_plugin/errors.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/options.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-import 'package:angular_analyzer_plugin/src/standard_components.dart';
-import 'package:meta/meta.dart';
-
-/// Custom tags shouldn't report things like unbound inputs/outputs
-bool isOnCustomTag(AttributeInfo node) {
- if (node.parent == null) {
- return false;
- }
-
- final parent = node.parent;
-
- return parent is ElementInfo && parent.tagMatchedAsCustomTag;
-}
-
-/// Overrides standard [ResolverVisitor] to prevent issues with analyzing
-/// dangling angular nodes, while also allowing custom resolution of pipes. Not
-/// intended as a long-term solution.
-class AngularResolverVisitor extends _IntermediateResolverVisitor {
- final List<Pipe> pipes;
-
- AngularResolverVisitor(
- InheritanceManager2 inheritanceManager2,
- LibraryElement library,
- Source source,
- TypeProvider typeProvider,
- AnalysisErrorListener errorListener,
- {@required this.pipes})
- : super(
- inheritanceManager2, library, source, typeProvider, errorListener);
-
- @override
- void visitAsExpression(AsExpression exp) {
- // This means we generated this in a pipe, and its OK.
- // TODO(mfairhurst): figure out an alternative approach to this.
- if (exp.asOperator.offset == 0) {
- super.visitAsExpression(exp);
- final pipeName = exp.getProperty<SimpleIdentifier>('_ng_pipeName');
- final matchingPipes =
- pipes.where((pipe) => pipe.pipeName == pipeName.name);
- if (matchingPipes.isEmpty) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.PIPE_NOT_FOUND, pipeName, [pipeName]);
- } else if (matchingPipes.length > 1) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.AMBIGUOUS_PIPE, pipeName, [pipeName]);
- } else {
- final matchingPipe = matchingPipes.single;
- exp.staticType = matchingPipe.transformReturnType;
-
- if (!typeSystem.isAssignableTo(
- exp.expression.staticType, matchingPipe.requiredArgumentType)) {
- errorReporter.reportErrorForNode(
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
- exp.expression,
- [exp.expression.staticType, matchingPipe.requiredArgumentType]);
- }
- }
- }
- }
-}
-
-/// Probably the most important visitor to understand in how we process angular
-/// templates.
-///
-/// First its important to note how angular scopes are determined by templates;
-/// that's how ngFor adds a variable below. Its also important to note that
-/// unlike in most languages, angular template semantics lets you use a variable
-/// before its declared, ie `<a>{{b}}</a><p #b></p>` so long as they share a
-/// scope. Also note that a template both ends a scope and begins it: all
-/// the bindings in the template are from the old scope, and yet let-vars add to
-/// the new new scope.
-///
-/// This means we need to have a multiple-pass process, and that means we spend
-/// a good chunk of time merely following the rules of scoping. This visitor
-/// will enforce that for you.
-///
-/// Just don't @override visitElementInfo (or do so carefully), and this visitor
-/// naturally walk over all the attributes in scope by what you give it. You can
-/// also hook into what happens when it hits the elements by overriding:
-///
-/// * visitBorderScopeTemplateAttribute(templateAttribute)
-/// * visitScopeRootElementWithTemplateAttribute(element)
-/// * visitBorderScopeTemplateElement(element)
-/// * visitScopeRootTemplateElement(element)
-/// * visitElementInScope(element)
-///
-/// Which should allow you to do specialty things, such as what the
-/// [PrepareScopeVisitor] does by using out-of-scope properties to affect the
-/// in-scope ones.
-class AngularScopeVisitor extends AngularAstVisitor {
- bool visitingRoot = true;
-
- void visitBorderScopeTemplateAttribute(TemplateAttribute attr) {
- // Border to the next scope. The virtual properties belong here, the real
- // element does not
- visitTemplateAttr(attr);
- }
-
- void visitBorderScopeTemplateElement(ElementInfo element) {
- // the attributes are in this scope, the children aren't
- for (final attr in element.attributes) {
- attr.accept(this);
- }
- }
-
- @override
- void visitDocumentInfo(DocumentInfo document) {
- visitingRoot = false;
- visitElementInScope(document);
- }
-
- @override
- void visitElementInfo(ElementInfo element) {
- final isRoot = visitingRoot;
- visitingRoot = false;
- if (element.templateAttribute != null) {
- if (!isRoot) {
- visitBorderScopeTemplateAttribute(element.templateAttribute);
- return;
- } else {
- visitScopeRootElementWithTemplateAttribute(element);
- }
- } else if (element.isTemplate) {
- if (isRoot) {
- visitScopeRootTemplateElement(element);
- } else {
- visitBorderScopeTemplateElement(element);
- }
- } else {
- visitElementInScope(element);
- }
- }
-
- void visitElementInScope(ElementInfo element) {
- for (final child in element.children) {
- child.accept(this);
- }
- }
-
- void visitScopeRootElementWithTemplateAttribute(ElementInfo element) {
- final children =
- element.children.where((child) => child is! TemplateAttribute);
- for (final child in children) {
- child.accept(this);
- }
- }
-
- void visitScopeRootTemplateElement(ElementInfo element) {
- // the children are in this scope, the template itself is borderlands
- for (var child in element.childNodes) {
- child.accept(this);
- }
- }
-}
-
-/// Find nodes which are not supported in angular (such as compound assignment
-/// and function expressions etc.), as well as terms used in the template that
-/// weren't exported by the component.
-class AngularSubsetVisitor extends RecursiveAstVisitor<Object> {
- final bool acceptAssignment;
- final Component owningComponent;
-
- final ErrorReporter errorReporter;
-
- AngularSubsetVisitor(
- {@required this.errorReporter,
- @required this.owningComponent,
- @required this.acceptAssignment});
-
- @override
- void visitAsExpression(AsExpression exp) {
- if (exp.asOperator.offset == 0) {
- // This means we generated this in a pipe, and its OK.
- } else {
- _reportDisallowedExpression(exp, "As expression", visitChildren: false);
- }
-
- // Don't visit the TypeName or it may suggest exporting it, which is not
- // possible.
- exp.expression.accept(this);
- }
-
- @override
- void visitAssignmentExpression(AssignmentExpression exp) {
- if (exp.operator.type != TokenType.EQ) {
- _reportDisallowedExpression(exp, 'Compound assignment',
- visitChildren: false);
- }
- // Only block reassignment of locals, not poperties. Resolve elements to
- // check that.
- final variableElement = ErrorVerifier.getVariableElement(exp.leftHandSide);
- final isLocal =
- variableElement != null && variableElement is! PropertyInducingElement;
- if (!acceptAssignment || isLocal) {
- _reportDisallowedExpression(exp, 'Assignment of locals',
- visitChildren: false);
- }
-
- super.visitAssignmentExpression(exp);
- }
-
- @override
- void visitAwaitExpression(AwaitExpression exp) =>
- _reportDisallowedExpression(exp, "Await");
-
- @override
- void visitCascadeExpression(CascadeExpression exp) =>
- _reportDisallowedExpression(exp, "Cascades");
-
- @override
- void visitFunctionExpression(FunctionExpression exp) =>
- _reportDisallowedExpression(exp, "Anonymous functions");
-
- /// Only allow access to:
- /// * current class members
- /// * inherited class members
- /// * methods
- /// * angular references (ie `<h1 #ref id="foo"></h1> {{h1.id}}`)
- /// * exported members
- ///
- /// Flag the rest and give the hint that they should be exported.
- void visitIdentifier(Identifier id) {
- final element = id.staticElement;
- final parent = id.parent;
- if (id is PrefixedIdentifier && id.prefix.staticElement is! PrefixElement) {
- // Static methods, enums, etc. Check the LHS.
- visitIdentifier(id.prefix);
- return;
- }
- if (parent is PropertyAccess && id == parent.propertyName) {
- // Accessors are always allowed.
- return;
- }
- if (element is PrefixElement) {
- // Prefixes can't be exported, and analyzer reports a warning for dangling
- // prefixes.
- return;
- }
- if (element is MethodElement) {
- // All methods are OK, as in `x.y()`. It's only `x` that may be hidden.
- return;
- }
- if (element is ClassElement && element == owningComponent.classElement) {
- // Static method calls on the current class are allowed
- return;
- }
- if (element is DynamicElementImpl) {
- // Usually indicates a resolution error, so don't double report it.
- return;
- }
- if (element == null) {
- // Also usually indicates an error, don't double report.
- return;
- }
- if (element is LocalVariableElement) {
- // `$event` variables, `ngFor` variables, these are OK.
- return;
- }
- if (element is ParameterElement) {
- // Named parameters always allowed
- return;
- }
- if (element is AngularElement) {
- // Variables local to the template
- return;
- }
- if (id is SimpleIdentifier &&
- (element is PropertyInducingElement ||
- element is PropertyAccessorElement) &&
- (owningComponent.classElement.lookUpGetter(id.name, null) != null ||
- owningComponent.classElement.lookUpSetter(id.name, null) != null)) {
- // Part of the component interface.
- return;
- }
-
- if (id is PrefixedIdentifier) {
- if (owningComponent.exports.any((export) =>
- export.prefix == id.prefix.name &&
- id.identifier.name == export.identifier)) {
- // Correct reference to exported prefix identifier
- return;
- }
- } else {
- if (parent is MethodInvocation && parent.methodName == id) {
- final target = parent.target;
- if (target is SimpleIdentifier &&
- target.staticElement is PrefixElement &&
- owningComponent.exports.any((export) =>
- export.prefix == target.name && export.identifier == id.name)) {
- // Invocation of a top-level function behind a prefix, which is stored
- // as a [MethodInvocation].
- return;
- }
- }
- if (owningComponent.exports.any(
- (export) => export.prefix == '' && id.name == export.identifier)) {
- // Correct reference to exported simple identifier
- return;
- }
- }
-
- errorReporter.reportErrorForNode(
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED, id, [id]);
- }
-
- @override
- void visitInstanceCreationExpression(InstanceCreationExpression exp) {
- _reportDisallowedExpression(exp, "Usage of new", visitChildren: false);
- // Don't visit the TypeName or it may suggest exporting it, which is not
- // possible.
-
- exp.argumentList.accept(this);
- }
-
- @override
- void visitIsExpression(IsExpression exp) {
- _reportDisallowedExpression(exp, "Is expression", visitChildren: false);
- // Don't visit the TypeName or it may suggest exporting it, which is not
- // possible.
-
- exp.expression.accept(this);
- }
-
- @override
- void visitListLiteral(ListLiteral list) {
- if (list.typeArguments != null) {
- _reportDisallowedExpression(list, "Typed list literals",
- visitChildren: false);
- // Don't visit the TypeName or it may suggest exporting it, which is not
- // possible.e.
-
- list.elements.accept(this);
- } else {
- super.visitListLiteral(list);
- }
- }
-
- @override
- void visitMapLiteral(MapLiteral map) {
- if (map.typeArguments != null) {
- _reportDisallowedExpression(map, "Typed map literals",
- visitChildren: false);
- // Don't visit the TypeName or it may suggest exporting it, which is not
- // possible.e.
-
- map.entries.accept(this);
- } else {
- super.visitMapLiteral(map);
- }
- }
-
- @override
- void visitPostfixExpression(PostfixExpression exp) {
- _reportDisallowedExpression(exp, exp.operator.lexeme);
- }
-
- @override
- void visitPrefixedIdentifier(PrefixedIdentifier id) => visitIdentifier(id);
-
- @override
- void visitPrefixExpression(PrefixExpression exp) {
- if (exp.operator.type != TokenType.MINUS &&
- exp.operator.type != TokenType.BANG) {
- _reportDisallowedExpression(exp, exp.operator.lexeme);
- }
- }
-
- @override
- void visitSimpleIdentifier(SimpleIdentifier id) => visitIdentifier(id);
-
- @override
- void visitSymbolLiteral(SymbolLiteral exp) =>
- _reportDisallowedExpression(exp, "Symbol literal");
-
- @override
- void visitThrowExpression(ThrowExpression exp) =>
- _reportDisallowedExpression(exp, "Throw");
-
- void _reportDisallowedExpression(Expression node, String description,
- {bool visitChildren = true}) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.DISALLOWED_EXPRESSION, node, [description]);
-
- if (visitChildren) {
- node.visitChildren(this);
- }
- }
-}
-
-class ComponentContentResolver extends AngularAstVisitor {
- final Source templateSource;
- final Template template;
- final AnalysisErrorListener errorListener;
-
- ComponentContentResolver(
- this.templateSource, this.template, this.errorListener);
-
- void checkTransclusionsContentChildren(
- Component component, List<NodeInfo> children,
- {@required bool tagIsStandard}) {
- if (component?.ngContents == null) {
- return;
- }
-
- final acceptAll = component.ngContents.any((s) => s.matchesAll);
- for (final child in children) {
- if (child is TextInfo && !acceptAll && child.text.trim() != "") {
- _reportErrorForRange(new SourceRange(child.offset, child.length),
- AngularWarningCode.CONTENT_NOT_TRANSCLUDED);
- } else if (child is ElementInfo) {
- final view = new ElementViewImpl(child.attributes, element: child);
-
- var matched = acceptAll;
- var matchedTag = false;
-
- for (final ngContent in component.ngContents) {
- final match = ngContent.matchesAll
- ? SelectorMatch.NonTagMatch
- : ngContent.selector.match(view, template);
- if (match != SelectorMatch.NoMatch) {
- matched = true;
- matchedTag = matchedTag || match == SelectorMatch.TagMatch;
- }
- }
-
- matched = matched || child.tagMatchedAsImmediateContentChild;
-
- if (!matched) {
- _reportErrorForRange(new SourceRange(child.offset, child.length),
- AngularWarningCode.CONTENT_NOT_TRANSCLUDED);
- } else if (matchedTag) {
- child.tagMatchedAsTransclusion = true;
- }
- }
- }
- }
-
- @override
- void visitElementInfo(ElementInfo element) {
- // TODO should we visitTemplateAttr(element.templateAttribute) ??
- var tagIsStandard = _isStandardTagName(element.localName);
- Component component;
-
- for (final directive in element.directives) {
- if (directive is Component) {
- component = directive;
- // TODO better html tag detection, see #248
- tagIsStandard = component.isHtml;
- }
- }
-
- if (!tagIsStandard &&
- !element.tagMatchedAsTransclusion &&
- !element.tagMatchedAsDirective &&
- !element.tagMatchedAsCustomTag) {
- _reportErrorForRange(element.openingNameSpan,
- AngularWarningCode.UNRESOLVED_TAG, [element.localName]);
- }
-
- if (!tagIsStandard) {
- checkTransclusionsContentChildren(component, element.childNodes,
- tagIsStandard: tagIsStandard);
- }
-
- for (final child in element.childNodes) {
- child.accept(this);
- }
- }
-
- /// Check whether the given [name] is a standard HTML5 tag name.
- bool _isStandardTagName(String name) {
- // ignore: parameter_assignments
- name = name.toLowerCase();
- return !name.contains('-') ||
- name == 'ng-content' ||
- name == 'ng-container';
- }
-
- void _reportErrorForRange(SourceRange range, ErrorCode errorCode,
- [List<Object> arguments]) {
- errorListener.onError(new AnalysisError(
- templateSource, range.offset, range.length, errorCode, arguments));
- }
-}
-
-class DartVariableManager {
- Template template;
- Source templateSource;
- AnalysisErrorListener errorListener;
-
- CompilationUnitElementImpl htmlCompilationUnitElement;
-
- ClassElementImpl htmlClassElement;
- MethodElementImpl htmlMethodElement;
- DartVariableManager(this.template, this.templateSource, this.errorListener);
-
- LocalVariableElement newLocalVariableElement(
- int offset, String name, DartType type) {
- // ensure artificial Dart elements in the template source
- if (htmlMethodElement == null) {
- htmlCompilationUnitElement = new CompilationUnitElementImpl()
- ..source = templateSource;
- htmlClassElement = new ClassElementImpl('AngularTemplateClass', -1);
- htmlCompilationUnitElement.types = <ClassElement>[htmlClassElement];
- htmlMethodElement = new MethodElementImpl('angularTemplateMethod', -1);
- htmlClassElement.methods = <MethodElement>[htmlMethodElement];
- }
- // add a new local variable
- final localVariable = new LocalVariableElementImpl(name, offset);
- localVariable.name.length;
- localVariable.type = type;
-
- return localVariable;
- }
-}
-
-class DirectiveResolver extends AngularAstVisitor {
- final List<AbstractDirective> allDirectives;
- final Source templateSource;
- final Template template;
- final AnalysisErrorListener errorListener;
- final ErrorReporter _errorReporter;
- final StandardAngular _standardAngular;
- final StandardHtml _standardHtml;
- final outerBindings = <DirectiveBinding>[];
- final outerElements = <ElementInfo>[];
- final Set<String> customTagNames;
-
- DirectiveResolver(
- this.allDirectives,
- this.templateSource,
- this.template,
- this._standardAngular,
- this._standardHtml,
- this._errorReporter,
- this.errorListener,
- this.customTagNames);
-
- void recordContentChildren(ElementInfo element) {
- for (final binding in outerBindings) {
- for (var contentChild in binding.boundDirective.contentChilds) {
- // an already matched ContentChild shouldn't look inside that match
- if (binding.contentChildBindings[contentChild]?.boundElements
- ?.any(outerElements.contains) ==
- true) {
- continue;
- }
-
- if (contentChild.query
- .match(element, _standardAngular, _standardHtml, _errorReporter)) {
- binding.contentChildBindings.putIfAbsent(
- contentChild,
- () => new ContentChildBinding(
- binding.boundDirective, contentChild));
-
- if (binding
- .contentChildBindings[contentChild].boundElements.isNotEmpty) {
- _errorReporter.reportErrorForOffset(
- AngularWarningCode.SINGULAR_CHILD_QUERY_MATCHED_MULTIPLE_TIMES,
- element.offset,
- element.length,
- [binding.boundDirective.name, contentChild.field.fieldName]);
- }
- binding.contentChildBindings[contentChild].boundElements.add(element);
-
- if (element.parent.boundDirectives.contains(binding)) {
- element.tagMatchedAsImmediateContentChild = true;
- }
- }
- }
-
- for (var contentChildren in binding.boundDirective.contentChildren) {
- if (contentChildren.query
- .match(element, _standardAngular, _standardHtml, _errorReporter)) {
- binding.contentChildrenBindings.putIfAbsent(
- contentChildren,
- () => new ContentChildBinding(
- binding.boundDirective, contentChildren));
- binding.contentChildrenBindings[contentChildren].boundElements
- .add(element);
-
- if (element.parent.boundDirectives.contains(binding)) {
- element.tagMatchedAsImmediateContentChild = true;
- }
- }
- }
- }
- }
-
- @override
- void visitElementInfo(ElementInfo element) {
- outerElements.add(element);
- if (element.templateAttribute != null) {
- visitTemplateAttr(element.templateAttribute);
- }
-
- final elementView =
- new ElementViewImpl(element.attributes, element: element);
- final unmatchedDirectives = <AbstractDirective>[];
-
- final containingDirectivesCount = outerBindings.length;
- for (final directive in allDirectives) {
- final match = directive.selector.match(elementView, template);
- if (match != SelectorMatch.NoMatch) {
- final binding = new DirectiveBinding(directive);
- element.boundDirectives.add(binding);
- if (match == SelectorMatch.TagMatch) {
- element.tagMatchedAsDirective = true;
- }
-
- // optimization: only add the bindings that care about content child
- if (directive.contentChilds.isNotEmpty ||
- directive.contentChildren.isNotEmpty) {
- outerBindings.add(binding);
- }
-
- // Specifically exclude NgIf and NgFor, they have their own error since
- // we *know* they require a template.
- if (directive.looksLikeTemplate &&
- !element.isTemplate &&
- directive.name != "NgIf" &&
- directive.name != "NgFor") {
- _reportErrorForRange(
- element.openingSpan,
- AngularWarningCode.CUSTOM_DIRECTIVE_MAY_REQUIRE_TEMPLATE,
- [directive.name]);
- }
- } else {
- unmatchedDirectives.add(directive);
- }
- }
-
- for (final directive in unmatchedDirectives) {
- if (directive is AbstractDirective &&
- directive.selector.availableTo(elementView) &&
- !directive.looksLikeTemplate) {
- element.availableDirectives[directive] =
- directive.selector.getAttributes(elementView);
- }
- }
-
- element.tagMatchedAsCustomTag = customTagNames.contains(element.localName);
-
- if (!element.isTemplate) {
- _checkNoStructuralDirectives(element.attributes);
- }
-
- recordContentChildren(element);
-
- for (final child in element.childNodes) {
- child.accept(this);
- }
-
- outerBindings.removeRange(containingDirectivesCount, outerBindings.length);
- outerElements.removeLast();
- }
-
- @override
- void visitTemplateAttr(TemplateAttribute attr) {
- final elementView =
- new ElementViewImpl(attr.virtualAttributes, elementName: 'template');
- for (final directive in allDirectives) {
- if (directive.selector.match(elementView, template) !=
- SelectorMatch.NoMatch) {
- attr.boundDirectives.add(new DirectiveBinding(directive));
- }
- }
-
- final templateAttrIsUsed =
- attr.directives.any((directive) => directive.looksLikeTemplate);
-
- if (!templateAttrIsUsed) {
- _reportErrorForRange(
- new SourceRange(attr.originalNameOffset, attr.originalName.length),
- AngularWarningCode.TEMPLATE_ATTR_NOT_USED);
- }
- }
-
- void _checkNoStructuralDirectives(List<AttributeInfo> attributes) {
- for (final attribute in attributes) {
- if (attribute is! TextAttribute) {
- continue;
- }
-
- if (attribute.name == 'ngFor' || attribute.name == 'ngIf') {
- _reportErrorForRange(
- new SourceRange(attribute.nameOffset, attribute.name.length),
- AngularWarningCode.STRUCTURAL_DIRECTIVES_REQUIRE_TEMPLATE,
- [attribute.name]);
- }
- }
- }
-
- void _reportErrorForRange(SourceRange range, ErrorCode errorCode,
- [List<Object> arguments]) {
- errorListener.onError(new AnalysisError(
- templateSource, range.offset, range.length, errorCode, arguments));
- }
-}
-
-/// The implementation of [ElementView] using [AttributeInfo]s.
-class ElementViewImpl implements ElementView {
- @override
- final attributeNameSpans = <String, SourceRange>{};
-
- @override
- final attributeValueSpans = <String, SourceRange>{};
-
- @override
- final attributes = <String, String>{};
-
- @override
- SourceRange closingSpan;
-
- @override
- SourceRange closingNameSpan;
-
- @override
- String localName;
-
- @override
- SourceRange openingSpan;
-
- @override
- SourceRange openingNameSpan;
-
- ElementViewImpl(List<AttributeInfo> attributeInfoList,
- {ElementInfo element, String elementName}) {
- for (final attribute in attributeInfoList) {
- if (attribute is TemplateAttribute) {
- continue;
- }
- final name = attribute.name;
- attributeNameSpans[name] =
- new SourceRange(attribute.nameOffset, attribute.name.length);
- if (attribute.value != null) {
- attributeValueSpans[name] =
- new SourceRange(attribute.valueOffset, attribute.valueLength);
- }
- attributes[name] = attribute.value;
- }
- if (element != null) {
- localName = element.localName;
- openingSpan = element.openingSpan;
- closingSpan = element.closingSpan;
- openingNameSpan = element.openingNameSpan;
- closingNameSpan = element.closingNameSpan;
- } else if (elementName != null) {
- localName = elementName;
- }
- }
-}
-
-/// A variable defined by a [AbstractDirective].
-class InternalVariable {
- final String name;
- final AngularElement element;
- final DartType type;
-
- InternalVariable(this.name, this.element, this.type);
-}
-
-/// Use this visitor to find the nested scopes within the [ElementInfo]
-/// you visit.
-class NextTemplateElementsSearch extends AngularAstVisitor {
- bool visitingRoot = true;
-
- final results = <ElementInfo>[];
-
- @override
- void visitDocumentInfo(DocumentInfo document) {
- visitingRoot = false;
- for (final child in document.childNodes) {
- child.accept(this);
- }
- }
-
- @override
- void visitElementInfo(ElementInfo element) {
- if (element.isOrHasTemplateAttribute && !visitingRoot) {
- results.add(element);
- return;
- }
-
- visitingRoot = false;
- for (final child in element.childNodes) {
- child.accept(this);
- }
- }
-}
-
-class NgContentRecorder extends AngularScopeVisitor {
- final List<NgContent> ngContents;
- final Source source;
- final ErrorReporter errorReporter;
-
- NgContentRecorder(Component component, this.errorReporter)
- : ngContents = component.ngContents,
- source = component.view.templateSource;
-
- NgContentRecorder.forFile(this.ngContents, this.source, this.errorReporter);
-
- @override
- void visitElementInfo(ElementInfo element) {
- if (element.localName != 'ng-content') {
- for (final child in element.childNodes) {
- child.accept(this);
- }
-
- return;
- }
-
- final selectorAttrs = element.attributes.where((a) => a.name == 'select');
-
- for (final child in element.childNodes) {
- if (!child.isSynthetic) {
- errorReporter.reportErrorForOffset(
- AngularWarningCode.NG_CONTENT_MUST_BE_EMPTY,
- element.openingSpan.offset,
- element.openingSpan.length);
- }
- }
-
- if (selectorAttrs.isEmpty) {
- ngContents.add(new NgContent(element.offset, element.length));
- return;
- }
-
- // We don't actually check if selectors.length > 2, because the parser
- // reports that.
- try {
- final selectorAttr = selectorAttrs.first;
- if (selectorAttr.value == null) {
- // TODO(mfairhust) report different error for a missing selector
- errorReporter.reportErrorForOffset(
- AngularWarningCode.CANNOT_PARSE_SELECTOR,
- selectorAttr.nameOffset,
- selectorAttr.name.length,
- ['missing']);
- } else if (selectorAttr.value == "") {
- // TODO(mfairhust) report different error for a missing selector
- errorReporter.reportErrorForOffset(
- AngularWarningCode.CANNOT_PARSE_SELECTOR,
- selectorAttr.valueOffset - 1,
- 2,
- ['missing']);
- } else {
- final selector = new SelectorParser(
- source, selectorAttr.valueOffset, selectorAttr.value)
- .parse();
- ngContents.add(new NgContent.withSelector(
- element.offset,
- element.length,
- selector,
- selectorAttr.valueOffset,
- selectorAttr.value.length));
- }
- } on SelectorParseError catch (e) {
- errorReporter.reportErrorForOffset(
- AngularWarningCode.CANNOT_PARSE_SELECTOR,
- e.offset,
- e.length,
- [e.message]);
- }
- }
-}
-
-class PrepareEventScopeVisitor extends AngularScopeVisitor {
- List<AbstractDirective> directives;
- final Template template;
- final Source templateSource;
- final Map<String, LocalVariable> localVariables;
- final Map<String, OutputElement> standardHtmlEvents;
- final TypeProvider typeProvider;
- final DartVariableManager dartVariableManager;
- final AnalysisErrorListener errorListener;
-
- PrepareEventScopeVisitor(
- this.standardHtmlEvents,
- this.template,
- this.templateSource,
- this.localVariables,
- this.typeProvider,
- this.dartVariableManager,
- this.errorListener);
-
- @override
- void visitElementInfo(ElementInfo elem) {
- directives = elem.directives;
- super.visitElementInfo(elem);
- }
-
- @override
- void visitStatementsBoundAttr(StatementsBoundAttribute attr) {
- if (attr.reductions.isNotEmpty &&
- attr.name != 'keyup' &&
- attr.name != 'keydown') {
- errorListener.onError(new AnalysisError(
- templateSource,
- attr.reductionsOffset,
- attr.reductionsLength,
- AngularWarningCode.EVENT_REDUCTION_NOT_ALLOWED));
- }
-
- var eventType = typeProvider.dynamicType;
- var matched = false;
-
- for (final directiveBinding in attr.parent.boundDirectives) {
- for (final output in directiveBinding.boundDirective.outputs) {
- //TODO what if this matches two directives?
- if (output.name == attr.name) {
- eventType = output.eventType;
- matched = true;
- final range = new SourceRange(attr.nameOffset, attr.name.length);
- template.addRange(range, output);
- directiveBinding.outputBindings.add(new OutputBinding(output, attr));
- }
- }
- }
-
- //standard HTML events bubble up, so everything supports them
- if (!matched) {
- final standardHtmlEvent = standardHtmlEvents[attr.name];
- if (standardHtmlEvent != null) {
- matched = true;
- eventType = standardHtmlEvent.eventType;
- final range = new SourceRange(attr.nameOffset, attr.name.length);
- template.addRange(range, standardHtmlEvent);
- attr.parent.boundStandardOutputs
- .add(new OutputBinding(standardHtmlEvent, attr));
- }
- }
-
- if (!matched && !isOnCustomTag(attr)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attr.nameOffset,
- attr.name.length,
- AngularWarningCode.NONEXIST_OUTPUT_BOUND,
- [attr.name]));
- }
-
- attr.localVariables = new HashMap.from(localVariables);
- final localVariableElement =
- dartVariableManager.newLocalVariableElement(-1, r'$event', eventType);
- final localVariable = new LocalVariable(
- r'$event', -1, 6, templateSource, localVariableElement);
- attr.localVariables[r'$event'] = localVariable;
- }
-
- @override
- void visitTemplateAttr(TemplateAttribute templateAttr) {
- directives = templateAttr.directives;
- super.visitTemplateAttr(templateAttr);
- }
-}
-
-/// We have to collect all vars and their types before we can resolve the
-/// bindings, since variables can be used before they are declared. This does
-/// that.
-///
-/// It loads each node's [localVariables] property so that the resolver has
-/// everything it needs, keeping those local variables around for autocomplete.
-/// As the scope is built up it is attached to the nodes -- and thanks to
-/// mutability + a shared reference, that works just fine.
-///
-/// However, `$event` vars require a copy of the scope, not a shared reference,
-/// so that the `$event` can be added. Therefore this visitor does not handle
-/// output bindings. That is [PrepareEventScopeVisitor]'s job, only to be
-/// performed after this step has completed.
-class PrepareScopeVisitor extends AngularScopeVisitor {
- /// The full map of names to internal variables in the current scope
- final Map<String, InternalVariable> internalVariables;
-
- /// The full map of names to local variables in the current scope
- final Map<String, LocalVariable> localVariables;
-
- final Template template;
- final Source templateSource;
- final TypeProvider typeProvider;
- final DartVariableManager dartVariableManager;
- final AnalysisErrorListener errorListener;
- final StandardAngular standardAngular;
-
- PrepareScopeVisitor(
- this.internalVariables,
- this.localVariables,
- this.template,
- this.templateSource,
- this.typeProvider,
- this.dartVariableManager,
- this.errorListener,
- this.standardAngular);
-
- @override
- void visitBorderScopeTemplateAttribute(TemplateAttribute attr) {
- // Border to the next scope. Make sure the virtual properties are bound
- // to the scope we're building now. But nothing else.
- visitTemplateAttr(attr);
- }
-
- @override
- void visitBorderScopeTemplateElement(ElementInfo element) {
- final exportAsMap = _defineExportAsVariables(element.directives);
- _defineReferenceVariablesForAttributes(
- element.directives, element.attributes, exportAsMap);
- super.visitBorderScopeTemplateElement(element);
- }
-
- @override
- void visitElementInScope(ElementInfo element) {
- final exportAsMap = _defineExportAsVariables(element.directives);
- // Regular element or component. Look for `#var`s.
- _defineReferenceVariablesForAttributes(
- element.directives, element.attributes, exportAsMap);
- super.visitElementInScope(element);
- }
-
- @override
- void visitExpressionBoundAttr(ExpressionBoundAttribute attr) {
- attr.localVariables = localVariables;
- }
-
- @override
- void visitMustache(Mustache mustache) {
- mustache.localVariables = localVariables;
- }
-
- @override
- void visitScopeRootElementWithTemplateAttribute(ElementInfo element) {
- final templateAttr = element.templateAttribute;
-
- final exportAsMap = _defineExportAsVariables(element.directives);
-
- // If this is how our scope begins, like we're within an ngFor, then
- // let the ngFor alter the current scope.
- for (final directive in templateAttr.directives) {
- _defineNgForVariables(templateAttr.virtualAttributes, directive);
- }
-
- _defineLetVariablesForAttributes(templateAttr.virtualAttributes);
-
- // Make sure the regular element also alters the current scope
- for (final directive in element.directives) {
- // This must be here for <template> tags.
- _defineNgForVariables(element.attributes, directive);
- }
-
- _defineReferenceVariablesForAttributes(
- element.directives, element.attributes, exportAsMap);
-
- super.visitScopeRootElementWithTemplateAttribute(element);
- }
-
- @override
- void visitScopeRootTemplateElement(ElementInfo element) {
- final exportAsMap = _defineExportAsVariables(element.directives);
- for (final directive in element.directives) {
- // This must be here for <template> tags.
- _defineNgForVariables(element.attributes, directive);
- }
-
- _defineReferenceVariablesForAttributes(
- element.directives, element.attributes, exportAsMap);
- _defineLetVariablesForAttributes(element.attributes);
-
- super.visitScopeRootTemplateElement(element);
- }
-
- /// Provides a map for 'exportAs' string to list ofclass element.
- /// Return type must be a class to later resolve conflicts should they exist.
- /// This is a shortlived variable existing only in the scope of
- /// element tag, therefore don't use [internalVariables].
- Map<String, List<InternalVariable>> _defineExportAsVariables(
- List<AbstractDirective> directives) {
- final exportAsMap = <String, List<InternalVariable>>{};
- for (final directive in directives) {
- final exportAs = directive.exportAs;
- if (exportAs != null && directive is AbstractClassDirective) {
- final name = exportAs.name;
- final type = directive.classElement.type;
- exportAsMap.putIfAbsent(name, () => <InternalVariable>[]);
- exportAsMap[name].add(new InternalVariable(name, exportAs, type));
- }
- }
- return exportAsMap;
- }
-
- /// Define reference variables [localVariables] for `#name` attributes.
- ///
- /// Begin by defining the type as 'dynamic'.
- /// In cases of *ngFor, this dynamic type is overwritten only if
- /// the value is defined within [internalVariables]. If value is null,
- /// it defaults to '$implicit'. If value is provided but isn't one of
- /// known implicit variables of ngFor, we can't throw an error since
- /// the value could still be defined.
- /// if '$implicit' is not defined within [internalVariables], we again
- /// default it to dynamicType.
- void _defineLetVariablesForAttributes(List<AttributeInfo> attributes) {
- for (final attribute in attributes) {
- var offset = attribute.nameOffset;
- var name = attribute.name;
- final value = attribute.value;
-
- if (name.startsWith('let-')) {
- final prefixLength = 'let-'.length;
- name = name.substring(prefixLength);
- offset += prefixLength;
- var type = typeProvider.dynamicType;
-
- final internalVar = internalVariables[value ?? r'$implicit'];
- if (internalVar != null) {
- type = internalVar.type;
- if (value != null) {
- template.addRange(
- new SourceRange(attribute.valueOffset, attribute.valueLength),
- internalVar.element,
- );
- }
- }
-
- final localVariableElement =
- dartVariableManager.newLocalVariableElement(-1, name, type);
- final localVariable = new LocalVariable(
- name, offset, name.length, templateSource, localVariableElement);
- localVariables[name] = localVariable;
- template.addRange(
- new SourceRange(offset, name.length),
- localVariable,
- );
- }
- }
- }
-
- void _defineNgForVariables(
- List<AttributeInfo> attributes, AbstractDirective directive) {
- // TODO(scheglov) Once Angular has a way to describe variables, reimplement
- // https://github.com/angular/angular/issues/4850
- if (directive.name == 'NgFor') {
- final dartElem =
- new DartElement((directive as AbstractClassDirective).classElement);
- internalVariables['index'] =
- new InternalVariable('index', dartElem, typeProvider.intType);
- internalVariables['even'] =
- new InternalVariable('even', dartElem, typeProvider.boolType);
- internalVariables['odd'] =
- new InternalVariable('odd', dartElem, typeProvider.boolType);
- internalVariables['first'] =
- new InternalVariable('first', dartElem, typeProvider.boolType);
- internalVariables['last'] =
- new InternalVariable('last', dartElem, typeProvider.boolType);
- for (final attribute in attributes) {
- if (attribute is ExpressionBoundAttribute &&
- attribute.name == 'ngForOf' &&
- attribute.expression != null) {
- final itemType = _getIterableItemType(attribute.expression);
- internalVariables[r'$implicit'] =
- new InternalVariable(r'$implicit', dartElem, itemType);
- }
- }
- }
- }
-
- /// Define reference variables [localVariables] for `#name` attributes.
- void _defineReferenceVariablesForAttributes(
- List<AbstractDirective> directives,
- List<AttributeInfo> attributes,
- Map<String, List<InternalVariable>> exportAsMap) {
- for (final attribute in attributes) {
- var offset = attribute.nameOffset;
- var name = attribute.name;
-
- // check if defines local variable
- final isRef = name.startsWith('ref-'); // not ng-for
- final isHash = name.startsWith('#'); // not ng-for
- final isVar =
- name.startsWith('var-'); // either (deprecated but still works)
- if (isHash || isVar || isRef) {
- final prefixLen = isHash ? 1 : 4;
- name = name.substring(prefixLen);
- offset += prefixLen;
- final refValue = attribute.value;
-
- // maybe an internal variable reference
- var type = typeProvider.dynamicType;
- AngularElement angularElement;
-
- if (refValue == null) {
- // Find the corresponding Component to assign reference to.
- for (final directive in directives) {
- if (directive is Component) {
- var classElement = directive.classElement;
- if (classElement.name == 'TemplateElement') {
- classElement = standardAngular.templateRef;
- }
- type = classElement.type;
- angularElement = new DartElement(classElement);
- break;
- }
- }
- } else {
- final internalVars = exportAsMap[refValue];
- if (internalVars == null || internalVars.isEmpty) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.valueOffset,
- attribute.value.length,
- AngularWarningCode.NO_DIRECTIVE_EXPORTED_BY_SPECIFIED_NAME,
- [attribute.value],
- ));
- } else if (internalVars.length > 1) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.valueOffset,
- attribute.value.length,
- AngularWarningCode.DIRECTIVE_EXPORTED_BY_AMBIGIOUS,
- [attribute.value],
- ));
- } else {
- final internalVar = internalVars[0];
- type = internalVar.type;
- angularElement = internalVar.element;
- }
- }
-
- if (attribute.value != null) {
- template.addRange(
- new SourceRange(attribute.valueOffset, attribute.valueLength),
- angularElement,
- );
- }
-
- final localVariableElement =
- dartVariableManager.newLocalVariableElement(offset, name, type);
- final localVariable = new LocalVariable(
- name, offset, name.length, templateSource, localVariableElement);
- localVariables[name] = localVariable;
- template.addRange(
- new SourceRange(localVariable.nameOffset, localVariable.name.length),
- localVariable,
- );
- }
- }
- }
-
- DartType _getIterableItemType(Expression expression) {
- final itemsType = expression.staticType;
- if (itemsType is InterfaceType) {
- final iteratorType = _lookupGetterReturnType(itemsType, 'iterator');
- if (iteratorType is InterfaceType) {
- final currentType = _lookupGetterReturnType(iteratorType, 'current');
- if (currentType != null) {
- return currentType;
- }
- }
- }
- return typeProvider.dynamicType;
- }
-
- /// Return the return type of the executable element with the given [name].
- /// May return `null` if the [type] does not define one.
- DartType _lookupGetterReturnType(InterfaceType type, String name) =>
- type.lookUpInheritedGetter(name)?.returnType;
-}
-
-/// Once all the scopes for all the expressions & statements are prepared, we're
-/// ready to resolve all the expressions inside and typecheck everything.
-///
-/// This will typecheck the contents of mustaches and attribute bindings against
-/// their scopes, and ensure that all attribute bindings exist on a directive and
-/// match the type of the binding where there is one. Then records references.
-class SingleScopeResolver extends AngularScopeVisitor {
- static var styleWithPercent = new Set<String>.from(<String>[
- 'border-bottom-left-radius',
- 'border-bottom-right-radius',
- 'border-image-slice',
- 'border-image-width',
- 'border-radius',
- 'border-top-left-radius',
- 'border-top-right-radius',
- 'bottom',
- 'font-size',
- 'height',
- 'left',
- 'line-height',
- 'margin',
- 'margin-bottom',
- 'margin-left',
- 'margin-right',
- 'margin-top',
- 'max-height',
- 'max-width',
- 'min-height',
- 'min-width',
- 'padding',
- 'padding-bottom',
- 'padding-left',
- 'padding-right',
- 'padding-top',
- 'right',
- 'text-indent',
- 'top',
- 'width',
- ]);
-
- /// Quick regex to match the spec, but doesn't handle unicode. They can start
- /// with a dash, but if so must be followed by an alphabetic or underscore or
- /// escaped character. Cannot start with a number.
- /// https://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
- static final RegExp _cssIdentifierRegexp =
- new RegExp(r"^(-?[a-zA-Z_]|\\.)([a-zA-Z0-9\-_]|\\.)*$");
- final Map<String, InputElement> standardHtmlAttributes;
- final List<Pipe> pipes;
- List<AbstractDirective> directives;
- View view;
- Template template;
- Source templateSource;
- TypeProvider typeProvider;
- TypeSystem typeSystem;
-
- AnalysisErrorListener errorListener;
-
- ErrorReporter errorReporter;
-
- /// The full map of names to local variables in the current context
- Map<String, LocalVariable> localVariables;
-
- SingleScopeResolver(
- this.standardHtmlAttributes,
- this.pipes,
- this.view,
- this.template,
- this.templateSource,
- this.typeProvider,
- this.typeSystem,
- this.errorListener,
- this.errorReporter);
-
- @override
- void visitElementInfo(ElementInfo element) {
- directives = element.directives;
- super.visitElementInfo(element);
- }
-
- @override
- void visitEmptyStarBinding(EmptyStarBinding binding) {
- // When the first virtual attribute matches a binding (like `ngIf`), flag it
- // if its empty. Only for the first. All others (like `trackBy`) are checked
- // in [EmbeddedDartParser.parseTemplateVirtualAttributes]
- if (!binding.isPrefix) {
- return;
- }
-
- // catch *ngIf without a value
- if (binding.parent.boundDirectives
- .map((binding) => binding.boundDirective)
- // TODO enable this again for all directives, not just NgIf
- .where((directive) => directive.name == "NgIf")
- .any((directive) =>
- directive.inputs.any((input) => input.name == binding.name))) {
- errorListener.onError(new AnalysisError(
- templateSource,
- binding.nameOffset,
- binding.name.length,
- AngularWarningCode.EMPTY_BINDING,
- [binding.name]));
- }
- }
-
- @override
- void visitExpressionBoundAttr(ExpressionBoundAttribute attribute) {
- localVariables = attribute.localVariables;
- _resolveDartExpression(attribute.expression);
- if (attribute.expression != null) {
- _recordAstNodeResolvedRanges(attribute.expression);
- }
-
- if (attribute.bound == ExpressionBoundType.twoWay) {
- _resolveTwoWayBoundAttributeValues(attribute);
- } else if (attribute.bound == ExpressionBoundType.input) {
- _resolveInputBoundAttributeValues(attribute);
- } else if (attribute.bound == ExpressionBoundType.clazz) {
- _resolveClassAttribute(attribute);
- } else if (attribute.bound == ExpressionBoundType.style) {
- _resolveStyleAttribute(attribute);
- } else if (attribute.bound == ExpressionBoundType.attr) {
- _resolveAttributeBoundAttribute(attribute);
- } else if (attribute.bound == ExpressionBoundType.attrIf) {
- _resolveAttributeBoundAttributeIf(attribute);
- }
- }
-
- @override
- void visitMustache(Mustache mustache) {
- localVariables = mustache.localVariables;
- _resolveDartExpression(mustache.expression);
- _recordAstNodeResolvedRanges(mustache.expression);
- }
-
- /// Resolve output-bound values of [attributes] as statements.
- @override
- void visitStatementsBoundAttr(StatementsBoundAttribute attribute) {
- localVariables = attribute.localVariables;
- _resolveDartExpressionStatements(attribute.statements);
- for (final statement in attribute.statements) {
- _recordAstNodeResolvedRanges(statement);
- }
- }
-
- @override
- void visitTemplateAttr(TemplateAttribute templateAttr) {
- directives = templateAttr.directives;
- super.visitTemplateAttr(templateAttr);
- }
-
- /// Resolve input-bound values of [attributes] as strings, if they match. Note,
- /// this does not report an error un unmatched attributes, but it will report
- /// the range, and ensure that input bindings are string-assingable.
- @override
- void visitTextAttr(TextAttribute attribute) {
- for (final directiveBinding in attribute.parent.boundDirectives) {
- for (final input in directiveBinding.boundDirective.inputs) {
- if (input.name == attribute.name) {
- if (!_checkTextAttrSecurity(attribute, input.securityContext)) {
- continue;
- }
-
- // Typecheck all but HTML inputs. For those, `width="10"` becomes
- // `setAttribute("width", "10")`, which is ok. But for directives and
- // components, this becomes `.someIntProp = "10"` which doesn't work.
- final inputType = input.setterType;
-
- // Some attr `foo` by itself, no brackets, as such, and no value, will
- // be bound "true" when its a boolean, which requires no typecheck.
- final booleanException =
- input.setterType.isSubtypeOf(typeProvider.boolType) &&
- attribute.value == null;
-
- if (!directiveBinding.boundDirective.isHtml &&
- !booleanException &&
- !typeSystem.isAssignableTo(typeProvider.stringType, inputType)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.nameOffset,
- attribute.name.length,
- AngularWarningCode.STRING_STYLE_INPUT_BINDING_INVALID,
- [input.name]));
- }
-
- final range =
- new SourceRange(attribute.nameOffset, attribute.name.length);
- template.addRange(range, input);
- directiveBinding.inputBindings
- .add(new InputBinding(input, attribute));
- }
- }
-
- for (final elem in directiveBinding.boundDirective.attributes) {
- if (elem.name == attribute.name) {
- final range =
- new SourceRange(attribute.nameOffset, attribute.name.length);
- template.addRange(range, elem);
- }
- }
- }
-
- final standardHtmlAttribute = standardHtmlAttributes[attribute.name];
- if (standardHtmlAttribute != null) {
- _checkTextAttrSecurity(attribute, standardHtmlAttribute.securityContext);
- // Don't typecheck html inputs. Those become attributes, not properties,
- // which means strings values are OK.
- final range =
- new SourceRange(attribute.nameOffset, attribute.name.length);
- template.addRange(range, standardHtmlAttribute);
- attribute.parent.boundStandardInputs
- .add(new InputBinding(standardHtmlAttribute, attribute));
- }
-
- // visit mustaches inside
- super.visitTextAttr(attribute);
- }
-
- bool _checkTextAttrSecurity(
- TextAttribute attribute, SecurityContext securityContext) {
- if (securityContext == null) {
- return true;
- }
- if (securityContext.sanitizationAvailable) {
- return true;
- }
- if (attribute.mustaches.isEmpty) {
- return true;
- }
-
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.valueOffset,
- attribute.value.length,
- AngularWarningCode.UNSAFE_BINDING,
- [securityContext.safeTypes.join(' or ')]));
- return false;
- }
-
- /// Get helpful description based on statement type to report in
- /// OUTPUT_STATEMENT_REQUIRES_EXPRESSION_STATEMENT
- String _getOutputStatementErrorDescription(Statement stmt) {
- final potentialToken = stmt.beginToken.keyword.toString().toLowerCase();
- if (potentialToken != "null") {
- return "token '$potentialToken'";
- } else {
- return stmt.runtimeType.toString().replaceFirst("Impl", "");
- }
- }
-
- bool _isCssIdentifier(String input) => _cssIdentifierRegexp.hasMatch(input);
-
- /// Record [ResolvedRange]s for the given [AstNode].
- void _recordAstNodeResolvedRanges(AstNode astNode) {
- final dartVariables = new HashMap<LocalVariableElement, LocalVariable>();
-
- for (final localVariable in localVariables.values) {
- dartVariables[localVariable.dartVariable] = localVariable;
- }
-
- if (astNode != null) {
- astNode.accept(new _DartReferencesRecorder(template, dartVariables));
- }
- }
-
- /// Resolve attributes of type [attribute.some-attribute]="someExpr"
- void _resolveAttributeBoundAttribute(ExpressionBoundAttribute attribute) {
- // TODO validate the type? Or against a dictionary?
- // note that the attribute name is valid by definition as it was discovered
- // within an attribute! (took me a while to realize why I couldn't make any
- // failing tests for this)
- }
-
- /// Resolve attributes of type [attribute.some-attribute]="someExpr"
- void _resolveAttributeBoundAttributeIf(ExpressionBoundAttribute attribute) {
- if (attribute.parent is! ElementInfo) {
- assert(false, 'Got an attr-if bound attribute on non element! Aborting!');
- return;
- }
-
- final parent = attribute.parent as ElementInfo;
-
- // For the [attr.foo.if] attribute, find the matching [attr.foo] attribute.
- final matchingAttr = parent.attributes
- .where((attr) =>
- attr is ExpressionBoundAttribute &&
- attr.bound == ExpressionBoundType.attr)
- .firstWhere((attrAttr) => attrAttr.name == attribute.name,
- orElse: () => null);
-
- // Error: no matching attribute to make conditional via this attr-if.
- if (matchingAttr == null) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.nameOffset,
- attribute.name.length,
- AngularWarningCode.UNMATCHED_ATTR_IF_BINDING,
- [attribute.name]));
- return;
- }
-
- // Add navigation from [attribute] (`[attr.foo.if]`) to [matchingAttr]
- // (`[attr.foo]`).
- final range = new SourceRange(attribute.nameOffset, attribute.name.length);
- template.addRange(
- range,
- new AngularElementImpl('attr.${attribute.name}',
- matchingAttr.nameOffset, matchingAttr.name.length, templateSource));
-
- // Ensure the if condition was a boolean.
- if (attribute.expression != null &&
- !typeSystem.isAssignableTo(
- attribute.expression.staticType, typeProvider.boolType)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.valueOffset,
- attribute.value.length,
- AngularWarningCode.ATTR_IF_BINDING_TYPE_ERROR,
- [attribute.name]));
- }
- }
-
- /// Resolve attributes of type [class.some-class]="someBoolExpr", ensuring
- /// the class is a valid css identifier and that the expression is of boolean
- /// type
- void _resolveClassAttribute(ExpressionBoundAttribute attribute) {
- if (!_isCssIdentifier(attribute.name)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.nameOffset,
- attribute.name.length,
- AngularWarningCode.INVALID_HTML_CLASSNAME,
- [attribute.name]));
- }
-
- // half-complete-code case: ensure the expression is actually there
- if (attribute.expression != null &&
- !typeSystem.isAssignableTo(
- attribute.expression.staticType ?? typeProvider.dynamicType,
- typeProvider.boolType)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.valueOffset,
- attribute.value.length,
- AngularWarningCode.CLASS_BINDING_NOT_BOOLEAN,
- ));
- }
- }
-
- /// Resolve the given [AstNode] ([expression] or [statement]) and report errors.
- void _resolveDartAstNode(AstNode astNode, bool acceptAssignment) {
- final classElement = view.classElement;
- final library = classElement.library;
- {
- final visitor = new LocalElementBuilder.forDanglingExpression();
- astNode.accept(visitor);
- }
- {
- final visitor = new TypeResolverVisitor(
- library, view.source, typeProvider, errorListener);
- astNode.accept(visitor);
- }
- final inheritanceManager2 = new InheritanceManager2(typeSystem);
- final resolver = new AngularResolverVisitor(inheritanceManager2, library,
- templateSource, typeProvider, errorListener,
- pipes: pipes);
- // fill the name scope
- final classScope = new ClassScope(resolver.nameScope, classElement);
- final localScope = new EnclosedScope(classScope);
- resolver
- ..nameScope = localScope
- ..enclosingClass = classElement;
- localVariables.values
- .forEach((local) => localScope.define(local.dartVariable));
- // do resolve
- astNode.accept(resolver);
- // verify
- final verifier = new ErrorVerifier(
- errorReporter, library, typeProvider, inheritanceManager2, true)
- ..enclosingClass = classElement;
- astNode.accept(verifier);
- // Check for concepts illegal to templates (for instance function literals).
- final angularSubsetChecker = new AngularSubsetVisitor(
- errorReporter: errorReporter,
- acceptAssignment: acceptAssignment,
- owningComponent: view.component);
- astNode.accept(angularSubsetChecker);
- }
-
- /// Resolve the Dart expression with the given [code] at [offset].
- void _resolveDartExpression(Expression expression) {
- if (expression != null) {
- _resolveDartAstNode(expression, false);
- }
- }
-
- /// Resolve the Dart ExpressionStatement with the given [code] at [offset].
- void _resolveDartExpressionStatements(List<Statement> statements) {
- for (final statement in statements) {
- if (statement is! ExpressionStatement && statement is! EmptyStatement) {
- errorListener.onError(new AnalysisError(
- templateSource,
- statement.offset,
- (statement.endToken.type == TokenType.SEMICOLON)
- ? statement.length - 1
- : statement.length,
- AngularWarningCode.OUTPUT_STATEMENT_REQUIRES_EXPRESSION_STATEMENT,
- [_getOutputStatementErrorDescription(statement)]));
- } else {
- _resolveDartAstNode(statement, true);
- }
- }
- }
-
- /// Resolve input-bound values of [attributes] as expressions.
- /// Also used by _resolveTwoWwayBoundAttributeValues.
- void _resolveInputBoundAttributeValues(ExpressionBoundAttribute attribute) {
- var inputMatched = false;
-
- // Check if input exists on bound directives.
- for (final directiveBinding in attribute.parent.boundDirectives) {
- for (final input in directiveBinding.boundDirective.inputs) {
- if (input.name == attribute.name) {
- _typecheckMatchingInput(attribute, input);
-
- final range =
- new SourceRange(attribute.nameOffset, attribute.name.length);
- template.addRange(range, input);
- directiveBinding.inputBindings
- .add(new InputBinding(input, attribute));
-
- inputMatched = true;
- }
- }
- }
-
- // Check if input exists from standard html attributes.
- if (!inputMatched) {
- final standardHtmlAttribute = standardHtmlAttributes[attribute.name];
- if (standardHtmlAttribute != null) {
- _typecheckMatchingInput(attribute, standardHtmlAttribute);
- final range =
- new SourceRange(attribute.nameOffset, attribute.name.length);
- template.addRange(range, standardHtmlAttribute);
- attribute.parent.boundStandardInputs
- .add(new InputBinding(standardHtmlAttribute, attribute));
-
- inputMatched = true;
- }
- }
-
- if (!inputMatched && !isOnCustomTag(attribute)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.nameOffset,
- attribute.name.length,
- AngularWarningCode.NONEXIST_INPUT_BOUND,
- [attribute.name]));
- }
- }
-
- /// Resolve attributes of type [style.color]="someExpr" and
- /// [style.background-width.px]="someNumExpr" which bind a css style property
- /// with optional units.
- void _resolveStyleAttribute(ExpressionBoundAttribute attribute) {
- var cssPropertyName = attribute.name;
- final dotpos = attribute.name.indexOf('.');
- if (dotpos != -1) {
- cssPropertyName = attribute.name.substring(0, dotpos);
- final cssUnitName = attribute.name.substring(dotpos + '.'.length);
- var validUnitName =
- styleWithPercent.contains(cssPropertyName) && cssUnitName == '%';
- validUnitName = validUnitName || _isCssIdentifier(cssUnitName);
- if (!validUnitName) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.nameOffset + dotpos + 1,
- cssUnitName.length,
- AngularWarningCode.INVALID_CSS_UNIT_NAME,
- [cssUnitName]));
- }
- // half-complete-code case: ensure the expression is actually there
- if (attribute.expression != null &&
- !typeSystem.isAssignableTo(
- attribute.expression.staticType ?? typeProvider.dynamicType,
- typeProvider.numType)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.valueOffset,
- attribute.value.length,
- AngularWarningCode.CSS_UNIT_BINDING_NOT_NUMBER));
- }
- }
-
- if (!_isCssIdentifier(cssPropertyName)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.nameOffset,
- cssPropertyName.length,
- AngularWarningCode.INVALID_CSS_PROPERTY_NAME,
- [cssPropertyName]));
- }
- }
-
- /// Resolve TwoWay-bound values of [attributes] as expressions.
- void _resolveTwoWayBoundAttributeValues(ExpressionBoundAttribute attribute) {
- var outputMatched = false;
-
- // empty attribute error registered in converter. Just don't crash.
- if (attribute.expression != null && !attribute.expression.isAssignable) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.valueOffset,
- attribute.value.length,
- AngularWarningCode.TWO_WAY_BINDING_NOT_ASSIGNABLE));
- }
-
- for (final directiveBinding in attribute.parent.boundDirectives) {
- for (final output in directiveBinding.boundDirective.outputs) {
- if (output.name == "${attribute.name}Change") {
- outputMatched = true;
- final eventType = output.eventType;
- directiveBinding.outputBindings
- .add(new OutputBinding(output, attribute));
-
- // half-complete-code case: ensure the expression is actually there
- if (attribute.expression != null &&
- !typeSystem.isAssignableTo(
- eventType,
- attribute.expression.staticType ??
- typeProvider.dynamicType)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.valueOffset,
- attribute.value.length,
- AngularWarningCode.TWO_WAY_BINDING_OUTPUT_TYPE_ERROR, [
- output.eventType,
- attribute.expression.staticType ?? typeProvider.dynamicType
- ]));
- }
- }
- }
- }
-
- if (!outputMatched && !isOnCustomTag(attribute)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attribute.nameOffset,
- attribute.name.length,
- AngularWarningCode.NONEXIST_TWO_WAY_OUTPUT_BOUND,
- [attribute.name, "${attribute.name}Change"]));
- }
-
- _resolveInputBoundAttributeValues(attribute);
- }
-
- void _typecheckMatchingInput(
- ExpressionBoundAttribute attr, InputElement input) {
- // half-complete-code case: ensure the expression is actually there
- if (attr.expression != null) {
- final attrType = attr.expression.staticType ?? typeProvider.dynamicType;
- final inputType = input.setterType;
- final securityContext = input.securityContext;
-
- if (securityContext != null) {
- if (securityContext.safeTypes
- .any((safeType) => typeSystem.isAssignableTo(attrType, safeType))) {
- return;
- } else if (!securityContext.sanitizationAvailable) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attr.valueOffset,
- attr.value.length,
- AngularWarningCode.UNSAFE_BINDING,
- [securityContext.safeTypes.join(' or ')]));
- return;
- }
- }
-
- if (!typeSystem.isAssignableTo(attrType, inputType)) {
- errorListener.onError(new AnalysisError(
- templateSource,
- attr.valueOffset,
- attr.value.length,
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR,
- [attrType, inputType]));
- }
- }
- }
-}
-
-/// [TemplateResolver]s resolve [Template]s.
-class TemplateResolver {
- final TypeProvider typeProvider;
- final TypeSystem typeSystem;
- final List<Component> standardHtmlComponents;
- final Map<String, OutputElement> standardHtmlEvents;
- final Map<String, InputElement> standardHtmlAttributes;
- final AngularOptions options;
- final AnalysisErrorListener errorListener;
- final StandardAngular standardAngular;
- final StandardHtml standardHtml;
-
- Template template;
- View view;
- Source templateSource;
- ErrorReporter errorReporter;
-
- /// The full map of names to internal variables in the current template.
- var internalVariables = new HashMap<String, InternalVariable>();
-
- /// The full map of names to local variables in the current template.
- var localVariables = new HashMap<String, LocalVariable>();
-
- TemplateResolver(
- this.typeProvider,
- this.typeSystem,
- this.standardHtmlComponents,
- this.standardHtmlEvents,
- this.standardHtmlAttributes,
- this.standardAngular,
- this.standardHtml,
- this.errorListener,
- this.options);
-
- void resolve(Template template) {
- this.template = template;
- view = template.view;
- templateSource = view.templateSource;
- errorReporter = new ErrorReporter(errorListener, templateSource);
-
- final root = template.ast;
-
- final allDirectives = <AbstractDirective>[]
- ..addAll(standardHtmlComponents)
- ..addAll(view.directives);
-
- final directiveResolver = new DirectiveResolver(
- allDirectives,
- templateSource,
- template,
- standardAngular,
- standardHtml,
- errorReporter,
- errorListener,
- new Set<String>.from(options.customTagNames));
- root.accept(directiveResolver);
- final contentResolver =
- new ComponentContentResolver(templateSource, template, errorListener);
- root.accept(contentResolver);
-
- _resolveScope(root);
- }
-
- /// Resolve the given [element]. This will either be a template or the root of
- /// the template, meaning it has its own scope. We have to resolve the
- /// outermost scopes first so that ngFor variables have types.
- ///
- /// See the comment block for [PrepareScopeVisitor] for the most detailed
- /// breakdown of what we do and why.
- ///
- /// Requires that we've already resolved the directives down the tree.
- void _resolveScope(ElementInfo element) {
- if (element == null) {
- return;
- }
- // apply template attributes
- final oldLocalVariables = localVariables;
- final oldInternalVariables = internalVariables;
- internalVariables = new HashMap.from(internalVariables);
- localVariables = new HashMap.from(localVariables);
- try {
- final dartVarManager =
- new DartVariableManager(template, templateSource, errorListener);
- // Prepare the scopes
- element
- ..accept(new PrepareScopeVisitor(
- internalVariables,
- localVariables,
- template,
- templateSource,
- typeProvider,
- dartVarManager,
- errorListener,
- standardAngular))
- // Load $event into the scopes
- ..accept(new PrepareEventScopeVisitor(
- standardHtmlEvents,
- template,
- templateSource,
- localVariables,
- typeProvider,
- dartVarManager,
- errorListener))
- // Resolve the scopes
- ..accept(new SingleScopeResolver(
- standardHtmlAttributes,
- view.pipes,
- view,
- template,
- templateSource,
- typeProvider,
- typeSystem,
- errorListener,
- errorReporter));
-
- // Now the next scope is ready to be resolved
- final tplSearch = new NextTemplateElementsSearch();
- element.accept(tplSearch);
- for (final templateElement in tplSearch.results) {
- _resolveScope(templateElement);
- }
- } finally {
- internalVariables = oldInternalVariables;
- localVariables = oldLocalVariables;
- }
- }
-}
-
-/// An [AstVisitor] that records references to Dart [Element]s into
-/// the given [template].
-class _DartReferencesRecorder extends RecursiveAstVisitor {
- final Map<Element, AngularElement> dartToAngularMap;
- final Template template;
-
- _DartReferencesRecorder(this.template, this.dartToAngularMap);
-
- @override
- void visitSimpleIdentifier(SimpleIdentifier node) {
- final dartElement = node.staticElement;
- if (dartElement != null) {
- final angularElement =
- dartToAngularMap[dartElement] ?? new DartElement(dartElement);
- final range = new SourceRange(node.offset, node.length);
- template.addRange(range, angularElement);
- }
- }
-}
-
-/// Workaround for "This mixin application is invalid because all of the
-/// constructors in the base class 'ResolverVisitor' have optional parameters."
-/// in the definition of [AngularResolverVisitor].
-///
-/// See https://github.com/dart-lang/sdk/issues/15101 for details
-class _IntermediateResolverVisitor extends ResolverVisitor {
- _IntermediateResolverVisitor(
- InheritanceManager2 inheritanceManager2,
- LibraryElement library,
- Source source,
- TypeProvider typeProvider,
- AnalysisErrorListener errorListener)
- : super(
- inheritanceManager2, library, source, typeProvider, errorListener);
-}
diff --git a/angular_analyzer_plugin/lib/src/selector.dart b/angular_analyzer_plugin/lib/src/selector.dart
deleted file mode 100644
index 989ead9..0000000
--- a/angular_analyzer_plugin/lib/src/selector.dart
+++ /dev/null
@@ -1,868 +0,0 @@
-library angular2.src.analysis.analyzer_plugin.src.selector;
-
-import 'dart:collection';
-
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/strings.dart';
-import 'package:meta/meta.dart';
-
-const _attributeEqualsValueRegexStr = // comment here for formatting:
- r'(\^=|\*=|=)' // capture which type of '=' operator
- // include values. Don't capture here, they contain captures themselves.
- '(?:$_attributeNoQuoteValueRegexStr|$_attributeQuotedValueRegexStr)';
-
-const _attributeNameRegexStr = r'[-\w]+|\*';
-
-const _attributeNoQuoteValueRegexStr =
- r'''([^\]'"]*)''' // Capture anything but ']' or a quote.
- ;
-
-const _attributeQuotedValueRegexStr = // comment here for formatting:
- r"'([^\]']*)'" // Capture the contents of a single quoted string
- r'|' // or
- r'"([^\]"]*)"' // Capture the contents of a double quoted string
- ;
-
-const _attributeRegexStr = // comment here for formatting:
- r'\[' // begins with '['
- '($_attributeNameRegexStr)' // capture the attribute name
- '(?:$_attributeEqualsValueRegexStr)?' // non-capturing optional value
- r'\]' // ends with ']'
- ;
-
-/// The [Selector] that matches all of the given [selectors].
-class AndSelector extends Selector {
- final List<Selector> selectors;
-
- AndSelector(this.selectors);
-
- @override
- bool availableTo(ElementView element) =>
- selectors.every((selector) => selector.availableTo(element));
-
- @override
- List<AngularElement> getAttributes(ElementView element) =>
- selectors.expand((selector) => selector.getAttributes(element)).toList();
-
- @override
- SelectorMatch match(ElementView element, Template template) {
- // Invalid selector case, should NOT match all.
- if (selectors.isEmpty) {
- return SelectorMatch.NoMatch;
- }
-
- var onSuccess = SelectorMatch.NonTagMatch;
- for (final selector in selectors) {
- final theMatch = selector.match(element, null);
- if (theMatch == SelectorMatch.TagMatch) {
- onSuccess = theMatch;
- } else if (theMatch == SelectorMatch.NoMatch) {
- return SelectorMatch.NoMatch;
- }
- }
- for (final selector in selectors) {
- selector.match(element, template);
- }
- return onSuccess;
- }
-
- @override
- void recordElementNameSelectors(List<ElementNameSelector> recordingList) {
- selectors.forEach(
- (selector) => selector.recordElementNameSelectors(recordingList));
- }
-
- @override
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context) {
- for (final selector in selectors) {
- // ignore: parameter_assignments
- context = selector.refineTagSuggestions(context);
- }
- return context;
- }
-
- @override
- String toString() => selectors.join(' && ');
-}
-
-/// The [AttributeContainsSelector] that matches elements that have attributes
-/// with the given name, and that attribute contains the value of the selector.
-class AttributeContainsSelector extends AttributeSelectorBase {
- @override
- final AngularElement nameElement;
- final String value;
-
- AttributeContainsSelector(this.nameElement, this.value);
-
- @override
- bool matchValue(String attributeValue) => attributeValue.contains(value);
-
- @override
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context) {
- for (final tag in context) {
- tag.setAttribute(nameElement.name, value: value);
- }
- return context;
- }
-
- @override
- String toString() {
- final name = nameElement.name;
- return '[$name*=$value]';
- }
-}
-
-/// The [Selector] that matches elements that have an attribute with the
-/// given name, and (optionally) with the given value;
-class AttributeSelector extends AttributeSelectorBase {
- @override
- final AngularElement nameElement;
- final String value;
-
- AttributeSelector(this.nameElement, this.value);
-
- @override
- List<AngularElement> getAttributes(ElementView element) =>
- match(element, null) == SelectorMatch.NonTagMatch ? [] : [nameElement];
-
- @override
- bool matchValue(String attributeValue) =>
- value == null || attributeValue == value;
-
- @override
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context) {
- for (final tag in context) {
- tag.setAttribute(nameElement.name, value: value);
- }
- return context;
- }
-
- @override
- String toString() {
- final name = nameElement.name;
- if (value != null) {
- return '[$name=$value]';
- }
- return '[$name]';
- }
-}
-
-abstract class AttributeSelectorBase extends Selector {
- AngularElement get nameElement;
-
- @override
- bool availableTo(ElementView element) =>
- !element.attributes.keys.contains(findAttribute(element)) ||
- match(element, null) != SelectorMatch.NoMatch;
-
- String findAttribute(ElementView element) => nameElement.name;
-
- @override
- List<AngularElement> getAttributes(ElementView element) =>
- element.attributes.keys.contains(findAttribute(element))
- ? []
- : [nameElement];
-
- @override
- SelectorMatch match(ElementView element, Template template) {
- SourceRange attributeSpan;
- String attributeValue;
-
- // Different selectors may find attributes differently
- final matchedName = findAttribute(element);
- if (matchedName == null) {
- return SelectorMatch.NoMatch;
- }
-
- attributeSpan = element.attributeNameSpans[matchedName];
- attributeValue = element.attributes[matchedName];
-
- if (attributeSpan == null) {
- return SelectorMatch.NoMatch;
- }
-
- // Different selectors may match the attribute value differently
- if (!matchValue(attributeValue)) {
- return SelectorMatch.NoMatch;
- }
-
- // OK
- if (template != null) {
- template.addRange(
- new SourceRange(attributeSpan.offset, attributeSpan.length),
- nameElement);
- }
- return SelectorMatch.NonTagMatch;
- }
-
- bool matchValue(String attributeValue);
-
- @override
- void recordElementNameSelectors(List<ElementNameSelector> recordingList) {
- // empty
- }
-}
-
-/// The [Selector] that matches elements that have an attribute with any name,
-/// and with contents that match the given regex.
-class AttributeStartsWithSelector extends AttributeSelectorBase {
- @override
- final AngularElement nameElement;
-
- final String value;
-
- AttributeStartsWithSelector(this.nameElement, this.value);
-
- @override
- bool matchValue(String attributeValue) => attributeValue.startsWith(value);
-
- @override
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context) =>
- context;
-
- @override
- String toString() => '[$nameElement^=$value]';
-}
-
-/// The [Selector] that matches elements that have an attribute with any name,
-/// and with contents that match the given regex.
-class AttributeValueRegexSelector extends Selector {
- final String regexpStr;
- final RegExp regexp;
-
- AttributeValueRegexSelector(this.regexpStr) : regexp = new RegExp(regexpStr);
-
- @override
- bool availableTo(ElementView element) =>
- match(element, null) == SelectorMatch.NonTagMatch;
-
- @override
- List<AngularElement> getAttributes(ElementView element) => [];
-
- @override
- SelectorMatch match(ElementView element, Template template) {
- for (final value in element.attributes.values) {
- if (regexp.hasMatch(value)) {
- return SelectorMatch.NonTagMatch;
- }
- }
- return SelectorMatch.NoMatch;
- }
-
- @override
- void recordElementNameSelectors(List<ElementNameSelector> recordingList) {
- // empty
- }
-
- @override
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context) =>
- context;
-
- @override
- String toString() => '[*=$regexpStr]';
-}
-
-/// The [Selector] that matches elements with the given (static) classes.
-class ClassSelector extends Selector {
- final AngularElement nameElement;
-
- ClassSelector(this.nameElement);
-
- @override
- bool availableTo(ElementView element) => true;
-
- // Always return true - classes can always be added to satisfy without
- // having to remove or change existing classes.
- @override
- List<AngularElement> getAttributes(ElementView element) => [];
-
- @override
- SelectorMatch match(ElementView element, Template template) {
- final name = nameElement.name;
- final val = element.attributes['class'];
- // no 'class' attribute
- if (val == null) {
- return SelectorMatch.NoMatch;
- }
- // no such class
- if (!val.split(' ').contains(name)) {
- return SelectorMatch.NoMatch;
- }
- // prepare index of "name" int the "class" attribute value
- int index;
- if (val == name || val.startsWith('$name ')) {
- index = 0;
- } else if (val.endsWith(' $name')) {
- index = val.length - name.length;
- } else {
- index = val.indexOf(' $name ') + 1;
- }
- // add resolved range
- final valueOffset = element.attributeValueSpans['class'].offset;
- final offset = valueOffset + index;
- template?.addRange(new SourceRange(offset, name.length), nameElement);
- return SelectorMatch.NonTagMatch;
- }
-
- @override
- void recordElementNameSelectors(List<ElementNameSelector> recordingList) {
- // empty
- }
-
- @override
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context) {
- for (final tag in context) {
- tag.addClass(nameElement.name);
- }
- return context;
- }
-
- @override
- String toString() => '.${nameElement.name}';
-}
-
-/// The [Selector] that checks a TextNode for contents by a regex
-class ContainsSelector extends Selector {
- final String regex;
-
- ContainsSelector(this.regex);
-
- @override
- bool availableTo(ElementView element) => false;
-
- @override
- List<AngularElement> getAttributes(ElementView element) => [];
-
- /// TODO check against actual text contents so we know which :contains
- /// directives were used (for when we want to advise removal of unused
- /// directives).
- ///
- /// We could also highlight the matching region in the text node with a color
- /// so users know it was applied.
- ///
- /// Not sure what else we could do.
- ///
- /// Never matches elements. Only matches [TextNode]s. Return false for now.
- @override
- SelectorMatch match(ElementView element, Template template) =>
- SelectorMatch.NoMatch;
-
- @override
- void recordElementNameSelectors(List<ElementNameSelector> recordingList) {
- // empty
- }
-
- @override
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context) =>
- context;
-
- @override
- String toString() => ":contains($regex)";
-}
-
-/// The element name based selector.
-class ElementNameSelector extends Selector {
- final AngularElement nameElement;
-
- ElementNameSelector(this.nameElement);
-
- @override
- bool availableTo(ElementView element) =>
- nameElement.name == element.localName;
-
- @override
- List<AngularElement> getAttributes(ElementView element) => [];
-
- @override
- SelectorMatch match(ElementView element, Template template) {
- final name = nameElement.name;
- // match
- if (element.localName != name) {
- return SelectorMatch.NoMatch;
- }
- // done if no template
- if (template == null) {
- return SelectorMatch.TagMatch;
- }
- // record resolution
- if (element.openingNameSpan != null) {
- template.addRange(element.openingNameSpan, nameElement);
- }
- if (element.closingNameSpan != null) {
- template.addRange(element.closingNameSpan, nameElement);
- }
- return SelectorMatch.TagMatch;
- }
-
- @override
- void recordElementNameSelectors(List<ElementNameSelector> recordingList) {
- recordingList.add(this);
- }
-
- @override
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context) {
- for (final tag in context) {
- tag.name = nameElement.name;
- }
- return context;
- }
-
- @override
- String toString() => nameElement.name;
-}
-
-abstract class ElementView {
- Map<String, SourceRange> get attributeNameSpans;
- Map<String, String> get attributes;
- Map<String, SourceRange> get attributeValueSpans;
- SourceRange get closingNameSpan;
- SourceRange get closingSpan;
- String get localName;
- SourceRange get openingNameSpan;
- SourceRange get openingSpan;
-}
-
-/// Where possible it is good to be able to suggest a fully completed html tag to
-/// match a selector. This has a few challenges: the selector may match multiple
-/// things, it may not include any tag name to go off of at all. It may lend
-/// itself to infinite suggestions (such as matching a regex), and parts of its
-/// selector may cancel other parts out leading to invalid suggestions (such as
-/// [prop=this][prop=thistoo]), especially in the presence of heavy booleans.
-///
-/// This doesn't track :not, so it may still suggest invalid things, but in
-/// general the goal of this class is that its an empty shell which tracks
-/// conflicting information.
-///
-/// Each selector takes in the current round of suggestions in
-/// [refineTagSuggestions], and may return more suggestions than it got
-/// originally (as in OR). At the end, all valid selectors can be checked for
-/// validity.
-///
-/// Selector.suggestTags() handles creating a seed HtmlTagForSelector and
-/// stripping invalid suggestions at the end, potentially resulting in none.
-class HtmlTagForSelector {
- String _name;
- Map<String, String> _attributes = <String, String>{};
- bool _isValid = true;
- Set<String> _classes = new HashSet<String>();
-
- bool get isValid => _name != null && _isValid && _classAttrValid;
-
- String get name => _name;
-
- set name(String name) {
- if (_name != null && _name != name) {
- _isValid = false;
- } else {
- _name = name;
- }
- }
-
- bool get _classAttrValid => _classes.isEmpty || _attributes["class"] == null
- ? true
- : _classes.length == 1 && _classes.first == _attributes["class"];
-
- void addClass(String classname) {
- _classes.add(classname);
- }
-
- HtmlTagForSelector clone() => new HtmlTagForSelector()
- ..name = _name
- .._attributes = (<String, String>{}..addAll(_attributes))
- .._isValid = _isValid
- .._classes = new HashSet<String>.from(_classes);
-
- void setAttribute(String name, {String value}) {
- if (_attributes.containsKey(name)) {
- if (value != null) {
- if (_attributes[name] != null && _attributes[name] != value) {
- _isValid = false;
- } else {
- _attributes[name] = value;
- }
- }
- } else {
- _attributes[name] = value;
- }
- }
-
- @override
- String toString() {
- final keepClassAttr = _classes.isEmpty;
-
- final attrStrs = <String>[];
- _attributes.forEach((k, v) {
- // in the case of [class].myclass don't create multiple class attrs
- if (k != "class" || keepClassAttr) {
- attrStrs.add(v == null ? k : '$k="$v"');
- }
- });
-
- if (_classes.isNotEmpty) {
- final classesList = (<String>[]
- ..addAll(_classes)
- ..sort())
- .join(' ');
- attrStrs.add('class="$classesList"');
- }
-
- attrStrs.sort();
-
- return (['<$_name']..addAll(attrStrs)).join(' ');
- }
-}
-
-/// The [Selector] that confirms the inner [Selector] condition does NOT match
-class NotSelector extends Selector {
- final Selector condition;
-
- NotSelector(this.condition);
-
- @override
- bool availableTo(ElementView element) =>
- condition.match(element, null) == SelectorMatch.NoMatch;
-
- @override
- List<AngularElement> getAttributes(ElementView element) => [];
-
- @override
- SelectorMatch match(ElementView element, Template template) =>
- condition.match(element, template) == SelectorMatch.NoMatch
- ? SelectorMatch.NonTagMatch
- : SelectorMatch.NoMatch;
-
- @override
- void recordElementNameSelectors(List<ElementNameSelector> recordingList) {
- // empty
- }
-
- @override
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context) =>
- context;
-
- @override
- String toString() => ":not($condition)";
-}
-
-/// The [Selector] that matches one of the given [selectors].
-class OrSelector extends Selector {
- final List<Selector> selectors;
-
- OrSelector(this.selectors);
-
- @override
- bool availableTo(ElementView element) =>
- selectors.any((selector) => selector.availableTo(element));
-
- @override
- List<AngularElement> getAttributes(ElementView element) =>
- selectors.expand((selector) => selector.getAttributes(element)).toList();
-
- @override
- SelectorMatch match(ElementView element, Template template) {
- var onNoTagMatch = SelectorMatch.NoMatch;
- for (final selector in selectors) {
- final theMatch = selector.match(element, template);
- if (theMatch == SelectorMatch.TagMatch) {
- return SelectorMatch.TagMatch;
- } else if (theMatch == SelectorMatch.NonTagMatch) {
- onNoTagMatch = SelectorMatch.NonTagMatch;
- }
- }
- return onNoTagMatch;
- }
-
- @override
- void recordElementNameSelectors(List<ElementNameSelector> recordingList) {
- selectors.forEach(
- (selector) => selector.recordElementNameSelectors(recordingList));
- }
-
- @override
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context) {
- final response = <HtmlTagForSelector>[];
- for (final selector in selectors) {
- final newContext = context.map((t) => t.clone()).toList();
- response.addAll(selector.refineTagSuggestions(newContext));
- }
-
- return response;
- }
-
- @override
- String toString() => selectors.join(' || ');
-}
-
-/// The base class for all Angular selectors.
-abstract class Selector {
- String originalString;
- int offset;
-
- /// Check whether the given [element] can potentially match with
- /// this selector. Or simply put, if there is no violation
- /// then the given [element] is 'availableTo' this selector without
- /// contradiction.
- ///
- /// Policy is 'availableTo' is true if selector can match
- /// without having to change/remove existing decorator.
- bool availableTo(ElementView element);
-
- /// Returns a list of all [AngularElement]s where each is an attribute name,
- /// and each attribute could be added to [element] and the selector would
- /// still be [availableTo] it.
- List<AngularElement> getAttributes(ElementView element);
-
- /// Check whether the given [element] matches this selector.
- /// If yes, then record resolved ranges into [template].
- SelectorMatch match(ElementView element, Template template);
-
- void recordElementNameSelectors(List<ElementNameSelector> recordingList);
-
- /// See [HtmlTagForSelector] for info on what this does.
- List<HtmlTagForSelector> refineTagSuggestions(
- List<HtmlTagForSelector> context);
-
- /// See [HtmlTagForSelector] for info on what this does. Selectors should NOT
- /// override this method, but rather [refineTagSuggestions].
- List<HtmlTagForSelector> suggestTags() {
- // create a seed tag: ORs will copy this, everything else modifies. Each
- // selector returns the newest set of tags to be transformed.
- final tags = [new HtmlTagForSelector()];
- return refineTagSuggestions(tags).where((t) => t.isValid).toList();
- }
-} // chars with dash, may end with or be just '*'.
-
-enum SelectorMatch { NoMatch, NonTagMatch, TagMatch }
-
-/// A name that is a part of a [Selector].
-class SelectorName extends AngularElementImpl {
- SelectorName(String name, int nameOffset, int nameLength, Source source)
- : super(name, nameOffset, nameLength, source);
-}
-
-class SelectorParseError extends FormatException {
- int length;
- SelectorParseError(String message, String source, int offset, this.length)
- : super(message, source, offset);
-}
-
-class SelectorParser {
- static const Map<int, _SelectorRegexMatch> matchIndexToType =
- const <int, _SelectorRegexMatch>{
- 1: _SelectorRegexMatch.NotStart,
- 2: _SelectorRegexMatch.Tag,
- 3: _SelectorRegexMatch.Class,
- 4: _SelectorRegexMatch.Attribute, // no quotes
- // 5 is part of Attribute. Not a match type.
- // 6 is part of Attribute. Not a match type.
- // 7 is part of Attribute. Not a match type.
- // 8 is part of Attribute. Not a match type.
- 9: _SelectorRegexMatch.NotEnd,
- 10: _SelectorRegexMatch.Comma,
- 11: _SelectorRegexMatch.Contains,
- // 12 is a part of Contains.
- };
- static const _operatorMatch = 5;
- static const _unquotedValueMatch = 6;
- static const _singleQuotedValueMatch = 7;
- static const _doubleQuotedValueMatch = 8;
- Match currentMatch;
- Iterator<Match> matches;
- int lastOffset = 0;
- final int fileOffset;
- final String str;
-
- String currentMatchStr; // :contains doesn't mix with the rest
-
- _SelectorRegexMatch currentMatchType;
-
- int currentMatchIndex;
- final Source source;
- final RegExp _regExp = new RegExp(r'(\:not\()|'
- r'([-\w]+)|' // Tag
- r'(?:\.([-\w]+))|' // Class
- '(?:$_attributeRegexStr)|' // Attribute, in a non-capturing group.
- r'(\))|'
- r'(\s*,\s*)|'
- r'(^\:contains\(\/(.+)\/\)$)');
- SelectorParser(this.source, this.fileOffset, this.str);
-
- Match advance() {
- if (!matches.moveNext()) {
- currentMatch = null;
- return null;
- }
-
- currentMatch = matches.current;
- // no content should be skipped
- {
- final skipStr = str.substring(lastOffset, currentMatch.start);
- if (!isBlank(skipStr)) {
- _unexpected(skipStr, lastOffset + fileOffset);
- }
- lastOffset = currentMatch.end;
- }
-
- for (final index in matchIndexToType.keys) {
- if (currentMatch[index] != null) {
- currentMatchIndex = index;
- currentMatchType = matchIndexToType[index];
- currentMatchStr = currentMatch[index];
- return currentMatch;
- }
- }
-
- currentMatchType = null;
- currentMatchStr = null;
- return null;
- }
-
- Selector parse() {
- if (str == null) {
- return null;
- }
- matches = _regExp.allMatches(str).iterator;
- advance();
- final selector = parseNested();
- if (currentMatch != null) {
- _unexpected(
- currentMatchStr, fileOffset + (currentMatch?.start ?? lastOffset));
- }
- return selector
- ..originalString = str
- ..offset = fileOffset;
- }
-
- Selector parseNested() {
- final selectors = <Selector>[];
- while (currentMatch != null) {
- if (currentMatchType == _SelectorRegexMatch.NotEnd) {
- // don't advance, just know we're at the end of this And
- break;
- }
-
- if (currentMatchType == _SelectorRegexMatch.NotStart) {
- selectors.add(parseNotSelector());
- } else if (currentMatchType == _SelectorRegexMatch.Tag) {
- final nameOffset = fileOffset + currentMatch.start;
- final name = currentMatchStr;
- selectors.add(new ElementNameSelector(
- new SelectorName(name, nameOffset, name.length, source)));
- advance();
- } else if (currentMatchType == _SelectorRegexMatch.Class) {
- final nameOffset = fileOffset + currentMatch.start + 1;
- final name = currentMatchStr;
- selectors.add(new ClassSelector(
- new SelectorName(name, nameOffset, name.length, source)));
- advance();
- } else if (currentMatchType == _SelectorRegexMatch.Attribute) {
- final nameIndex = currentMatch.start + '['.length;
- final nameOffset = fileOffset + nameIndex;
- final operator = currentMatch[_operatorMatch];
- final value = currentMatch[_unquotedValueMatch] ??
- currentMatch[_singleQuotedValueMatch] ??
- currentMatch[_doubleQuotedValueMatch];
-
- if (operator != null && value.isEmpty) {
- _expected('a value after $operator',
- actual: ']', offset: currentMatch.end - 1);
- }
-
- var name = currentMatchStr;
- advance();
-
- if (name == '*' &&
- value != null &&
- value.startsWith('/') &&
- value.endsWith('/')) {
- if (operator != '=') {
- _unexpected(operator, nameIndex + name.length);
- }
- selectors.add(new AttributeValueRegexSelector(
- value.substring(1, value.length - 1)));
- continue;
- } else if (operator == '*=') {
- name = name.replaceAll('*', '');
- selectors.add(new AttributeContainsSelector(
- new SelectorName(name, nameOffset, name.length, source), value));
- continue;
- } else if (operator == '^=') {
- selectors.add(new AttributeStartsWithSelector(
- new SelectorName(name, nameOffset, name.length, source), value));
- continue;
- }
-
- selectors.add(new AttributeSelector(
- new SelectorName(name, nameOffset, name.length, source), value));
- } else if (currentMatchType == _SelectorRegexMatch.Comma) {
- advance();
- final rhs = parseNested();
- if (rhs is OrSelector) {
- // flatten "a, b, c, d" from (a, (b, (c, d))) into (a, b, c, d)
- return new OrSelector(
- <Selector>[_andSelectors(selectors)]..addAll(rhs.selectors));
- } else {
- return new OrSelector(<Selector>[_andSelectors(selectors), rhs]);
- }
- } else if (currentMatchType == _SelectorRegexMatch.Contains) {
- selectors
- .add(new ContainsSelector(currentMatch[currentMatchIndex + 1]));
- advance();
- } else {
- break;
- }
- }
- // final result
- return _andSelectors(selectors);
- }
-
- NotSelector parseNotSelector() {
- advance();
- final condition = parseNested();
- if (currentMatchType != _SelectorRegexMatch.NotEnd) {
- _unexpected(
- currentMatchStr, fileOffset + (currentMatch?.start ?? lastOffset));
- }
- advance();
- return new NotSelector(condition);
- }
-
- Selector _andSelectors(List<Selector> selectors) {
- if (selectors.length == 1) {
- return selectors[0];
- }
- return new AndSelector(selectors);
- }
-
- void _expected(String expected,
- {@required String actual, @required int offset}) {
- throw new SelectorParseError(
- "Expected $expected, got $actual", str, offset, actual.length);
- }
-
- void _unexpected(String eString, int eOffset) {
- throw new SelectorParseError(
- "Unexpected $eString", str, eOffset, eString.length);
- }
-}
-
-enum _SelectorRegexMatch {
- NotStart,
- NotEnd,
- Attribute,
- Tag,
- Comma,
- Class,
- Contains
-}
diff --git a/angular_analyzer_plugin/lib/src/standard_components.dart b/angular_analyzer_plugin/lib/src/standard_components.dart
deleted file mode 100644
index d0793e2..0000000
--- a/angular_analyzer_plugin/lib/src/standard_components.dart
+++ /dev/null
@@ -1,387 +0,0 @@
-import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/dart/ast/ast.dart' as ast;
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-
-typedef void CaptureAspectFn<T>(
- Map<String, T> aspectMap, PropertyAccessorElement accessor);
-
-class BuildStandardHtmlComponentsVisitor extends RecursiveAstVisitor {
- static const Map<String, String> specialElementClasses =
- const <String, String>{
- "AudioElement": 'audio',
- "OptionElement": 'option',
- "DialogElement": "dialog",
- "MediaElement": "media",
- "MenuItemElement": "menuitem",
- "ModElement": "mod",
- "PictureElement": "picture"
- };
- static const alternativeInputs = const {
- 'className': 'class',
- 'innerHTML': 'innerHtml',
- 'readOnly': 'readonly',
- 'tabIndex': 'tabindex',
- };
- static const missingOutputs = const {
- 'focusin': 'FocusEvent',
- 'focusout': 'FocusEvent',
- };
- final Map<String, Component> components;
- final Map<String, OutputElement> events;
-
- final Map<String, InputElement> attributes;
-
- // https://github.com/dart-lang/angular2/blob/8220ba3a693aff51eed33cd1ec9542bde9017423/lib/src/compiler/schema/dom_element_schema_registry.dart#L199
- final Source source;
-
- final SecuritySchema securitySchema;
-
- ClassElement classElement;
-
- BuildStandardHtmlComponentsVisitor(this.components, this.events,
- this.attributes, this.source, this.securitySchema);
-
- /// dart:html is missing an annotation to fix this casing. Compensate.
- /// TODO(mfairhurst) remove this fix once dart:html is fixed
- String fixName(String name) => name == 'innerHtml' ? 'innerHTML' : name;
-
- @override
- void visitClassDeclaration(ast.ClassDeclaration node) {
- classElement = node.declaredElement;
- super.visitClassDeclaration(node);
- if (classElement.name == 'HtmlElement') {
- final outputElements = _buildOutputs(true);
- for (final outputElement in outputElements) {
- events[outputElement.name] = outputElement;
- }
- final inputElements = _buildInputs();
- for (final inputElement in inputElements) {
- attributes[inputElement.name] = inputElement;
- final originalName = inputElement.originalName;
- if (originalName != null) {
- attributes[originalName] = inputElement;
- }
- }
- } else {
- final specialTagName = specialElementClasses[classElement.name];
- if (specialTagName != null) {
- final tag = specialTagName;
- // TODO any better offset we can do here?
- final tagOffset = classElement.nameOffset + 'HTML'.length;
- final component = _buildComponent(tag, tagOffset);
- components[tag] = component;
- }
- }
- classElement = null;
- }
-
- @override
- void visitCompilationUnit(ast.CompilationUnit unit) {
- super.visitCompilationUnit(unit);
-
- missingOutputs.forEach((name, type) {
- final namespace = unit.declaredElement.library.publicNamespace;
- final eventClass = namespace.get(type) as ClassElement;
- events[name] = new OutputElement(name, null, null,
- unit.declaredElement.source, null, null, eventClass.type);
- });
- }
-
- @override
- void visitConstructorDeclaration(ast.ConstructorDeclaration node) {
- if (node.factoryKeyword != null) {
- super.visitConstructorDeclaration(node);
- }
- }
-
- @override
- void visitMethodInvocation(ast.MethodInvocation node) {
- // ignore: omit_local_variable_types
- final ast.Expression target = node.target;
- final argumentList = node.argumentList;
- if (target is ast.SimpleIdentifier &&
- target.name == 'document' &&
- node.methodName.name == 'createElement' &&
- argumentList != null &&
- argumentList.arguments.length == 1) {
- final argument = argumentList.arguments.single;
- if (argument is ast.SimpleStringLiteral) {
- final tag = argument.value;
- final tagOffset = argument.contentsOffset;
- // don't track <template>, angular treats those specially.
- if (tag != "template") {
- final component = _buildComponent(tag, tagOffset);
- components[tag] = component;
- }
- }
- } else if (node.methodName.name == 'JS' &&
- argumentList != null &&
- argumentList.arguments.length == 4) {
- final documentArgument = argumentList.arguments[2];
- final tagArgument = argumentList.arguments[3];
- if (documentArgument is ast.SimpleIdentifier &&
- documentArgument.name == 'document' &&
- tagArgument is ast.SimpleStringLiteral) {
- final tag = tagArgument.value;
- final tagOffset = tagArgument.contentsOffset;
- // don't track <template>, angular treats those specially.
- if (tag != "template") {
- final component = _buildComponent(tag, tagOffset);
- components[tag] = component;
- }
- }
- }
- }
-
- /// Return a new [Component] for the current [classElement].
- Component _buildComponent(String tag, int tagOffset) {
- final inputElements = _buildInputs(tagname: tag);
- final outputElements = _buildOutputs(false);
- return new Component(classElement,
- inputs: inputElements,
- outputs: outputElements,
- selector: new ElementNameSelector(
- new SelectorName(tag, tagOffset, tag.length, source)),
- isHtml: true);
- }
-
- List<InputElement> _buildInputs({String tagname}) =>
- _captureAspects((inputMap, accessor) {
- final name = fixName(accessor.displayName);
- final prettyName = alternativeInputs[name];
- final originalName = prettyName == null ? null : name;
- if (!inputMap.containsKey(name)) {
- if (accessor.isSetter) {
- inputMap[name] = new InputElement(
- prettyName ?? name,
- accessor.nameOffset,
- accessor.nameLength,
- accessor.source,
- accessor,
- new SourceRange(accessor.nameOffset, accessor.nameLength),
- accessor.variable.type,
- originalName: originalName,
- securityContext: tagname == null
- ? securitySchema.lookupGlobal(name)
- : securitySchema.lookup(tagname, name));
- }
- }
- }, tagname == null); // Either grabbing HtmlElement attrs or skipping them
-
- List<OutputElement> _buildOutputs(bool globalOutputs) =>
- _captureAspects((outputMap, accessor) {
- final domName = accessor.name.toLowerCase();
- if (domName == null) {
- return;
- }
-
- // Event domnames start with on
- final name = domName.substring("on".length);
-
- if (!outputMap.containsKey(name)) {
- if (accessor.isGetter) {
- final returnType =
- accessor.type == null ? null : accessor.type.returnType;
- DartType eventType;
- if (returnType != null && returnType is InterfaceType) {
- // TODO allow subtypes of ElementStream? This is a generated file
- // so might not be necessary.
- if (returnType.element.name == 'ElementStream') {
- eventType = returnType.typeArguments[0]; // may be null
- outputMap[name] = new OutputElement(
- name,
- accessor.nameOffset,
- accessor.nameLength,
- accessor.source,
- accessor,
- null,
- eventType);
- }
- }
- }
- }
- }, globalOutputs); // Either grabbing HtmlElement events or skipping them
-
- List<T> _captureAspects<T>(CaptureAspectFn<T> addAspect, bool globalAspects) {
- final aspectMap = <String, T>{};
- final visitedTypes = new Set<InterfaceType>();
-
- void addAspects(InterfaceType type) {
- if (type != null && visitedTypes.add(type)) {
- // The events defined here are handled specially because everything
- // (even directives) can use them. Note, this leaves only a few
- // special elements with outputs such as BodyElement, everything else
- // relies on standardHtmlEvents checked after the outputs.
- if (globalAspects || type.name != 'HtmlElement') {
- type.accessors
- .where((elem) => !elem.isPrivate)
- .forEach((elem) => addAspect(aspectMap, elem));
- type.mixins.forEach(addAspects);
- addAspects(type.superclass);
- }
- }
- }
-
- addAspects(classElement.type);
- return aspectMap.values.toList();
- }
-}
-
-class SecurityContext {
- final List<DartType> safeTypes;
- final bool sanitizationAvailable;
-
- SecurityContext(this.safeTypes, {this.sanitizationAvailable = true});
-}
-
-class SecuritySchema {
- final Map<String, SecurityContext> schema = {};
-
- SecuritySchema(
- {SecurityContext htmlSecurityContext,
- SecurityContext urlSecurityContext,
- SecurityContext scriptSecurityContext,
- SecurityContext styleSecurityContext,
- SecurityContext resourceUrlSecurityContext}) {
- // This is written to be easily synced to angular's security
- _registerSecuritySchema(
- htmlSecurityContext, ['iframe|srcdoc', '*|innerHTML', '*|outerHTML']);
- _registerSecuritySchema(styleSecurityContext, ['*|style']);
- _registerSecuritySchema(urlSecurityContext, [
- '*|formAction',
- 'area|href',
- 'area|ping',
- 'audio|src',
- 'a|href',
- 'a|ping',
- 'blockquote|cite',
- 'body|background',
- 'del|cite',
- 'form|action',
- 'img|src',
- 'img|srcset',
- 'input|src',
- 'ins|cite',
- 'q|cite',
- 'source|src',
- 'source|srcset',
- 'video|poster',
- 'video|src'
- ]);
- _registerSecuritySchema(resourceUrlSecurityContext, [
- 'applet|code',
- 'applet|codebase',
- 'base|href',
- 'embed|src',
- 'frame|src',
- 'head|profile',
- 'html|manifest',
- 'iframe|src',
- 'link|href',
- 'media|src',
- 'object|codebase',
- 'object|data',
- 'script|src',
- 'track|src'
- ]);
- // TODO where's script security?
- }
-
- SecurityContext lookup(String elementName, String name) =>
- schema['$elementName|$name'];
-
- SecurityContext lookupGlobal(String name) => schema['*|$name'];
-
- void _registerSecuritySchema(SecurityContext context, List<String> specs) {
- for (final spec in specs) {
- schema[spec] = context;
- }
- }
-}
-
-class StandardAngular {
- final ClassElement templateRef;
- final ClassElement elementRef;
- final ClassElement queryList;
- final ClassElement pipeTransform;
- final ClassElement component;
- final SecuritySchema securitySchema;
-
- StandardAngular(
- {this.templateRef,
- this.elementRef,
- this.queryList,
- this.pipeTransform,
- this.component,
- this.securitySchema});
-
- factory StandardAngular.fromAnalysis(
- {ResolvedUnitResult angularResult,
- ResolvedUnitResult securityResult,
- ResolvedUnitResult protoSecurityResult}) {
- final ng = angularResult.unit.declaredElement.library.exportNamespace;
- final security =
- securityResult.unit.declaredElement.library.exportNamespace;
- final protoSecurity = protoSecurityResult == null
- ? null
- : protoSecurityResult.unit.declaredElement.library.exportNamespace;
-
- List<DartType> interfaceTypes(List<Element> elements) => elements
- .whereType<ClassElement>()
- .map((e) => e?.type)
- .where((e) => e != null)
- .toList();
-
- List<DartType> safeTypes(String id) => interfaceTypes(
- [security.get('Safe$id'), protoSecurity?.get('Safe${id}Proto')]);
-
- final securitySchema = new SecuritySchema(
- htmlSecurityContext: SecurityContext(safeTypes('Html')),
- urlSecurityContext: SecurityContext(safeTypes('Url')),
- styleSecurityContext: SecurityContext(safeTypes('Style')),
- scriptSecurityContext:
- SecurityContext(safeTypes('Script'), sanitizationAvailable: false),
- resourceUrlSecurityContext: SecurityContext(
- interfaceTypes([
- security.get('SafeResourceUrl'),
- protoSecurity?.get('TrustedResourceUrlProto')
- ]),
- sanitizationAvailable: false));
-
- return new StandardAngular(
- queryList: ng.get("QueryList") as ClassElement,
- elementRef: ng.get("ElementRef") as ClassElement,
- templateRef: ng.get("TemplateRef") as ClassElement,
- pipeTransform: ng.get("PipeTransform") as ClassElement,
- component: ng.get("Component") as ClassElement,
- securitySchema: securitySchema);
- }
-}
-
-class StandardHtml {
- final Map<String, Component> components;
- final Map<String, InputElement> attributes;
- final Map<String, OutputElement> standardEvents;
- final Map<String, OutputElement> customEvents;
-
- final ClassElement elementClass;
-
- final ClassElement htmlElementClass;
-
- /// In attributes, there can be multiple strings that point to the
- /// same [InputElement] generated from [alternativeInputs] (below).
- /// This will provide a static source of unique [InputElement]s.
- final Set<InputElement> uniqueAttributeElements;
-
- StandardHtml(this.components, this.attributes, this.standardEvents,
- this.customEvents, this.elementClass, this.htmlElementClass)
- : uniqueAttributeElements = new Set.from(attributes.values);
-
- Map<String, OutputElement> get events =>
- new Map<String, OutputElement>.from(standardEvents)..addAll(customEvents);
-}
diff --git a/angular_analyzer_plugin/lib/src/strings.dart b/angular_analyzer_plugin/lib/src/strings.dart
deleted file mode 100644
index a180e02..0000000
--- a/angular_analyzer_plugin/lib/src/strings.dart
+++ /dev/null
@@ -1,227 +0,0 @@
-import 'dart:math';
-
-/// "$"
-const CHAR_DOLLAR = 0x24;
-
-/// "."
-const CHAR_DOT = 0x2E;
-
-/// "_"
-const CHAR_UNDERSCORE = 0x5F;
-
-String capitalize(String str) {
- if (isEmpty(str)) {
- return str;
- }
- // ignore: prefer_interpolation_to_compose_strings
- return str.substring(0, 1).toUpperCase() + str.substring(1);
-}
-
-int compareStrings(String a, String b) {
- if (a == b) {
- return 0;
- }
- if (a == null) {
- return 1;
- }
- if (b == null) {
- return -1;
- }
- return a.compareTo(b);
-}
-
-/// Counts how many times [sub] appears in [str].
-int countMatches(String str, String sub) {
- if (isEmpty(str) || isEmpty(sub)) {
- return 0;
- }
- var count = 0;
- var idx = 0;
- // ignore: prefer_contains
- while ((idx = str.indexOf(sub, idx)) != -1) {
- count++;
- idx += sub.length;
- }
- return count;
-}
-
-String decapitalize(String str) {
- if (isEmpty(str)) {
- return str;
- }
- // ignore: prefer_interpolation_to_compose_strings
- return str.substring(0, 1).toLowerCase() + str.substring(1);
-}
-
-/// Returns the number of characters common to the end of [a] and the start
-/// of [b].
-int findCommonOverlap(String _a, String _b) {
- var a = _a;
- var b = _b;
- final aLength = a.length;
- final bLength = b.length;
- // all empty
- if (aLength == 0 || bLength == 0) {
- return 0;
- }
- // truncate
- if (aLength > bLength) {
- a = a.substring(aLength - bLength);
- } else if (aLength < bLength) {
- b = b.substring(0, aLength);
- }
- final textLength = min(aLength, bLength);
- // the worst case
- if (a == b) {
- return textLength;
- }
- // increase common length one by one
- var length = 0;
- while (length < textLength) {
- if (a.codeUnitAt(textLength - 1 - length) != b.codeUnitAt(length)) {
- break;
- }
- length++;
- }
- return length;
-}
-
-/// Return the number of characters common to the start of [a] and [b].
-int findCommonPrefix(String a, String b) {
- final n = min(a.length, b.length);
- for (var i = 0; i < n; i++) {
- if (a.codeUnitAt(i) != b.codeUnitAt(i)) {
- return i;
- }
- }
- return n;
-}
-
-/// Return the number of characters common to the end of [a] and [b].
-int findCommonSuffix(String a, String b) {
- final aLength = a.length;
- final bLength = b.length;
- final n = min(aLength, bLength);
- for (var i = 1; i <= n; i++) {
- if (a.codeUnitAt(aLength - i) != b.codeUnitAt(bLength - i)) {
- return i - 1;
- }
- }
- return n;
-}
-
-/// Returns a list of words for the given camel case string.
-///
-/// 'getCamelWords' => ['get', 'Camel', 'Words']
-/// 'getHTMLText' => ['get', 'HTML', 'Text']
-List<String> getCamelWords(String str) {
- if (str == null || str.isEmpty) {
- return <String>[];
- }
- final parts = <String>[];
- var wasLowerCase = false;
- var wasUpperCase = false;
- var wordStart = 0;
- for (var i = 0; i < str.length; i++) {
- final c = str.codeUnitAt(i);
- final newLowerCase = isLowerCase(c);
- final newUpperCase = isUpperCase(c);
- // myWord
- // | ^
- if (wasLowerCase && newUpperCase) {
- parts.add(str.substring(wordStart, i));
- wordStart = i;
- }
- // myHTMLText
- // | ^
- if (wasUpperCase &&
- newUpperCase &&
- i + 1 < str.length &&
- isLowerCase(str.codeUnitAt(i + 1))) {
- parts.add(str.substring(wordStart, i));
- wordStart = i;
- }
- wasLowerCase = newLowerCase;
- wasUpperCase = newUpperCase;
- }
- parts.add(str.substring(wordStart));
- return parts;
-}
-
-/// Checks if [str] is `null`, empty or is whitespace.
-bool isBlank(String str) {
- if (str == null) {
- return true;
- }
- if (str.isEmpty) {
- return true;
- }
- return str.codeUnits.every(isSpace);
-}
-
-bool isDigit(int c) => c >= 0x30 && c <= 0x39;
-
-bool isEmpty(String str) => str == null || str.isEmpty;
-
-bool isLetter(int c) => (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A);
-
-bool isLetterOrDigit(int c) => isLetter(c) || isDigit(c);
-
-bool isLowerCase(int c) => c >= 0x61 && c <= 0x7A;
-
-bool isSpace(int c) => c == 0x20 || c == 0x09;
-
-bool isUpperCase(int c) => c >= 0x41 && c <= 0x5A;
-
-bool isWhitespace(int c) => isSpace(c) || c == 0x0D || c == 0x0A;
-
-String remove(String str, String remove) {
- if (isEmpty(str) || isEmpty(remove)) {
- return str;
- }
- return str.replaceAll(remove, '');
-}
-
-String removeEnd(String str, String remove) {
- if (isEmpty(str) || isEmpty(remove)) {
- return str;
- }
- if (str.endsWith(remove)) {
- return str.substring(0, str.length - remove.length);
- }
- return str;
-}
-
-String removeStart(String str, String remove) {
- if (isEmpty(str) || isEmpty(remove)) {
- return str;
- }
- if (str.startsWith(remove)) {
- return str.substring(remove.length);
- }
- return str;
-}
-
-String repeat(String s, int n) {
- final sb = new StringBuffer();
- for (var i = 0; i < n; i++) {
- sb.write(s);
- }
- return sb.toString();
-}
-
-/// Gets the substring after the last occurrence of a separator.
-/// The separator is not returned.
-String substringAfterLast(String str, String separator) {
- if (isEmpty(str)) {
- return str;
- }
- if (isEmpty(separator)) {
- return '';
- }
- final pos = str.lastIndexOf(separator);
- if (pos == -1) {
- return str;
- }
- return str.substring(pos + separator.length);
-}
diff --git a/angular_analyzer_plugin/lib/src/summary/format.dart b/angular_analyzer_plugin/lib/src/summary/format.dart
deleted file mode 100644
index b24e370..0000000
--- a/angular_analyzer_plugin/lib/src/summary/format.dart
+++ /dev/null
@@ -1,3144 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-//
-// This file has been automatically generated. Please do not edit it manually.
-// To regenerate the file, use the script "pkg/analyzer/tool/generate_files".
-
-library analyzer.src.summary.format;
-
-import 'dart:convert' as convert;
-
-import 'package:analyzer/src/summary/api_signature.dart' as api_sig;
-import 'package:analyzer/src/summary/flat_buffers.dart' as fb;
-
-import 'idl.dart' as idl;
-
-idl.LinkedDartSummary readLinkedDartSummary(List<int> buffer) {
- fb.BufferContext rootRef = new fb.BufferContext.fromBytes(buffer);
- return const _LinkedDartSummaryReader().read(rootRef, 0);
-}
-
-idl.LinkedHtmlSummary readLinkedHtmlSummary(List<int> buffer) {
- fb.BufferContext rootRef = new fb.BufferContext.fromBytes(buffer);
- return const _LinkedHtmlSummaryReader().read(rootRef, 0);
-}
-
-idl.PackageBundle readPackageBundle(List<int> buffer) {
- fb.BufferContext rootRef = new fb.BufferContext.fromBytes(buffer);
- return const _PackageBundleReader().read(rootRef, 0);
-}
-
-idl.UnlinkedDartSummary readUnlinkedDartSummary(List<int> buffer) {
- fb.BufferContext rootRef = new fb.BufferContext.fromBytes(buffer);
- return const _UnlinkedDartSummaryReader().read(rootRef, 0);
-}
-
-idl.UnlinkedHtmlSummary readUnlinkedHtmlSummary(List<int> buffer) {
- fb.BufferContext rootRef = new fb.BufferContext.fromBytes(buffer);
- return const _UnlinkedHtmlSummaryReader().read(rootRef, 0);
-}
-
-class LinkedDartSummaryBuilder extends Object
- with _LinkedDartSummaryMixin
- implements idl.LinkedDartSummary {
- List<SummarizedAnalysisErrorBuilder> _errors;
- List<String> _referencedHtmlFiles;
- List<String> _referencedDartFiles;
- bool _hasDartTemplates;
-
- LinkedDartSummaryBuilder(
- {List<SummarizedAnalysisErrorBuilder> errors,
- List<String> referencedHtmlFiles,
- List<String> referencedDartFiles,
- bool hasDartTemplates})
- : _errors = errors,
- _referencedHtmlFiles = referencedHtmlFiles,
- _referencedDartFiles = referencedDartFiles,
- _hasDartTemplates = hasDartTemplates;
-
- @override
- List<SummarizedAnalysisErrorBuilder> get errors =>
- _errors ??= <SummarizedAnalysisErrorBuilder>[];
-
- void set errors(List<SummarizedAnalysisErrorBuilder> value) {
- this._errors = value;
- }
-
- @override
- bool get hasDartTemplates => _hasDartTemplates ??= false;
-
- void set hasDartTemplates(bool value) {
- this._hasDartTemplates = value;
- }
-
- @override
- List<String> get referencedDartFiles => _referencedDartFiles ??= <String>[];
-
- void set referencedDartFiles(List<String> value) {
- this._referencedDartFiles = value;
- }
-
- @override
- List<String> get referencedHtmlFiles => _referencedHtmlFiles ??= <String>[];
-
- void set referencedHtmlFiles(List<String> value) {
- this._referencedHtmlFiles = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- if (this._errors == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._errors.length);
- for (var x in this._errors) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._referencedHtmlFiles == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._referencedHtmlFiles.length);
- for (var x in this._referencedHtmlFiles) {
- signature.addString(x);
- }
- }
- if (this._referencedDartFiles == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._referencedDartFiles.length);
- for (var x in this._referencedDartFiles) {
- signature.addString(x);
- }
- }
- signature.addBool(this._hasDartTemplates == true);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_errors;
- fb.Offset offset_referencedHtmlFiles;
- fb.Offset offset_referencedDartFiles;
- if (!(_errors == null || _errors.isEmpty)) {
- offset_errors =
- fbBuilder.writeList(_errors.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_referencedHtmlFiles == null || _referencedHtmlFiles.isEmpty)) {
- offset_referencedHtmlFiles = fbBuilder.writeList(
- _referencedHtmlFiles.map((b) => fbBuilder.writeString(b)).toList());
- }
- if (!(_referencedDartFiles == null || _referencedDartFiles.isEmpty)) {
- offset_referencedDartFiles = fbBuilder.writeList(
- _referencedDartFiles.map((b) => fbBuilder.writeString(b)).toList());
- }
- fbBuilder.startTable();
- if (offset_errors != null) {
- fbBuilder.addOffset(0, offset_errors);
- }
- if (offset_referencedHtmlFiles != null) {
- fbBuilder.addOffset(1, offset_referencedHtmlFiles);
- }
- if (offset_referencedDartFiles != null) {
- fbBuilder.addOffset(2, offset_referencedDartFiles);
- }
- if (_hasDartTemplates == true) {
- fbBuilder.addBool(3, true);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {
- _errors?.forEach((b) => b.flushInformative());
- }
-
- List<int> toBuffer() {
- fb.Builder fbBuilder = new fb.Builder();
- return fbBuilder.finish(finish(fbBuilder), "APLD");
- }
-}
-
-class LinkedHtmlSummaryBuilder extends Object
- with _LinkedHtmlSummaryMixin
- implements idl.LinkedHtmlSummary {
- List<SummarizedAnalysisErrorBuilder> _errors;
- List<SummarizedAnalysisErrorFromPathBuilder> _errorsFromPath;
-
- LinkedHtmlSummaryBuilder(
- {List<SummarizedAnalysisErrorBuilder> errors,
- List<SummarizedAnalysisErrorFromPathBuilder> errorsFromPath})
- : _errors = errors,
- _errorsFromPath = errorsFromPath;
-
- @override
- List<SummarizedAnalysisErrorBuilder> get errors =>
- _errors ??= <SummarizedAnalysisErrorBuilder>[];
-
- void set errors(List<SummarizedAnalysisErrorBuilder> value) {
- this._errors = value;
- }
-
- @override
- List<SummarizedAnalysisErrorFromPathBuilder> get errorsFromPath =>
- _errorsFromPath ??= <SummarizedAnalysisErrorFromPathBuilder>[];
-
- void set errorsFromPath(List<SummarizedAnalysisErrorFromPathBuilder> value) {
- this._errorsFromPath = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- if (this._errors == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._errors.length);
- for (var x in this._errors) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._errorsFromPath == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._errorsFromPath.length);
- for (var x in this._errorsFromPath) {
- x?.collectApiSignature(signature);
- }
- }
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_errors;
- fb.Offset offset_errorsFromPath;
- if (!(_errors == null || _errors.isEmpty)) {
- offset_errors =
- fbBuilder.writeList(_errors.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_errorsFromPath == null || _errorsFromPath.isEmpty)) {
- offset_errorsFromPath = fbBuilder
- .writeList(_errorsFromPath.map((b) => b.finish(fbBuilder)).toList());
- }
- fbBuilder.startTable();
- if (offset_errors != null) {
- fbBuilder.addOffset(0, offset_errors);
- }
- if (offset_errorsFromPath != null) {
- fbBuilder.addOffset(1, offset_errorsFromPath);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {
- _errors?.forEach((b) => b.flushInformative());
- _errorsFromPath?.forEach((b) => b.flushInformative());
- }
-
- List<int> toBuffer() {
- fb.Builder fbBuilder = new fb.Builder();
- return fbBuilder.finish(finish(fbBuilder), "APLH");
- }
-}
-
-class PackageBundleBuilder extends Object
- with _PackageBundleMixin
- implements idl.PackageBundle {
- List<UnlinkedDartSummaryBuilder> _unlinkedDartSummary;
-
- PackageBundleBuilder({List<UnlinkedDartSummaryBuilder> unlinkedDartSummary})
- : _unlinkedDartSummary = unlinkedDartSummary;
-
- @override
- List<UnlinkedDartSummaryBuilder> get unlinkedDartSummary =>
- _unlinkedDartSummary ??= <UnlinkedDartSummaryBuilder>[];
-
- void set unlinkedDartSummary(List<UnlinkedDartSummaryBuilder> value) {
- this._unlinkedDartSummary = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- if (this._unlinkedDartSummary == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._unlinkedDartSummary.length);
- for (var x in this._unlinkedDartSummary) {
- x?.collectApiSignature(signature);
- }
- }
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_unlinkedDartSummary;
- if (!(_unlinkedDartSummary == null || _unlinkedDartSummary.isEmpty)) {
- offset_unlinkedDartSummary = fbBuilder.writeList(
- _unlinkedDartSummary.map((b) => b.finish(fbBuilder)).toList());
- }
- fbBuilder.startTable();
- if (offset_unlinkedDartSummary != null) {
- fbBuilder.addOffset(0, offset_unlinkedDartSummary);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {
- _unlinkedDartSummary?.forEach((b) => b.flushInformative());
- }
-
- List<int> toBuffer() {
- fb.Builder fbBuilder = new fb.Builder();
- return fbBuilder.finish(finish(fbBuilder), "APdl");
- }
-}
-
-class SummarizedAnalysisErrorBuilder extends Object
- with _SummarizedAnalysisErrorMixin
- implements idl.SummarizedAnalysisError {
- String _errorCode;
- String _message;
- String _correction;
- int _offset;
- int _length;
-
- SummarizedAnalysisErrorBuilder(
- {String errorCode,
- String message,
- String correction,
- int offset,
- int length})
- : _errorCode = errorCode,
- _message = message,
- _correction = correction,
- _offset = offset,
- _length = length;
-
- @override
- String get correction => _correction ??= '';
-
- void set correction(String value) {
- this._correction = value;
- }
-
- @override
- String get errorCode => _errorCode ??= '';
-
- void set errorCode(String value) {
- this._errorCode = value;
- }
-
- @override
- int get length => _length ??= 0;
-
- void set length(int value) {
- assert(value == null || value >= 0);
- this._length = value;
- }
-
- @override
- String get message => _message ??= '';
-
- void set message(String value) {
- this._message = value;
- }
-
- @override
- int get offset => _offset ??= 0;
-
- void set offset(int value) {
- assert(value == null || value >= 0);
- this._offset = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addString(this._errorCode ?? '');
- signature.addString(this._message ?? '');
- signature.addString(this._correction ?? '');
- signature.addInt(this._offset ?? 0);
- signature.addInt(this._length ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_errorCode;
- fb.Offset offset_message;
- fb.Offset offset_correction;
- if (_errorCode != null) {
- offset_errorCode = fbBuilder.writeString(_errorCode);
- }
- if (_message != null) {
- offset_message = fbBuilder.writeString(_message);
- }
- if (_correction != null) {
- offset_correction = fbBuilder.writeString(_correction);
- }
- fbBuilder.startTable();
- if (offset_errorCode != null) {
- fbBuilder.addOffset(0, offset_errorCode);
- }
- if (offset_message != null) {
- fbBuilder.addOffset(1, offset_message);
- }
- if (offset_correction != null) {
- fbBuilder.addOffset(2, offset_correction);
- }
- if (_offset != null && _offset != 0) {
- fbBuilder.addUint32(3, _offset);
- }
- if (_length != null && _length != 0) {
- fbBuilder.addUint32(4, _length);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {}
-}
-
-class SummarizedAnalysisErrorFromPathBuilder extends Object
- with _SummarizedAnalysisErrorFromPathMixin
- implements idl.SummarizedAnalysisErrorFromPath {
- String _path;
- String _classname;
- SummarizedAnalysisErrorBuilder _originalError;
-
- SummarizedAnalysisErrorFromPathBuilder(
- {String path,
- String classname,
- SummarizedAnalysisErrorBuilder originalError})
- : _path = path,
- _classname = classname,
- _originalError = originalError;
-
- @override
- String get classname => _classname ??= '';
-
- void set classname(String value) {
- this._classname = value;
- }
-
- @override
- SummarizedAnalysisErrorBuilder get originalError => _originalError;
-
- void set originalError(SummarizedAnalysisErrorBuilder value) {
- this._originalError = value;
- }
-
- @override
- String get path => _path ??= '';
-
- void set path(String value) {
- this._path = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addString(this._path ?? '');
- signature.addString(this._classname ?? '');
- signature.addBool(this._originalError != null);
- this._originalError?.collectApiSignature(signature);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_path;
- fb.Offset offset_classname;
- fb.Offset offset_originalError;
- if (_path != null) {
- offset_path = fbBuilder.writeString(_path);
- }
- if (_classname != null) {
- offset_classname = fbBuilder.writeString(_classname);
- }
- if (_originalError != null) {
- offset_originalError = _originalError.finish(fbBuilder);
- }
- fbBuilder.startTable();
- if (offset_path != null) {
- fbBuilder.addOffset(0, offset_path);
- }
- if (offset_classname != null) {
- fbBuilder.addOffset(1, offset_classname);
- }
- if (offset_originalError != null) {
- fbBuilder.addOffset(2, offset_originalError);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {
- _originalError?.flushInformative();
- }
-}
-
-class SummarizedBindableBuilder extends Object
- with _SummarizedBindableMixin
- implements idl.SummarizedBindable {
- String _name;
- int _nameOffset;
- String _propName;
- int _propNameOffset;
-
- SummarizedBindableBuilder(
- {String name, int nameOffset, String propName, int propNameOffset})
- : _name = name,
- _nameOffset = nameOffset,
- _propName = propName,
- _propNameOffset = propNameOffset;
-
- @override
- String get name => _name ??= '';
-
- void set name(String value) {
- this._name = value;
- }
-
- @override
- int get nameOffset => _nameOffset ??= 0;
-
- void set nameOffset(int value) {
- assert(value == null || value >= 0);
- this._nameOffset = value;
- }
-
- @override
- String get propName => _propName ??= '';
-
- void set propName(String value) {
- this._propName = value;
- }
-
- @override
- int get propNameOffset => _propNameOffset ??= 0;
-
- void set propNameOffset(int value) {
- assert(value == null || value >= 0);
- this._propNameOffset = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addString(this._name ?? '');
- signature.addInt(this._nameOffset ?? 0);
- signature.addString(this._propName ?? '');
- signature.addInt(this._propNameOffset ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_name;
- fb.Offset offset_propName;
- if (_name != null) {
- offset_name = fbBuilder.writeString(_name);
- }
- if (_propName != null) {
- offset_propName = fbBuilder.writeString(_propName);
- }
- fbBuilder.startTable();
- if (offset_name != null) {
- fbBuilder.addOffset(0, offset_name);
- }
- if (_nameOffset != null && _nameOffset != 0) {
- fbBuilder.addUint32(1, _nameOffset);
- }
- if (offset_propName != null) {
- fbBuilder.addOffset(2, offset_propName);
- }
- if (_propNameOffset != null && _propNameOffset != 0) {
- fbBuilder.addUint32(3, _propNameOffset);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {}
-}
-
-class SummarizedClassAnnotationsBuilder extends Object
- with _SummarizedClassAnnotationsMixin
- implements idl.SummarizedClassAnnotations {
- String _className;
- List<SummarizedBindableBuilder> _inputs;
- List<SummarizedBindableBuilder> _outputs;
- List<SummarizedContentChildFieldBuilder> _contentChildFields;
- List<SummarizedContentChildFieldBuilder> _contentChildrenFields;
-
- SummarizedClassAnnotationsBuilder(
- {String className,
- List<SummarizedBindableBuilder> inputs,
- List<SummarizedBindableBuilder> outputs,
- List<SummarizedContentChildFieldBuilder> contentChildFields,
- List<SummarizedContentChildFieldBuilder> contentChildrenFields})
- : _className = className,
- _inputs = inputs,
- _outputs = outputs,
- _contentChildFields = contentChildFields,
- _contentChildrenFields = contentChildrenFields;
-
- @override
- String get className => _className ??= '';
-
- void set className(String value) {
- this._className = value;
- }
-
- @override
- List<SummarizedContentChildFieldBuilder> get contentChildFields =>
- _contentChildFields ??= <SummarizedContentChildFieldBuilder>[];
-
- void set contentChildFields(List<SummarizedContentChildFieldBuilder> value) {
- this._contentChildFields = value;
- }
-
- @override
- List<SummarizedContentChildFieldBuilder> get contentChildrenFields =>
- _contentChildrenFields ??= <SummarizedContentChildFieldBuilder>[];
-
- void set contentChildrenFields(
- List<SummarizedContentChildFieldBuilder> value) {
- this._contentChildrenFields = value;
- }
-
- @override
- List<SummarizedBindableBuilder> get inputs =>
- _inputs ??= <SummarizedBindableBuilder>[];
-
- void set inputs(List<SummarizedBindableBuilder> value) {
- this._inputs = value;
- }
-
- @override
- List<SummarizedBindableBuilder> get outputs =>
- _outputs ??= <SummarizedBindableBuilder>[];
-
- void set outputs(List<SummarizedBindableBuilder> value) {
- this._outputs = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addString(this._className ?? '');
- if (this._inputs == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._inputs.length);
- for (var x in this._inputs) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._outputs == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._outputs.length);
- for (var x in this._outputs) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._contentChildFields == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._contentChildFields.length);
- for (var x in this._contentChildFields) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._contentChildrenFields == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._contentChildrenFields.length);
- for (var x in this._contentChildrenFields) {
- x?.collectApiSignature(signature);
- }
- }
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_className;
- fb.Offset offset_inputs;
- fb.Offset offset_outputs;
- fb.Offset offset_contentChildFields;
- fb.Offset offset_contentChildrenFields;
- if (_className != null) {
- offset_className = fbBuilder.writeString(_className);
- }
- if (!(_inputs == null || _inputs.isEmpty)) {
- offset_inputs =
- fbBuilder.writeList(_inputs.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_outputs == null || _outputs.isEmpty)) {
- offset_outputs = fbBuilder
- .writeList(_outputs.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_contentChildFields == null || _contentChildFields.isEmpty)) {
- offset_contentChildFields = fbBuilder.writeList(
- _contentChildFields.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_contentChildrenFields == null || _contentChildrenFields.isEmpty)) {
- offset_contentChildrenFields = fbBuilder.writeList(
- _contentChildrenFields.map((b) => b.finish(fbBuilder)).toList());
- }
- fbBuilder.startTable();
- if (offset_className != null) {
- fbBuilder.addOffset(0, offset_className);
- }
- if (offset_inputs != null) {
- fbBuilder.addOffset(1, offset_inputs);
- }
- if (offset_outputs != null) {
- fbBuilder.addOffset(2, offset_outputs);
- }
- if (offset_contentChildFields != null) {
- fbBuilder.addOffset(3, offset_contentChildFields);
- }
- if (offset_contentChildrenFields != null) {
- fbBuilder.addOffset(4, offset_contentChildrenFields);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {
- _inputs?.forEach((b) => b.flushInformative());
- _outputs?.forEach((b) => b.flushInformative());
- _contentChildFields?.forEach((b) => b.flushInformative());
- _contentChildrenFields?.forEach((b) => b.flushInformative());
- }
-}
-
-class SummarizedContentChildFieldBuilder extends Object
- with _SummarizedContentChildFieldMixin
- implements idl.SummarizedContentChildField {
- String _fieldName;
- int _nameOffset;
- int _nameLength;
- int _typeOffset;
- int _typeLength;
-
- SummarizedContentChildFieldBuilder(
- {String fieldName,
- int nameOffset,
- int nameLength,
- int typeOffset,
- int typeLength})
- : _fieldName = fieldName,
- _nameOffset = nameOffset,
- _nameLength = nameLength,
- _typeOffset = typeOffset,
- _typeLength = typeLength;
-
- @override
- String get fieldName => _fieldName ??= '';
-
- void set fieldName(String value) {
- this._fieldName = value;
- }
-
- @override
- int get nameLength => _nameLength ??= 0;
-
- void set nameLength(int value) {
- assert(value == null || value >= 0);
- this._nameLength = value;
- }
-
- @override
- int get nameOffset => _nameOffset ??= 0;
-
- void set nameOffset(int value) {
- assert(value == null || value >= 0);
- this._nameOffset = value;
- }
-
- @override
- int get typeLength => _typeLength ??= 0;
-
- void set typeLength(int value) {
- assert(value == null || value >= 0);
- this._typeLength = value;
- }
-
- @override
- int get typeOffset => _typeOffset ??= 0;
-
- void set typeOffset(int value) {
- assert(value == null || value >= 0);
- this._typeOffset = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addString(this._fieldName ?? '');
- signature.addInt(this._nameOffset ?? 0);
- signature.addInt(this._nameLength ?? 0);
- signature.addInt(this._typeOffset ?? 0);
- signature.addInt(this._typeLength ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_fieldName;
- if (_fieldName != null) {
- offset_fieldName = fbBuilder.writeString(_fieldName);
- }
- fbBuilder.startTable();
- if (offset_fieldName != null) {
- fbBuilder.addOffset(0, offset_fieldName);
- }
- if (_nameOffset != null && _nameOffset != 0) {
- fbBuilder.addUint32(1, _nameOffset);
- }
- if (_nameLength != null && _nameLength != 0) {
- fbBuilder.addUint32(2, _nameLength);
- }
- if (_typeOffset != null && _typeOffset != 0) {
- fbBuilder.addUint32(3, _typeOffset);
- }
- if (_typeLength != null && _typeLength != 0) {
- fbBuilder.addUint32(4, _typeLength);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {}
-}
-
-class SummarizedDirectiveBuilder extends Object
- with _SummarizedDirectiveMixin
- implements idl.SummarizedDirective {
- SummarizedClassAnnotationsBuilder _classAnnotations;
- String _functionName;
- bool _isComponent;
- String _selectorStr;
- int _selectorOffset;
- String _exportAs;
- int _exportAsOffset;
- String _templateUrl;
- int _templateUrlOffset;
- int _templateUrlLength;
- String _templateText;
- int _templateOffset;
- List<SummarizedNgContentBuilder> _ngContents;
- bool _usesArrayOfDirectiveReferencesStrategy;
- List<SummarizedDirectiveUseBuilder> _subdirectives;
- List<SummarizedExportedIdentifierBuilder> _exports;
- List<SummarizedPipesUseBuilder> _pipesUse;
- int _constDirectiveStrategyOffset;
- int _constDirectiveStrategyLength;
-
- SummarizedDirectiveBuilder(
- {SummarizedClassAnnotationsBuilder classAnnotations,
- String functionName,
- bool isComponent,
- String selectorStr,
- int selectorOffset,
- String exportAs,
- int exportAsOffset,
- String templateUrl,
- int templateUrlOffset,
- int templateUrlLength,
- String templateText,
- int templateOffset,
- List<SummarizedNgContentBuilder> ngContents,
- bool usesArrayOfDirectiveReferencesStrategy,
- List<SummarizedDirectiveUseBuilder> subdirectives,
- List<SummarizedExportedIdentifierBuilder> exports,
- List<SummarizedPipesUseBuilder> pipesUse,
- int constDirectiveStrategyOffset,
- int constDirectiveStrategyLength})
- : _classAnnotations = classAnnotations,
- _functionName = functionName,
- _isComponent = isComponent,
- _selectorStr = selectorStr,
- _selectorOffset = selectorOffset,
- _exportAs = exportAs,
- _exportAsOffset = exportAsOffset,
- _templateUrl = templateUrl,
- _templateUrlOffset = templateUrlOffset,
- _templateUrlLength = templateUrlLength,
- _templateText = templateText,
- _templateOffset = templateOffset,
- _ngContents = ngContents,
- _usesArrayOfDirectiveReferencesStrategy =
- usesArrayOfDirectiveReferencesStrategy,
- _subdirectives = subdirectives,
- _exports = exports,
- _pipesUse = pipesUse,
- _constDirectiveStrategyOffset = constDirectiveStrategyOffset,
- _constDirectiveStrategyLength = constDirectiveStrategyLength;
-
- @override
- SummarizedClassAnnotationsBuilder get classAnnotations => _classAnnotations;
-
- void set classAnnotations(SummarizedClassAnnotationsBuilder value) {
- this._classAnnotations = value;
- }
-
- @override
- int get constDirectiveStrategyLength => _constDirectiveStrategyLength ??= 0;
-
- void set constDirectiveStrategyLength(int value) {
- assert(value == null || value >= 0);
- this._constDirectiveStrategyLength = value;
- }
-
- @override
- int get constDirectiveStrategyOffset => _constDirectiveStrategyOffset ??= 0;
-
- void set constDirectiveStrategyOffset(int value) {
- assert(value == null || value >= 0);
- this._constDirectiveStrategyOffset = value;
- }
-
- @override
- String get exportAs => _exportAs ??= '';
-
- void set exportAs(String value) {
- this._exportAs = value;
- }
-
- @override
- int get exportAsOffset => _exportAsOffset ??= 0;
-
- void set exportAsOffset(int value) {
- assert(value == null || value >= 0);
- this._exportAsOffset = value;
- }
-
- @override
- List<SummarizedExportedIdentifierBuilder> get exports =>
- _exports ??= <SummarizedExportedIdentifierBuilder>[];
-
- void set exports(List<SummarizedExportedIdentifierBuilder> value) {
- this._exports = value;
- }
-
- @override
- String get functionName => _functionName ??= '';
-
- void set functionName(String value) {
- this._functionName = value;
- }
-
- @override
- bool get isComponent => _isComponent ??= false;
-
- void set isComponent(bool value) {
- this._isComponent = value;
- }
-
- @override
- List<SummarizedNgContentBuilder> get ngContents =>
- _ngContents ??= <SummarizedNgContentBuilder>[];
-
- void set ngContents(List<SummarizedNgContentBuilder> value) {
- this._ngContents = value;
- }
-
- @override
- List<SummarizedPipesUseBuilder> get pipesUse =>
- _pipesUse ??= <SummarizedPipesUseBuilder>[];
-
- void set pipesUse(List<SummarizedPipesUseBuilder> value) {
- this._pipesUse = value;
- }
-
- @override
- int get selectorOffset => _selectorOffset ??= 0;
-
- void set selectorOffset(int value) {
- assert(value == null || value >= 0);
- this._selectorOffset = value;
- }
-
- @override
- String get selectorStr => _selectorStr ??= '';
-
- void set selectorStr(String value) {
- this._selectorStr = value;
- }
-
- @override
- List<SummarizedDirectiveUseBuilder> get subdirectives =>
- _subdirectives ??= <SummarizedDirectiveUseBuilder>[];
-
- void set subdirectives(List<SummarizedDirectiveUseBuilder> value) {
- this._subdirectives = value;
- }
-
- @override
- int get templateOffset => _templateOffset ??= 0;
-
- void set templateOffset(int value) {
- assert(value == null || value >= 0);
- this._templateOffset = value;
- }
-
- @override
- String get templateText => _templateText ??= '';
-
- void set templateText(String value) {
- this._templateText = value;
- }
-
- @override
- String get templateUrl => _templateUrl ??= '';
-
- void set templateUrl(String value) {
- this._templateUrl = value;
- }
-
- @override
- int get templateUrlLength => _templateUrlLength ??= 0;
-
- void set templateUrlLength(int value) {
- assert(value == null || value >= 0);
- this._templateUrlLength = value;
- }
-
- @override
- int get templateUrlOffset => _templateUrlOffset ??= 0;
-
- void set templateUrlOffset(int value) {
- assert(value == null || value >= 0);
- this._templateUrlOffset = value;
- }
-
- @override
- bool get usesArrayOfDirectiveReferencesStrategy =>
- _usesArrayOfDirectiveReferencesStrategy ??= false;
-
- void set usesArrayOfDirectiveReferencesStrategy(bool value) {
- this._usesArrayOfDirectiveReferencesStrategy = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addBool(this._classAnnotations != null);
- this._classAnnotations?.collectApiSignature(signature);
- signature.addString(this._functionName ?? '');
- signature.addBool(this._isComponent == true);
- signature.addString(this._selectorStr ?? '');
- signature.addInt(this._selectorOffset ?? 0);
- signature.addString(this._exportAs ?? '');
- signature.addInt(this._exportAsOffset ?? 0);
- signature.addString(this._templateUrl ?? '');
- signature.addInt(this._templateUrlOffset ?? 0);
- signature.addInt(this._templateUrlLength ?? 0);
- signature.addString(this._templateText ?? '');
- signature.addInt(this._templateOffset ?? 0);
- if (this._ngContents == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._ngContents.length);
- for (var x in this._ngContents) {
- x?.collectApiSignature(signature);
- }
- }
- signature.addBool(this._usesArrayOfDirectiveReferencesStrategy == true);
- if (this._subdirectives == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._subdirectives.length);
- for (var x in this._subdirectives) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._exports == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._exports.length);
- for (var x in this._exports) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._pipesUse == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._pipesUse.length);
- for (var x in this._pipesUse) {
- x?.collectApiSignature(signature);
- }
- }
- signature.addInt(this._constDirectiveStrategyOffset ?? 0);
- signature.addInt(this._constDirectiveStrategyLength ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_classAnnotations;
- fb.Offset offset_functionName;
- fb.Offset offset_selectorStr;
- fb.Offset offset_exportAs;
- fb.Offset offset_templateUrl;
- fb.Offset offset_templateText;
- fb.Offset offset_ngContents;
- fb.Offset offset_subdirectives;
- fb.Offset offset_exports;
- fb.Offset offset_pipesUse;
- if (_classAnnotations != null) {
- offset_classAnnotations = _classAnnotations.finish(fbBuilder);
- }
- if (_functionName != null) {
- offset_functionName = fbBuilder.writeString(_functionName);
- }
- if (_selectorStr != null) {
- offset_selectorStr = fbBuilder.writeString(_selectorStr);
- }
- if (_exportAs != null) {
- offset_exportAs = fbBuilder.writeString(_exportAs);
- }
- if (_templateUrl != null) {
- offset_templateUrl = fbBuilder.writeString(_templateUrl);
- }
- if (_templateText != null) {
- offset_templateText = fbBuilder.writeString(_templateText);
- }
- if (!(_ngContents == null || _ngContents.isEmpty)) {
- offset_ngContents = fbBuilder
- .writeList(_ngContents.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_subdirectives == null || _subdirectives.isEmpty)) {
- offset_subdirectives = fbBuilder
- .writeList(_subdirectives.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_exports == null || _exports.isEmpty)) {
- offset_exports = fbBuilder
- .writeList(_exports.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_pipesUse == null || _pipesUse.isEmpty)) {
- offset_pipesUse = fbBuilder
- .writeList(_pipesUse.map((b) => b.finish(fbBuilder)).toList());
- }
- fbBuilder.startTable();
- if (offset_classAnnotations != null) {
- fbBuilder.addOffset(0, offset_classAnnotations);
- }
- if (offset_functionName != null) {
- fbBuilder.addOffset(1, offset_functionName);
- }
- if (_isComponent == true) {
- fbBuilder.addBool(2, true);
- }
- if (offset_selectorStr != null) {
- fbBuilder.addOffset(3, offset_selectorStr);
- }
- if (_selectorOffset != null && _selectorOffset != 0) {
- fbBuilder.addUint32(4, _selectorOffset);
- }
- if (offset_exportAs != null) {
- fbBuilder.addOffset(5, offset_exportAs);
- }
- if (_exportAsOffset != null && _exportAsOffset != 0) {
- fbBuilder.addUint32(6, _exportAsOffset);
- }
- if (offset_templateUrl != null) {
- fbBuilder.addOffset(7, offset_templateUrl);
- }
- if (_templateUrlOffset != null && _templateUrlOffset != 0) {
- fbBuilder.addUint32(8, _templateUrlOffset);
- }
- if (_templateUrlLength != null && _templateUrlLength != 0) {
- fbBuilder.addUint32(9, _templateUrlLength);
- }
- if (offset_templateText != null) {
- fbBuilder.addOffset(10, offset_templateText);
- }
- if (_templateOffset != null && _templateOffset != 0) {
- fbBuilder.addUint32(11, _templateOffset);
- }
- if (offset_ngContents != null) {
- fbBuilder.addOffset(12, offset_ngContents);
- }
- if (_usesArrayOfDirectiveReferencesStrategy == true) {
- fbBuilder.addBool(13, true);
- }
- if (offset_subdirectives != null) {
- fbBuilder.addOffset(14, offset_subdirectives);
- }
- if (offset_exports != null) {
- fbBuilder.addOffset(15, offset_exports);
- }
- if (offset_pipesUse != null) {
- fbBuilder.addOffset(16, offset_pipesUse);
- }
- if (_constDirectiveStrategyOffset != null &&
- _constDirectiveStrategyOffset != 0) {
- fbBuilder.addUint32(17, _constDirectiveStrategyOffset);
- }
- if (_constDirectiveStrategyLength != null &&
- _constDirectiveStrategyLength != 0) {
- fbBuilder.addUint32(18, _constDirectiveStrategyLength);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {
- _classAnnotations?.flushInformative();
- _ngContents?.forEach((b) => b.flushInformative());
- _subdirectives?.forEach((b) => b.flushInformative());
- _exports?.forEach((b) => b.flushInformative());
- _pipesUse?.forEach((b) => b.flushInformative());
- }
-}
-
-class SummarizedDirectiveUseBuilder extends Object
- with _SummarizedDirectiveUseMixin
- implements idl.SummarizedDirectiveUse {
- String _name;
- String _prefix;
- int _offset;
- int _length;
-
- SummarizedDirectiveUseBuilder(
- {String name, String prefix, int offset, int length})
- : _name = name,
- _prefix = prefix,
- _offset = offset,
- _length = length;
-
- @override
- int get length => _length ??= 0;
-
- void set length(int value) {
- assert(value == null || value >= 0);
- this._length = value;
- }
-
- @override
- String get name => _name ??= '';
-
- void set name(String value) {
- this._name = value;
- }
-
- @override
- int get offset => _offset ??= 0;
-
- void set offset(int value) {
- assert(value == null || value >= 0);
- this._offset = value;
- }
-
- @override
- String get prefix => _prefix ??= '';
-
- void set prefix(String value) {
- this._prefix = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addString(this._name ?? '');
- signature.addString(this._prefix ?? '');
- signature.addInt(this._offset ?? 0);
- signature.addInt(this._length ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_name;
- fb.Offset offset_prefix;
- if (_name != null) {
- offset_name = fbBuilder.writeString(_name);
- }
- if (_prefix != null) {
- offset_prefix = fbBuilder.writeString(_prefix);
- }
- fbBuilder.startTable();
- if (offset_name != null) {
- fbBuilder.addOffset(0, offset_name);
- }
- if (offset_prefix != null) {
- fbBuilder.addOffset(1, offset_prefix);
- }
- if (_offset != null && _offset != 0) {
- fbBuilder.addUint32(2, _offset);
- }
- if (_length != null && _length != 0) {
- fbBuilder.addUint32(3, _length);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {}
-}
-
-class SummarizedExportedIdentifierBuilder extends Object
- with _SummarizedExportedIdentifierMixin
- implements idl.SummarizedExportedIdentifier {
- String _name;
- String _prefix;
- int _offset;
- int _length;
-
- SummarizedExportedIdentifierBuilder(
- {String name, String prefix, int offset, int length})
- : _name = name,
- _prefix = prefix,
- _offset = offset,
- _length = length;
-
- @override
- int get length => _length ??= 0;
-
- void set length(int value) {
- assert(value == null || value >= 0);
- this._length = value;
- }
-
- @override
- String get name => _name ??= '';
-
- void set name(String value) {
- this._name = value;
- }
-
- @override
- int get offset => _offset ??= 0;
-
- void set offset(int value) {
- assert(value == null || value >= 0);
- this._offset = value;
- }
-
- @override
- String get prefix => _prefix ??= '';
-
- void set prefix(String value) {
- this._prefix = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addString(this._name ?? '');
- signature.addString(this._prefix ?? '');
- signature.addInt(this._offset ?? 0);
- signature.addInt(this._length ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_name;
- fb.Offset offset_prefix;
- if (_name != null) {
- offset_name = fbBuilder.writeString(_name);
- }
- if (_prefix != null) {
- offset_prefix = fbBuilder.writeString(_prefix);
- }
- fbBuilder.startTable();
- if (offset_name != null) {
- fbBuilder.addOffset(0, offset_name);
- }
- if (offset_prefix != null) {
- fbBuilder.addOffset(1, offset_prefix);
- }
- if (_offset != null && _offset != 0) {
- fbBuilder.addUint32(2, _offset);
- }
- if (_length != null && _length != 0) {
- fbBuilder.addUint32(3, _length);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {}
-}
-
-class SummarizedNgContentBuilder extends Object
- with _SummarizedNgContentMixin
- implements idl.SummarizedNgContent {
- int _offset;
- int _length;
- String _selectorStr;
- int _selectorOffset;
-
- SummarizedNgContentBuilder(
- {int offset, int length, String selectorStr, int selectorOffset})
- : _offset = offset,
- _length = length,
- _selectorStr = selectorStr,
- _selectorOffset = selectorOffset;
-
- @override
- int get length => _length ??= 0;
-
- void set length(int value) {
- assert(value == null || value >= 0);
- this._length = value;
- }
-
- @override
- int get offset => _offset ??= 0;
-
- void set offset(int value) {
- assert(value == null || value >= 0);
- this._offset = value;
- }
-
- @override
- int get selectorOffset => _selectorOffset ??= 0;
-
- void set selectorOffset(int value) {
- assert(value == null || value >= 0);
- this._selectorOffset = value;
- }
-
- @override
- String get selectorStr => _selectorStr ??= '';
-
- void set selectorStr(String value) {
- this._selectorStr = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addInt(this._offset ?? 0);
- signature.addInt(this._length ?? 0);
- signature.addString(this._selectorStr ?? '');
- signature.addInt(this._selectorOffset ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_selectorStr;
- if (_selectorStr != null) {
- offset_selectorStr = fbBuilder.writeString(_selectorStr);
- }
- fbBuilder.startTable();
- if (_offset != null && _offset != 0) {
- fbBuilder.addUint32(0, _offset);
- }
- if (_length != null && _length != 0) {
- fbBuilder.addUint32(1, _length);
- }
- if (offset_selectorStr != null) {
- fbBuilder.addOffset(2, offset_selectorStr);
- }
- if (_selectorOffset != null && _selectorOffset != 0) {
- fbBuilder.addUint32(3, _selectorOffset);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {}
-}
-
-class SummarizedPipeBuilder extends Object
- with _SummarizedPipeMixin
- implements idl.SummarizedPipe {
- String _pipeName;
- int _pipeNameOffset;
- bool _isPure;
- String _decoratedClassName;
-
- SummarizedPipeBuilder(
- {String pipeName,
- int pipeNameOffset,
- bool isPure,
- String decoratedClassName})
- : _pipeName = pipeName,
- _pipeNameOffset = pipeNameOffset,
- _isPure = isPure,
- _decoratedClassName = decoratedClassName;
-
- @override
- String get decoratedClassName => _decoratedClassName ??= '';
-
- void set decoratedClassName(String value) {
- this._decoratedClassName = value;
- }
-
- @override
- bool get isPure => _isPure ??= false;
-
- void set isPure(bool value) {
- this._isPure = value;
- }
-
- @override
- String get pipeName => _pipeName ??= '';
-
- void set pipeName(String value) {
- this._pipeName = value;
- }
-
- @override
- int get pipeNameOffset => _pipeNameOffset ??= 0;
-
- void set pipeNameOffset(int value) {
- assert(value == null || value >= 0);
- this._pipeNameOffset = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addString(this._pipeName ?? '');
- signature.addInt(this._pipeNameOffset ?? 0);
- signature.addBool(this._isPure == true);
- signature.addString(this._decoratedClassName ?? '');
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_pipeName;
- fb.Offset offset_decoratedClassName;
- if (_pipeName != null) {
- offset_pipeName = fbBuilder.writeString(_pipeName);
- }
- if (_decoratedClassName != null) {
- offset_decoratedClassName = fbBuilder.writeString(_decoratedClassName);
- }
- fbBuilder.startTable();
- if (offset_pipeName != null) {
- fbBuilder.addOffset(0, offset_pipeName);
- }
- if (_pipeNameOffset != null && _pipeNameOffset != 0) {
- fbBuilder.addUint32(1, _pipeNameOffset);
- }
- if (_isPure == true) {
- fbBuilder.addBool(2, true);
- }
- if (offset_decoratedClassName != null) {
- fbBuilder.addOffset(3, offset_decoratedClassName);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {}
-}
-
-class SummarizedPipesUseBuilder extends Object
- with _SummarizedPipesUseMixin
- implements idl.SummarizedPipesUse {
- String _name;
- String _prefix;
- int _offset;
- int _length;
-
- SummarizedPipesUseBuilder(
- {String name, String prefix, int offset, int length})
- : _name = name,
- _prefix = prefix,
- _offset = offset,
- _length = length;
-
- @override
- int get length => _length ??= 0;
-
- void set length(int value) {
- assert(value == null || value >= 0);
- this._length = value;
- }
-
- @override
- String get name => _name ??= '';
-
- void set name(String value) {
- this._name = value;
- }
-
- @override
- int get offset => _offset ??= 0;
-
- void set offset(int value) {
- assert(value == null || value >= 0);
- this._offset = value;
- }
-
- @override
- String get prefix => _prefix ??= '';
-
- void set prefix(String value) {
- this._prefix = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addString(this._name ?? '');
- signature.addString(this._prefix ?? '');
- signature.addInt(this._offset ?? 0);
- signature.addInt(this._length ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_name;
- fb.Offset offset_prefix;
- if (_name != null) {
- offset_name = fbBuilder.writeString(_name);
- }
- if (_prefix != null) {
- offset_prefix = fbBuilder.writeString(_prefix);
- }
- fbBuilder.startTable();
- if (offset_name != null) {
- fbBuilder.addOffset(0, offset_name);
- }
- if (offset_prefix != null) {
- fbBuilder.addOffset(1, offset_prefix);
- }
- if (_offset != null && _offset != 0) {
- fbBuilder.addUint32(2, _offset);
- }
- if (_length != null && _length != 0) {
- fbBuilder.addUint32(3, _length);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {}
-}
-
-class UnlinkedDartSummaryBuilder extends Object
- with _UnlinkedDartSummaryMixin
- implements idl.UnlinkedDartSummary {
- List<SummarizedDirectiveBuilder> _directiveSummaries;
- List<SummarizedClassAnnotationsBuilder> _annotatedClasses;
- List<SummarizedAnalysisErrorBuilder> _errors;
- List<SummarizedPipeBuilder> _pipeSummaries;
-
- UnlinkedDartSummaryBuilder(
- {List<SummarizedDirectiveBuilder> directiveSummaries,
- List<SummarizedClassAnnotationsBuilder> annotatedClasses,
- List<SummarizedAnalysisErrorBuilder> errors,
- List<SummarizedPipeBuilder> pipeSummaries})
- : _directiveSummaries = directiveSummaries,
- _annotatedClasses = annotatedClasses,
- _errors = errors,
- _pipeSummaries = pipeSummaries;
-
- @override
- List<SummarizedClassAnnotationsBuilder> get annotatedClasses =>
- _annotatedClasses ??= <SummarizedClassAnnotationsBuilder>[];
-
- void set annotatedClasses(List<SummarizedClassAnnotationsBuilder> value) {
- this._annotatedClasses = value;
- }
-
- @override
- List<SummarizedDirectiveBuilder> get directiveSummaries =>
- _directiveSummaries ??= <SummarizedDirectiveBuilder>[];
-
- void set directiveSummaries(List<SummarizedDirectiveBuilder> value) {
- this._directiveSummaries = value;
- }
-
- @override
- List<SummarizedAnalysisErrorBuilder> get errors =>
- _errors ??= <SummarizedAnalysisErrorBuilder>[];
-
- void set errors(List<SummarizedAnalysisErrorBuilder> value) {
- this._errors = value;
- }
-
- @override
- List<SummarizedPipeBuilder> get pipeSummaries =>
- _pipeSummaries ??= <SummarizedPipeBuilder>[];
-
- void set pipeSummaries(List<SummarizedPipeBuilder> value) {
- this._pipeSummaries = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- if (this._directiveSummaries == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._directiveSummaries.length);
- for (var x in this._directiveSummaries) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._annotatedClasses == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._annotatedClasses.length);
- for (var x in this._annotatedClasses) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._errors == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._errors.length);
- for (var x in this._errors) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._pipeSummaries == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._pipeSummaries.length);
- for (var x in this._pipeSummaries) {
- x?.collectApiSignature(signature);
- }
- }
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_directiveSummaries;
- fb.Offset offset_annotatedClasses;
- fb.Offset offset_errors;
- fb.Offset offset_pipeSummaries;
- if (!(_directiveSummaries == null || _directiveSummaries.isEmpty)) {
- offset_directiveSummaries = fbBuilder.writeList(
- _directiveSummaries.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_annotatedClasses == null || _annotatedClasses.isEmpty)) {
- offset_annotatedClasses = fbBuilder.writeList(
- _annotatedClasses.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_errors == null || _errors.isEmpty)) {
- offset_errors =
- fbBuilder.writeList(_errors.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_pipeSummaries == null || _pipeSummaries.isEmpty)) {
- offset_pipeSummaries = fbBuilder
- .writeList(_pipeSummaries.map((b) => b.finish(fbBuilder)).toList());
- }
- fbBuilder.startTable();
- if (offset_directiveSummaries != null) {
- fbBuilder.addOffset(0, offset_directiveSummaries);
- }
- if (offset_annotatedClasses != null) {
- fbBuilder.addOffset(1, offset_annotatedClasses);
- }
- if (offset_errors != null) {
- fbBuilder.addOffset(2, offset_errors);
- }
- if (offset_pipeSummaries != null) {
- fbBuilder.addOffset(3, offset_pipeSummaries);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {
- _directiveSummaries?.forEach((b) => b.flushInformative());
- _annotatedClasses?.forEach((b) => b.flushInformative());
- _errors?.forEach((b) => b.flushInformative());
- _pipeSummaries?.forEach((b) => b.flushInformative());
- }
-
- List<int> toBuffer() {
- fb.Builder fbBuilder = new fb.Builder();
- return fbBuilder.finish(finish(fbBuilder), "APUD");
- }
-}
-
-class UnlinkedHtmlSummaryBuilder extends Object
- with _UnlinkedHtmlSummaryMixin
- implements idl.UnlinkedHtmlSummary {
- List<SummarizedNgContentBuilder> _ngContents;
-
- UnlinkedHtmlSummaryBuilder({List<SummarizedNgContentBuilder> ngContents})
- : _ngContents = ngContents;
-
- @override
- List<SummarizedNgContentBuilder> get ngContents =>
- _ngContents ??= <SummarizedNgContentBuilder>[];
-
- void set ngContents(List<SummarizedNgContentBuilder> value) {
- this._ngContents = value;
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- if (this._ngContents == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._ngContents.length);
- for (var x in this._ngContents) {
- x?.collectApiSignature(signature);
- }
- }
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_ngContents;
- if (!(_ngContents == null || _ngContents.isEmpty)) {
- offset_ngContents = fbBuilder
- .writeList(_ngContents.map((b) => b.finish(fbBuilder)).toList());
- }
- fbBuilder.startTable();
- if (offset_ngContents != null) {
- fbBuilder.addOffset(0, offset_ngContents);
- }
- return fbBuilder.endTable();
- }
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {
- _ngContents?.forEach((b) => b.flushInformative());
- }
-
- List<int> toBuffer() {
- fb.Builder fbBuilder = new fb.Builder();
- return fbBuilder.finish(finish(fbBuilder), "APUH");
- }
-}
-
-class _LinkedDartSummaryImpl extends Object
- with _LinkedDartSummaryMixin
- implements idl.LinkedDartSummary {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- List<idl.SummarizedAnalysisError> _errors;
-
- List<String> _referencedHtmlFiles;
- List<String> _referencedDartFiles;
- bool _hasDartTemplates;
- _LinkedDartSummaryImpl(this._bc, this._bcOffset);
-
- @override
- List<idl.SummarizedAnalysisError> get errors {
- _errors ??= const fb.ListReader<idl.SummarizedAnalysisError>(
- const _SummarizedAnalysisErrorReader())
- .vTableGet(_bc, _bcOffset, 0, const <idl.SummarizedAnalysisError>[]);
- return _errors;
- }
-
- @override
- bool get hasDartTemplates {
- _hasDartTemplates ??=
- const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
- return _hasDartTemplates;
- }
-
- @override
- List<String> get referencedDartFiles {
- _referencedDartFiles ??=
- const fb.ListReader<String>(const fb.StringReader())
- .vTableGet(_bc, _bcOffset, 2, const <String>[]);
- return _referencedDartFiles;
- }
-
- @override
- List<String> get referencedHtmlFiles {
- _referencedHtmlFiles ??=
- const fb.ListReader<String>(const fb.StringReader())
- .vTableGet(_bc, _bcOffset, 1, const <String>[]);
- return _referencedHtmlFiles;
- }
-}
-
-abstract class _LinkedDartSummaryMixin implements idl.LinkedDartSummary {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (errors.isNotEmpty)
- _result["errors"] = errors.map((_value) => _value.toJson()).toList();
- if (referencedHtmlFiles.isNotEmpty)
- _result["referencedHtmlFiles"] = referencedHtmlFiles;
- if (referencedDartFiles.isNotEmpty)
- _result["referencedDartFiles"] = referencedDartFiles;
- if (hasDartTemplates != false)
- _result["hasDartTemplates"] = hasDartTemplates;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "errors": errors,
- "referencedHtmlFiles": referencedHtmlFiles,
- "referencedDartFiles": referencedDartFiles,
- "hasDartTemplates": hasDartTemplates,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _LinkedDartSummaryReader extends fb.TableReader<_LinkedDartSummaryImpl> {
- const _LinkedDartSummaryReader();
-
- @override
- _LinkedDartSummaryImpl createObject(fb.BufferContext bc, int offset) =>
- new _LinkedDartSummaryImpl(bc, offset);
-}
-
-class _LinkedHtmlSummaryImpl extends Object
- with _LinkedHtmlSummaryMixin
- implements idl.LinkedHtmlSummary {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- List<idl.SummarizedAnalysisError> _errors;
-
- List<idl.SummarizedAnalysisErrorFromPath> _errorsFromPath;
- _LinkedHtmlSummaryImpl(this._bc, this._bcOffset);
-
- @override
- List<idl.SummarizedAnalysisError> get errors {
- _errors ??= const fb.ListReader<idl.SummarizedAnalysisError>(
- const _SummarizedAnalysisErrorReader())
- .vTableGet(_bc, _bcOffset, 0, const <idl.SummarizedAnalysisError>[]);
- return _errors;
- }
-
- @override
- List<idl.SummarizedAnalysisErrorFromPath> get errorsFromPath {
- _errorsFromPath ??=
- const fb.ListReader<idl.SummarizedAnalysisErrorFromPath>(
- const _SummarizedAnalysisErrorFromPathReader())
- .vTableGet(_bc, _bcOffset, 1,
- const <idl.SummarizedAnalysisErrorFromPath>[]);
- return _errorsFromPath;
- }
-}
-
-abstract class _LinkedHtmlSummaryMixin implements idl.LinkedHtmlSummary {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (errors.isNotEmpty)
- _result["errors"] = errors.map((_value) => _value.toJson()).toList();
- if (errorsFromPath.isNotEmpty)
- _result["errorsFromPath"] =
- errorsFromPath.map((_value) => _value.toJson()).toList();
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "errors": errors,
- "errorsFromPath": errorsFromPath,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _LinkedHtmlSummaryReader extends fb.TableReader<_LinkedHtmlSummaryImpl> {
- const _LinkedHtmlSummaryReader();
-
- @override
- _LinkedHtmlSummaryImpl createObject(fb.BufferContext bc, int offset) =>
- new _LinkedHtmlSummaryImpl(bc, offset);
-}
-
-class _PackageBundleImpl extends Object
- with _PackageBundleMixin
- implements idl.PackageBundle {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- List<idl.UnlinkedDartSummary> _unlinkedDartSummary;
-
- _PackageBundleImpl(this._bc, this._bcOffset);
-
- @override
- List<idl.UnlinkedDartSummary> get unlinkedDartSummary {
- _unlinkedDartSummary ??= const fb.ListReader<idl.UnlinkedDartSummary>(
- const _UnlinkedDartSummaryReader())
- .vTableGet(_bc, _bcOffset, 0, const <idl.UnlinkedDartSummary>[]);
- return _unlinkedDartSummary;
- }
-}
-
-abstract class _PackageBundleMixin implements idl.PackageBundle {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (unlinkedDartSummary.isNotEmpty)
- _result["unlinkedDartSummary"] =
- unlinkedDartSummary.map((_value) => _value.toJson()).toList();
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "unlinkedDartSummary": unlinkedDartSummary,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _PackageBundleReader extends fb.TableReader<_PackageBundleImpl> {
- const _PackageBundleReader();
-
- @override
- _PackageBundleImpl createObject(fb.BufferContext bc, int offset) =>
- new _PackageBundleImpl(bc, offset);
-}
-
-class _SummarizedAnalysisErrorFromPathImpl extends Object
- with _SummarizedAnalysisErrorFromPathMixin
- implements idl.SummarizedAnalysisErrorFromPath {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- String _path;
-
- String _classname;
- idl.SummarizedAnalysisError _originalError;
- _SummarizedAnalysisErrorFromPathImpl(this._bc, this._bcOffset);
-
- @override
- String get classname {
- _classname ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
- return _classname;
- }
-
- @override
- idl.SummarizedAnalysisError get originalError {
- _originalError ??= const _SummarizedAnalysisErrorReader()
- .vTableGet(_bc, _bcOffset, 2, null);
- return _originalError;
- }
-
- @override
- String get path {
- _path ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
- return _path;
- }
-}
-
-abstract class _SummarizedAnalysisErrorFromPathMixin
- implements idl.SummarizedAnalysisErrorFromPath {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (path != '') _result["path"] = path;
- if (classname != '') _result["classname"] = classname;
- if (originalError != null)
- _result["originalError"] = originalError.toJson();
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "path": path,
- "classname": classname,
- "originalError": originalError,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedAnalysisErrorFromPathReader
- extends fb.TableReader<_SummarizedAnalysisErrorFromPathImpl> {
- const _SummarizedAnalysisErrorFromPathReader();
-
- @override
- _SummarizedAnalysisErrorFromPathImpl createObject(
- fb.BufferContext bc, int offset) =>
- new _SummarizedAnalysisErrorFromPathImpl(bc, offset);
-}
-
-class _SummarizedAnalysisErrorImpl extends Object
- with _SummarizedAnalysisErrorMixin
- implements idl.SummarizedAnalysisError {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- String _errorCode;
-
- String _message;
- String _correction;
- int _offset;
- int _length;
- _SummarizedAnalysisErrorImpl(this._bc, this._bcOffset);
-
- @override
- String get correction {
- _correction ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 2, '');
- return _correction;
- }
-
- @override
- String get errorCode {
- _errorCode ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
- return _errorCode;
- }
-
- @override
- int get length {
- _length ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 4, 0);
- return _length;
- }
-
- @override
- String get message {
- _message ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
- return _message;
- }
-
- @override
- int get offset {
- _offset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
- return _offset;
- }
-}
-
-abstract class _SummarizedAnalysisErrorMixin
- implements idl.SummarizedAnalysisError {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (errorCode != '') _result["errorCode"] = errorCode;
- if (message != '') _result["message"] = message;
- if (correction != '') _result["correction"] = correction;
- if (offset != 0) _result["offset"] = offset;
- if (length != 0) _result["length"] = length;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "errorCode": errorCode,
- "message": message,
- "correction": correction,
- "offset": offset,
- "length": length,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedAnalysisErrorReader
- extends fb.TableReader<_SummarizedAnalysisErrorImpl> {
- const _SummarizedAnalysisErrorReader();
-
- @override
- _SummarizedAnalysisErrorImpl createObject(fb.BufferContext bc, int offset) =>
- new _SummarizedAnalysisErrorImpl(bc, offset);
-}
-
-class _SummarizedBindableImpl extends Object
- with _SummarizedBindableMixin
- implements idl.SummarizedBindable {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- String _name;
-
- int _nameOffset;
- String _propName;
- int _propNameOffset;
- _SummarizedBindableImpl(this._bc, this._bcOffset);
-
- @override
- String get name {
- _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
- return _name;
- }
-
- @override
- int get nameOffset {
- _nameOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
- return _nameOffset;
- }
-
- @override
- String get propName {
- _propName ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 2, '');
- return _propName;
- }
-
- @override
- int get propNameOffset {
- _propNameOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
- return _propNameOffset;
- }
-}
-
-abstract class _SummarizedBindableMixin implements idl.SummarizedBindable {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (name != '') _result["name"] = name;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (propName != '') _result["propName"] = propName;
- if (propNameOffset != 0) _result["propNameOffset"] = propNameOffset;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "name": name,
- "nameOffset": nameOffset,
- "propName": propName,
- "propNameOffset": propNameOffset,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedBindableReader
- extends fb.TableReader<_SummarizedBindableImpl> {
- const _SummarizedBindableReader();
-
- @override
- _SummarizedBindableImpl createObject(fb.BufferContext bc, int offset) =>
- new _SummarizedBindableImpl(bc, offset);
-}
-
-class _SummarizedClassAnnotationsImpl extends Object
- with _SummarizedClassAnnotationsMixin
- implements idl.SummarizedClassAnnotations {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- String _className;
-
- List<idl.SummarizedBindable> _inputs;
- List<idl.SummarizedBindable> _outputs;
- List<idl.SummarizedContentChildField> _contentChildFields;
- List<idl.SummarizedContentChildField> _contentChildrenFields;
- _SummarizedClassAnnotationsImpl(this._bc, this._bcOffset);
-
- @override
- String get className {
- _className ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
- return _className;
- }
-
- @override
- List<idl.SummarizedContentChildField> get contentChildFields {
- _contentChildFields ??=
- const fb.ListReader<idl.SummarizedContentChildField>(
- const _SummarizedContentChildFieldReader())
- .vTableGet(
- _bc, _bcOffset, 3, const <idl.SummarizedContentChildField>[]);
- return _contentChildFields;
- }
-
- @override
- List<idl.SummarizedContentChildField> get contentChildrenFields {
- _contentChildrenFields ??=
- const fb.ListReader<idl.SummarizedContentChildField>(
- const _SummarizedContentChildFieldReader())
- .vTableGet(
- _bc, _bcOffset, 4, const <idl.SummarizedContentChildField>[]);
- return _contentChildrenFields;
- }
-
- @override
- List<idl.SummarizedBindable> get inputs {
- _inputs ??= const fb.ListReader<idl.SummarizedBindable>(
- const _SummarizedBindableReader())
- .vTableGet(_bc, _bcOffset, 1, const <idl.SummarizedBindable>[]);
- return _inputs;
- }
-
- @override
- List<idl.SummarizedBindable> get outputs {
- _outputs ??= const fb.ListReader<idl.SummarizedBindable>(
- const _SummarizedBindableReader())
- .vTableGet(_bc, _bcOffset, 2, const <idl.SummarizedBindable>[]);
- return _outputs;
- }
-}
-
-abstract class _SummarizedClassAnnotationsMixin
- implements idl.SummarizedClassAnnotations {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (className != '') _result["className"] = className;
- if (inputs.isNotEmpty)
- _result["inputs"] = inputs.map((_value) => _value.toJson()).toList();
- if (outputs.isNotEmpty)
- _result["outputs"] = outputs.map((_value) => _value.toJson()).toList();
- if (contentChildFields.isNotEmpty)
- _result["contentChildFields"] =
- contentChildFields.map((_value) => _value.toJson()).toList();
- if (contentChildrenFields.isNotEmpty)
- _result["contentChildrenFields"] =
- contentChildrenFields.map((_value) => _value.toJson()).toList();
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "className": className,
- "inputs": inputs,
- "outputs": outputs,
- "contentChildFields": contentChildFields,
- "contentChildrenFields": contentChildrenFields,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedClassAnnotationsReader
- extends fb.TableReader<_SummarizedClassAnnotationsImpl> {
- const _SummarizedClassAnnotationsReader();
-
- @override
- _SummarizedClassAnnotationsImpl createObject(
- fb.BufferContext bc, int offset) =>
- new _SummarizedClassAnnotationsImpl(bc, offset);
-}
-
-class _SummarizedContentChildFieldImpl extends Object
- with _SummarizedContentChildFieldMixin
- implements idl.SummarizedContentChildField {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- String _fieldName;
-
- int _nameOffset;
- int _nameLength;
- int _typeOffset;
- int _typeLength;
- _SummarizedContentChildFieldImpl(this._bc, this._bcOffset);
-
- @override
- String get fieldName {
- _fieldName ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
- return _fieldName;
- }
-
- @override
- int get nameLength {
- _nameLength ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 2, 0);
- return _nameLength;
- }
-
- @override
- int get nameOffset {
- _nameOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
- return _nameOffset;
- }
-
- @override
- int get typeLength {
- _typeLength ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 4, 0);
- return _typeLength;
- }
-
- @override
- int get typeOffset {
- _typeOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
- return _typeOffset;
- }
-}
-
-abstract class _SummarizedContentChildFieldMixin
- implements idl.SummarizedContentChildField {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (fieldName != '') _result["fieldName"] = fieldName;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (nameLength != 0) _result["nameLength"] = nameLength;
- if (typeOffset != 0) _result["typeOffset"] = typeOffset;
- if (typeLength != 0) _result["typeLength"] = typeLength;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "fieldName": fieldName,
- "nameOffset": nameOffset,
- "nameLength": nameLength,
- "typeOffset": typeOffset,
- "typeLength": typeLength,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedContentChildFieldReader
- extends fb.TableReader<_SummarizedContentChildFieldImpl> {
- const _SummarizedContentChildFieldReader();
-
- @override
- _SummarizedContentChildFieldImpl createObject(
- fb.BufferContext bc, int offset) =>
- new _SummarizedContentChildFieldImpl(bc, offset);
-}
-
-class _SummarizedDirectiveImpl extends Object
- with _SummarizedDirectiveMixin
- implements idl.SummarizedDirective {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- idl.SummarizedClassAnnotations _classAnnotations;
-
- String _functionName;
- bool _isComponent;
- String _selectorStr;
- int _selectorOffset;
- String _exportAs;
- int _exportAsOffset;
- String _templateUrl;
- int _templateUrlOffset;
- int _templateUrlLength;
- String _templateText;
- int _templateOffset;
- List<idl.SummarizedNgContent> _ngContents;
- bool _usesArrayOfDirectiveReferencesStrategy;
- List<idl.SummarizedDirectiveUse> _subdirectives;
- List<idl.SummarizedExportedIdentifier> _exports;
- List<idl.SummarizedPipesUse> _pipesUse;
- int _constDirectiveStrategyOffset;
- int _constDirectiveStrategyLength;
- _SummarizedDirectiveImpl(this._bc, this._bcOffset);
-
- @override
- idl.SummarizedClassAnnotations get classAnnotations {
- _classAnnotations ??= const _SummarizedClassAnnotationsReader()
- .vTableGet(_bc, _bcOffset, 0, null);
- return _classAnnotations;
- }
-
- @override
- int get constDirectiveStrategyLength {
- _constDirectiveStrategyLength ??=
- const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 18, 0);
- return _constDirectiveStrategyLength;
- }
-
- @override
- int get constDirectiveStrategyOffset {
- _constDirectiveStrategyOffset ??=
- const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
- return _constDirectiveStrategyOffset;
- }
-
- @override
- String get exportAs {
- _exportAs ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 5, '');
- return _exportAs;
- }
-
- @override
- int get exportAsOffset {
- _exportAsOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 6, 0);
- return _exportAsOffset;
- }
-
- @override
- List<idl.SummarizedExportedIdentifier> get exports {
- _exports ??= const fb.ListReader<idl.SummarizedExportedIdentifier>(
- const _SummarizedExportedIdentifierReader())
- .vTableGet(
- _bc, _bcOffset, 15, const <idl.SummarizedExportedIdentifier>[]);
- return _exports;
- }
-
- @override
- String get functionName {
- _functionName ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
- return _functionName;
- }
-
- @override
- bool get isComponent {
- _isComponent ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
- return _isComponent;
- }
-
- @override
- List<idl.SummarizedNgContent> get ngContents {
- _ngContents ??= const fb.ListReader<idl.SummarizedNgContent>(
- const _SummarizedNgContentReader())
- .vTableGet(_bc, _bcOffset, 12, const <idl.SummarizedNgContent>[]);
- return _ngContents;
- }
-
- @override
- List<idl.SummarizedPipesUse> get pipesUse {
- _pipesUse ??= const fb.ListReader<idl.SummarizedPipesUse>(
- const _SummarizedPipesUseReader())
- .vTableGet(_bc, _bcOffset, 16, const <idl.SummarizedPipesUse>[]);
- return _pipesUse;
- }
-
- @override
- int get selectorOffset {
- _selectorOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 4, 0);
- return _selectorOffset;
- }
-
- @override
- String get selectorStr {
- _selectorStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 3, '');
- return _selectorStr;
- }
-
- @override
- List<idl.SummarizedDirectiveUse> get subdirectives {
- _subdirectives ??= const fb.ListReader<idl.SummarizedDirectiveUse>(
- const _SummarizedDirectiveUseReader())
- .vTableGet(_bc, _bcOffset, 14, const <idl.SummarizedDirectiveUse>[]);
- return _subdirectives;
- }
-
- @override
- int get templateOffset {
- _templateOffset ??=
- const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 11, 0);
- return _templateOffset;
- }
-
- @override
- String get templateText {
- _templateText ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 10, '');
- return _templateText;
- }
-
- @override
- String get templateUrl {
- _templateUrl ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 7, '');
- return _templateUrl;
- }
-
- @override
- int get templateUrlLength {
- _templateUrlLength ??=
- const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 9, 0);
- return _templateUrlLength;
- }
-
- @override
- int get templateUrlOffset {
- _templateUrlOffset ??=
- const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 8, 0);
- return _templateUrlOffset;
- }
-
- @override
- bool get usesArrayOfDirectiveReferencesStrategy {
- _usesArrayOfDirectiveReferencesStrategy ??=
- const fb.BoolReader().vTableGet(_bc, _bcOffset, 13, false);
- return _usesArrayOfDirectiveReferencesStrategy;
- }
-}
-
-abstract class _SummarizedDirectiveMixin implements idl.SummarizedDirective {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (classAnnotations != null)
- _result["classAnnotations"] = classAnnotations.toJson();
- if (functionName != '') _result["functionName"] = functionName;
- if (isComponent != false) _result["isComponent"] = isComponent;
- if (selectorStr != '') _result["selectorStr"] = selectorStr;
- if (selectorOffset != 0) _result["selectorOffset"] = selectorOffset;
- if (exportAs != '') _result["exportAs"] = exportAs;
- if (exportAsOffset != 0) _result["exportAsOffset"] = exportAsOffset;
- if (templateUrl != '') _result["templateUrl"] = templateUrl;
- if (templateUrlOffset != 0)
- _result["templateUrlOffset"] = templateUrlOffset;
- if (templateUrlLength != 0)
- _result["templateUrlLength"] = templateUrlLength;
- if (templateText != '') _result["templateText"] = templateText;
- if (templateOffset != 0) _result["templateOffset"] = templateOffset;
- if (ngContents.isNotEmpty)
- _result["ngContents"] =
- ngContents.map((_value) => _value.toJson()).toList();
- if (usesArrayOfDirectiveReferencesStrategy != false)
- _result["usesArrayOfDirectiveReferencesStrategy"] =
- usesArrayOfDirectiveReferencesStrategy;
- if (subdirectives.isNotEmpty)
- _result["subdirectives"] =
- subdirectives.map((_value) => _value.toJson()).toList();
- if (exports.isNotEmpty)
- _result["exports"] = exports.map((_value) => _value.toJson()).toList();
- if (pipesUse.isNotEmpty)
- _result["pipesUse"] = pipesUse.map((_value) => _value.toJson()).toList();
- if (constDirectiveStrategyOffset != 0)
- _result["constDirectiveStrategyOffset"] = constDirectiveStrategyOffset;
- if (constDirectiveStrategyLength != 0)
- _result["constDirectiveStrategyLength"] = constDirectiveStrategyLength;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "classAnnotations": classAnnotations,
- "functionName": functionName,
- "isComponent": isComponent,
- "selectorStr": selectorStr,
- "selectorOffset": selectorOffset,
- "exportAs": exportAs,
- "exportAsOffset": exportAsOffset,
- "templateUrl": templateUrl,
- "templateUrlOffset": templateUrlOffset,
- "templateUrlLength": templateUrlLength,
- "templateText": templateText,
- "templateOffset": templateOffset,
- "ngContents": ngContents,
- "usesArrayOfDirectiveReferencesStrategy":
- usesArrayOfDirectiveReferencesStrategy,
- "subdirectives": subdirectives,
- "exports": exports,
- "pipesUse": pipesUse,
- "constDirectiveStrategyOffset": constDirectiveStrategyOffset,
- "constDirectiveStrategyLength": constDirectiveStrategyLength,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedDirectiveReader
- extends fb.TableReader<_SummarizedDirectiveImpl> {
- const _SummarizedDirectiveReader();
-
- @override
- _SummarizedDirectiveImpl createObject(fb.BufferContext bc, int offset) =>
- new _SummarizedDirectiveImpl(bc, offset);
-}
-
-class _SummarizedDirectiveUseImpl extends Object
- with _SummarizedDirectiveUseMixin
- implements idl.SummarizedDirectiveUse {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- String _name;
-
- String _prefix;
- int _offset;
- int _length;
- _SummarizedDirectiveUseImpl(this._bc, this._bcOffset);
-
- @override
- int get length {
- _length ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
- return _length;
- }
-
- @override
- String get name {
- _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
- return _name;
- }
-
- @override
- int get offset {
- _offset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 2, 0);
- return _offset;
- }
-
- @override
- String get prefix {
- _prefix ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
- return _prefix;
- }
-}
-
-abstract class _SummarizedDirectiveUseMixin
- implements idl.SummarizedDirectiveUse {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (name != '') _result["name"] = name;
- if (prefix != '') _result["prefix"] = prefix;
- if (offset != 0) _result["offset"] = offset;
- if (length != 0) _result["length"] = length;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "name": name,
- "prefix": prefix,
- "offset": offset,
- "length": length,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedDirectiveUseReader
- extends fb.TableReader<_SummarizedDirectiveUseImpl> {
- const _SummarizedDirectiveUseReader();
-
- @override
- _SummarizedDirectiveUseImpl createObject(fb.BufferContext bc, int offset) =>
- new _SummarizedDirectiveUseImpl(bc, offset);
-}
-
-class _SummarizedExportedIdentifierImpl extends Object
- with _SummarizedExportedIdentifierMixin
- implements idl.SummarizedExportedIdentifier {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- String _name;
-
- String _prefix;
- int _offset;
- int _length;
- _SummarizedExportedIdentifierImpl(this._bc, this._bcOffset);
-
- @override
- int get length {
- _length ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
- return _length;
- }
-
- @override
- String get name {
- _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
- return _name;
- }
-
- @override
- int get offset {
- _offset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 2, 0);
- return _offset;
- }
-
- @override
- String get prefix {
- _prefix ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
- return _prefix;
- }
-}
-
-abstract class _SummarizedExportedIdentifierMixin
- implements idl.SummarizedExportedIdentifier {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (name != '') _result["name"] = name;
- if (prefix != '') _result["prefix"] = prefix;
- if (offset != 0) _result["offset"] = offset;
- if (length != 0) _result["length"] = length;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "name": name,
- "prefix": prefix,
- "offset": offset,
- "length": length,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedExportedIdentifierReader
- extends fb.TableReader<_SummarizedExportedIdentifierImpl> {
- const _SummarizedExportedIdentifierReader();
-
- @override
- _SummarizedExportedIdentifierImpl createObject(
- fb.BufferContext bc, int offset) =>
- new _SummarizedExportedIdentifierImpl(bc, offset);
-}
-
-class _SummarizedNgContentImpl extends Object
- with _SummarizedNgContentMixin
- implements idl.SummarizedNgContent {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- int _offset;
-
- int _length;
- String _selectorStr;
- int _selectorOffset;
- _SummarizedNgContentImpl(this._bc, this._bcOffset);
-
- @override
- int get length {
- _length ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
- return _length;
- }
-
- @override
- int get offset {
- _offset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 0, 0);
- return _offset;
- }
-
- @override
- int get selectorOffset {
- _selectorOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
- return _selectorOffset;
- }
-
- @override
- String get selectorStr {
- _selectorStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 2, '');
- return _selectorStr;
- }
-}
-
-abstract class _SummarizedNgContentMixin implements idl.SummarizedNgContent {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (offset != 0) _result["offset"] = offset;
- if (length != 0) _result["length"] = length;
- if (selectorStr != '') _result["selectorStr"] = selectorStr;
- if (selectorOffset != 0) _result["selectorOffset"] = selectorOffset;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "offset": offset,
- "length": length,
- "selectorStr": selectorStr,
- "selectorOffset": selectorOffset,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedNgContentReader
- extends fb.TableReader<_SummarizedNgContentImpl> {
- const _SummarizedNgContentReader();
-
- @override
- _SummarizedNgContentImpl createObject(fb.BufferContext bc, int offset) =>
- new _SummarizedNgContentImpl(bc, offset);
-}
-
-class _SummarizedPipeImpl extends Object
- with _SummarizedPipeMixin
- implements idl.SummarizedPipe {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- String _pipeName;
-
- int _pipeNameOffset;
- bool _isPure;
- String _decoratedClassName;
- _SummarizedPipeImpl(this._bc, this._bcOffset);
-
- @override
- String get decoratedClassName {
- _decoratedClassName ??=
- const fb.StringReader().vTableGet(_bc, _bcOffset, 3, '');
- return _decoratedClassName;
- }
-
- @override
- bool get isPure {
- _isPure ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
- return _isPure;
- }
-
- @override
- String get pipeName {
- _pipeName ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
- return _pipeName;
- }
-
- @override
- int get pipeNameOffset {
- _pipeNameOffset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 1, 0);
- return _pipeNameOffset;
- }
-}
-
-abstract class _SummarizedPipeMixin implements idl.SummarizedPipe {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (pipeName != '') _result["pipeName"] = pipeName;
- if (pipeNameOffset != 0) _result["pipeNameOffset"] = pipeNameOffset;
- if (isPure != false) _result["isPure"] = isPure;
- if (decoratedClassName != '')
- _result["decoratedClassName"] = decoratedClassName;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "pipeName": pipeName,
- "pipeNameOffset": pipeNameOffset,
- "isPure": isPure,
- "decoratedClassName": decoratedClassName,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedPipeReader extends fb.TableReader<_SummarizedPipeImpl> {
- const _SummarizedPipeReader();
-
- @override
- _SummarizedPipeImpl createObject(fb.BufferContext bc, int offset) =>
- new _SummarizedPipeImpl(bc, offset);
-}
-
-class _SummarizedPipesUseImpl extends Object
- with _SummarizedPipesUseMixin
- implements idl.SummarizedPipesUse {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- String _name;
-
- String _prefix;
- int _offset;
- int _length;
- _SummarizedPipesUseImpl(this._bc, this._bcOffset);
-
- @override
- int get length {
- _length ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 3, 0);
- return _length;
- }
-
- @override
- String get name {
- _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
- return _name;
- }
-
- @override
- int get offset {
- _offset ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 2, 0);
- return _offset;
- }
-
- @override
- String get prefix {
- _prefix ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
- return _prefix;
- }
-}
-
-abstract class _SummarizedPipesUseMixin implements idl.SummarizedPipesUse {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (name != '') _result["name"] = name;
- if (prefix != '') _result["prefix"] = prefix;
- if (offset != 0) _result["offset"] = offset;
- if (length != 0) _result["length"] = length;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "name": name,
- "prefix": prefix,
- "offset": offset,
- "length": length,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _SummarizedPipesUseReader
- extends fb.TableReader<_SummarizedPipesUseImpl> {
- const _SummarizedPipesUseReader();
-
- @override
- _SummarizedPipesUseImpl createObject(fb.BufferContext bc, int offset) =>
- new _SummarizedPipesUseImpl(bc, offset);
-}
-
-class _UnlinkedDartSummaryImpl extends Object
- with _UnlinkedDartSummaryMixin
- implements idl.UnlinkedDartSummary {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- List<idl.SummarizedDirective> _directiveSummaries;
-
- List<idl.SummarizedClassAnnotations> _annotatedClasses;
- List<idl.SummarizedAnalysisError> _errors;
- List<idl.SummarizedPipe> _pipeSummaries;
- _UnlinkedDartSummaryImpl(this._bc, this._bcOffset);
-
- @override
- List<idl.SummarizedClassAnnotations> get annotatedClasses {
- _annotatedClasses ??= const fb.ListReader<idl.SummarizedClassAnnotations>(
- const _SummarizedClassAnnotationsReader())
- .vTableGet(_bc, _bcOffset, 1, const <idl.SummarizedClassAnnotations>[]);
- return _annotatedClasses;
- }
-
- @override
- List<idl.SummarizedDirective> get directiveSummaries {
- _directiveSummaries ??= const fb.ListReader<idl.SummarizedDirective>(
- const _SummarizedDirectiveReader())
- .vTableGet(_bc, _bcOffset, 0, const <idl.SummarizedDirective>[]);
- return _directiveSummaries;
- }
-
- @override
- List<idl.SummarizedAnalysisError> get errors {
- _errors ??= const fb.ListReader<idl.SummarizedAnalysisError>(
- const _SummarizedAnalysisErrorReader())
- .vTableGet(_bc, _bcOffset, 2, const <idl.SummarizedAnalysisError>[]);
- return _errors;
- }
-
- @override
- List<idl.SummarizedPipe> get pipeSummaries {
- _pipeSummaries ??=
- const fb.ListReader<idl.SummarizedPipe>(const _SummarizedPipeReader())
- .vTableGet(_bc, _bcOffset, 3, const <idl.SummarizedPipe>[]);
- return _pipeSummaries;
- }
-}
-
-abstract class _UnlinkedDartSummaryMixin implements idl.UnlinkedDartSummary {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (directiveSummaries.isNotEmpty)
- _result["directiveSummaries"] =
- directiveSummaries.map((_value) => _value.toJson()).toList();
- if (annotatedClasses.isNotEmpty)
- _result["annotatedClasses"] =
- annotatedClasses.map((_value) => _value.toJson()).toList();
- if (errors.isNotEmpty)
- _result["errors"] = errors.map((_value) => _value.toJson()).toList();
- if (pipeSummaries.isNotEmpty)
- _result["pipeSummaries"] =
- pipeSummaries.map((_value) => _value.toJson()).toList();
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "directiveSummaries": directiveSummaries,
- "annotatedClasses": annotatedClasses,
- "errors": errors,
- "pipeSummaries": pipeSummaries,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _UnlinkedDartSummaryReader
- extends fb.TableReader<_UnlinkedDartSummaryImpl> {
- const _UnlinkedDartSummaryReader();
-
- @override
- _UnlinkedDartSummaryImpl createObject(fb.BufferContext bc, int offset) =>
- new _UnlinkedDartSummaryImpl(bc, offset);
-}
-
-class _UnlinkedHtmlSummaryImpl extends Object
- with _UnlinkedHtmlSummaryMixin
- implements idl.UnlinkedHtmlSummary {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- List<idl.SummarizedNgContent> _ngContents;
-
- _UnlinkedHtmlSummaryImpl(this._bc, this._bcOffset);
-
- @override
- List<idl.SummarizedNgContent> get ngContents {
- _ngContents ??= const fb.ListReader<idl.SummarizedNgContent>(
- const _SummarizedNgContentReader())
- .vTableGet(_bc, _bcOffset, 0, const <idl.SummarizedNgContent>[]);
- return _ngContents;
- }
-}
-
-abstract class _UnlinkedHtmlSummaryMixin implements idl.UnlinkedHtmlSummary {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (ngContents.isNotEmpty)
- _result["ngContents"] =
- ngContents.map((_value) => _value.toJson()).toList();
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "ngContents": ngContents,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class _UnlinkedHtmlSummaryReader
- extends fb.TableReader<_UnlinkedHtmlSummaryImpl> {
- const _UnlinkedHtmlSummaryReader();
-
- @override
- _UnlinkedHtmlSummaryImpl createObject(fb.BufferContext bc, int offset) =>
- new _UnlinkedHtmlSummaryImpl(bc, offset);
-}
diff --git a/angular_analyzer_plugin/lib/src/summary/format.fbs b/angular_analyzer_plugin/lib/src/summary/format.fbs
deleted file mode 100644
index f8a2b40..0000000
--- a/angular_analyzer_plugin/lib/src/summary/format.fbs
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-//
-// This file has been automatically generated. Please do not edit it manually.
-// To regenerate the file, use the script "pkg/analyzer/tool/generate_files".
-
-
-table PackageBundle {
- unlinkedDartSummary:[UnlinkedDartSummary] (id: 0);
-}
-
-table LinkedHtmlSummary {
- errors:[SummarizedAnalysisError] (id: 0);
-
- errorsFromPath:[SummarizedAnalysisErrorFromPath] (id: 1);
-}
-
-table UnlinkedHtmlSummary {
- ngContents:[SummarizedNgContent] (id: 0);
-}
-
-table LinkedDartSummary {
- errors:[SummarizedAnalysisError] (id: 0);
-
- referencedHtmlFiles:[string] (id: 1);
-
- referencedDartFiles:[string] (id: 2);
-
- hasDartTemplates:bool (id: 3);
-}
-
-table UnlinkedDartSummary {
- directiveSummaries:[SummarizedDirective] (id: 0);
-
- annotatedClasses:[SummarizedClassAnnotations] (id: 1);
-
- errors:[SummarizedAnalysisError] (id: 2);
-
- pipeSummaries:[SummarizedPipe] (id: 3);
-}
-
-table SummarizedClassAnnotations {
- className:string (id: 0);
-
- inputs:[SummarizedBindable] (id: 1);
-
- outputs:[SummarizedBindable] (id: 2);
-
- contentChildFields:[SummarizedContentChildField] (id: 3);
-
- contentChildrenFields:[SummarizedContentChildField] (id: 4);
-}
-
-table SummarizedDirective {
- classAnnotations:SummarizedClassAnnotations (id: 0);
-
- functionName:string (id: 1);
-
- isComponent:bool (id: 2);
-
- selectorStr:string (id: 3);
-
- selectorOffset:uint (id: 4);
-
- exportAs:string (id: 5);
-
- exportAsOffset:uint (id: 6);
-
- templateUrl:string (id: 7);
-
- templateUrlOffset:uint (id: 8);
-
- templateUrlLength:uint (id: 9);
-
- templateText:string (id: 10);
-
- templateOffset:uint (id: 11);
-
- ngContents:[SummarizedNgContent] (id: 12);
-
- usesArrayOfDirectiveReferencesStrategy:bool (id: 13);
-
- subdirectives:[SummarizedDirectiveUse] (id: 14);
-
- exports:[SummarizedExportedIdentifier] (id: 15);
-
- pipesUse:[SummarizedPipesUse] (id: 16);
-
- constDirectiveStrategyOffset:uint (id: 17);
-
- constDirectiveStrategyLength:uint (id: 18);
-}
-
-table SummarizedPipe {
- pipeName:string (id: 0);
-
- pipeNameOffset:uint (id: 1);
-
- isPure:bool (id: 2);
-
- decoratedClassName:string (id: 3);
-}
-
-table SummarizedAnalysisError {
- errorCode:string (id: 0);
-
- message:string (id: 1);
-
- correction:string (id: 2);
-
- offset:uint (id: 3);
-
- length:uint (id: 4);
-}
-
-table SummarizedAnalysisErrorFromPath {
- path:string (id: 0);
-
- classname:string (id: 1);
-
- originalError:SummarizedAnalysisError (id: 2);
-}
-
-table SummarizedBindable {
- name:string (id: 0);
-
- nameOffset:uint (id: 1);
-
- propName:string (id: 2);
-
- propNameOffset:uint (id: 3);
-}
-
-table SummarizedDirectiveUse {
- name:string (id: 0);
-
- prefix:string (id: 1);
-
- offset:uint (id: 2);
-
- length:uint (id: 3);
-}
-
-table SummarizedNgContent {
- offset:uint (id: 0);
-
- length:uint (id: 1);
-
- selectorStr:string (id: 2);
-
- selectorOffset:uint (id: 3);
-}
-
-table SummarizedContentChildField {
- fieldName:string (id: 0);
-
- nameOffset:uint (id: 1);
-
- nameLength:uint (id: 2);
-
- typeOffset:uint (id: 3);
-
- typeLength:uint (id: 4);
-}
-
-table SummarizedExportedIdentifier {
- name:string (id: 0);
-
- prefix:string (id: 1);
-
- offset:uint (id: 2);
-
- length:uint (id: 3);
-}
-
-table SummarizedPipesUse {
- name:string (id: 0);
-
- prefix:string (id: 1);
-
- offset:uint (id: 2);
-
- length:uint (id: 3);
-}
-
-root_type PackageBundle;
-
-file_identifier "APdl";
diff --git a/angular_analyzer_plugin/lib/src/summary/idl.dart b/angular_analyzer_plugin/lib/src/summary/idl.dart
deleted file mode 100644
index a964512..0000000
--- a/angular_analyzer_plugin/lib/src/summary/idl.dart
+++ /dev/null
@@ -1,221 +0,0 @@
-import 'package:analyzer/src/summary/base.dart' as base;
-import 'package:analyzer/src/summary/base.dart' show Id, TopLevel;
-
-import 'format.dart' as generated;
-
-@TopLevel('APLD')
-abstract class LinkedDartSummary extends base.SummaryClass {
- factory LinkedDartSummary.fromBuffer(List<int> buffer) =>
- generated.readLinkedDartSummary(buffer);
-
- @Id(0)
- List<SummarizedAnalysisError> get errors;
-
- @Id(3)
- bool get hasDartTemplates;
-
- @Id(2)
- List<String> get referencedDartFiles;
-
- @Id(1)
- List<String> get referencedHtmlFiles;
-}
-
-@TopLevel('APLH')
-abstract class LinkedHtmlSummary extends base.SummaryClass {
- factory LinkedHtmlSummary.fromBuffer(List<int> buffer) =>
- generated.readLinkedHtmlSummary(buffer);
-
- @Id(0)
- List<SummarizedAnalysisError> get errors;
- @Id(1)
- List<SummarizedAnalysisErrorFromPath> get errorsFromPath;
-}
-
-@TopLevel('APdl')
-abstract class PackageBundle extends base.SummaryClass {
- factory PackageBundle.fromBuffer(List<int> buffer) =>
- generated.readPackageBundle(buffer);
-
- @Id(0)
- List<UnlinkedDartSummary> get unlinkedDartSummary;
-}
-
-abstract class SummarizedAnalysisError extends base.SummaryClass {
- @Id(2)
- String get correction;
- @Id(0)
- String get errorCode;
- @Id(4)
- int get length;
- @Id(1)
- String get message;
- @Id(3)
- int get offset;
-}
-
-abstract class SummarizedAnalysisErrorFromPath extends base.SummaryClass {
- @Id(1)
- String get classname;
- @Id(2)
- SummarizedAnalysisError get originalError;
- @Id(0)
- String get path;
-}
-
-abstract class SummarizedBindable extends base.SummaryClass {
- @Id(0)
- String get name;
- @Id(1)
- int get nameOffset;
- @Id(2)
- String get propName;
- @Id(3)
- int get propNameOffset;
-}
-
-abstract class SummarizedClassAnnotations extends base.SummaryClass {
- @Id(0)
- String get className;
- @Id(3)
- List<SummarizedContentChildField> get contentChildFields;
- @Id(4)
- List<SummarizedContentChildField> get contentChildrenFields;
- @Id(1)
- List<SummarizedBindable> get inputs;
- @Id(2)
- List<SummarizedBindable> get outputs;
-}
-
-abstract class SummarizedContentChildField extends base.SummaryClass {
- @Id(0)
- String get fieldName;
- @Id(2)
- int get nameLength;
- @Id(1)
- int get nameOffset;
- @Id(4)
- int get typeLength;
- @Id(3)
- int get typeOffset;
-}
-
-abstract class SummarizedDirective extends base.SummaryClass {
- @Id(0)
- SummarizedClassAnnotations get classAnnotations;
- @Id(18)
- int get constDirectiveStrategyLength;
- @Id(17)
- int get constDirectiveStrategyOffset;
- @Id(5)
- String get exportAs;
- @Id(6)
- int get exportAsOffset;
- @Id(15)
- List<SummarizedExportedIdentifier> get exports;
- @Id(1)
- String get functionName;
- @Id(2)
- bool get isComponent;
- @Id(12)
- List<SummarizedNgContent> get ngContents;
- @Id(16)
- List<SummarizedPipesUse> get pipesUse;
- @Id(4)
- int get selectorOffset;
- @Id(3)
- String get selectorStr;
- @Id(14)
- List<SummarizedDirectiveUse> get subdirectives;
- @Id(11)
- int get templateOffset;
- @Id(10)
- String get templateText;
- @Id(7)
- String get templateUrl;
- @Id(9)
- int get templateUrlLength;
- @Id(8)
- int get templateUrlOffset;
- @Id(13)
- bool get usesArrayOfDirectiveReferencesStrategy;
-}
-
-abstract class SummarizedDirectiveUse extends base.SummaryClass {
- @Id(3)
- int get length;
- @Id(0)
- String get name;
- @Id(2)
- int get offset;
- @Id(1)
- String get prefix;
-}
-
-abstract class SummarizedExportedIdentifier extends base.SummaryClass {
- @Id(3)
- int get length;
- @Id(0)
- String get name;
- @Id(2)
- int get offset;
- @Id(1)
- String get prefix;
-}
-
-abstract class SummarizedNgContent extends base.SummaryClass {
- @Id(1)
- int get length;
- @Id(0)
- int get offset;
- @Id(3)
- int get selectorOffset;
- @Id(2)
- String get selectorStr;
-}
-
-abstract class SummarizedPipe extends base.SummaryClass {
- @Id(3)
- String get decoratedClassName;
- @Id(2)
- bool get isPure;
- @Id(0)
- String get pipeName;
- @Id(1)
- int get pipeNameOffset;
-}
-
-abstract class SummarizedPipesUse extends base.SummaryClass {
- @Id(3)
- int get length;
- @Id(0)
- String get name;
- @Id(2)
- int get offset;
- @Id(1)
- String get prefix;
-}
-
-@TopLevel('APUD')
-abstract class UnlinkedDartSummary extends base.SummaryClass {
- factory UnlinkedDartSummary.fromBuffer(List<int> buffer) =>
- generated.readUnlinkedDartSummary(buffer);
-
- @Id(1)
- List<SummarizedClassAnnotations> get annotatedClasses;
- @Id(0)
- List<SummarizedDirective> get directiveSummaries;
- @Id(2)
- List<SummarizedAnalysisError> get errors;
- @Id(3)
- List<SummarizedPipe> get pipeSummaries;
-}
-
-@TopLevel('APUH')
-abstract class UnlinkedHtmlSummary extends base.SummaryClass {
- factory UnlinkedHtmlSummary.fromBuffer(List<int> buffer) =>
- generated.readUnlinkedHtmlSummary(buffer);
-
- @Id(0)
- List<SummarizedNgContent> get ngContents;
-}
diff --git a/angular_analyzer_plugin/lib/src/tasks.dart b/angular_analyzer_plugin/lib/src/tasks.dart
deleted file mode 100644
index 19714a3..0000000
--- a/angular_analyzer_plugin/lib/src/tasks.dart
+++ /dev/null
@@ -1,208 +0,0 @@
-import 'package:analyzer/dart/ast/ast.dart' as ast;
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart' as utils;
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/errors.dart';
-
-/// Helper for processing Angular annotations.
-class AnnotationProcessorMixin {
- var errorListener = new RecordingErrorListener();
- ErrorReporter errorReporter;
-
- /// The evaluator of constant values, such as annotation arguments.
- final utils.ConstantEvaluator _constantEvaluator =
- new utils.ConstantEvaluator();
-
- /// Returns the [String] value of the given [expression].
- /// If [expression] does not have a [String] value, reports an error
- /// and returns `null`.
- OffsettingConstantEvaluator calculateStringWithOffsets(
- ast.Expression expression) {
- if (expression != null) {
- final evaluator = new OffsettingConstantEvaluator();
- evaluator.value = expression.accept(evaluator);
-
- if (!evaluator.offsetsAreValid) {
- errorReporter.reportErrorForNode(
- AngularHintCode.OFFSETS_CANNOT_BE_CREATED,
- evaluator.lastUnoffsettableNode);
- } else if (evaluator.value is! String &&
- evaluator.value != utils.ConstantEvaluator.NOT_A_CONSTANT) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.STRING_VALUE_EXPECTED, expression);
- }
- return evaluator;
- }
- return null;
- }
-
- /// Returns the [String] value of the given [expression].
- /// If [expression] does not have a [String] value, reports an error
- /// and returns `null`.
- String getExpressionString(ast.Expression expression) {
- if (expression != null) {
- // ignore: omit_local_variable_types
- final Object value = expression.accept(_constantEvaluator);
- if (value is String) {
- return value;
- }
- errorReporter.reportErrorForNode(
- AngularWarningCode.STRING_VALUE_EXPECTED, expression);
- }
- return null;
- }
-
- /// Returns the value of the argument with the given [name].
- /// Returns `null` if not found.
- ast.Expression getNamedArgument(ast.Annotation node, String name) {
- if (node.arguments != null) {
- final arguments = node.arguments.arguments;
- for (var argument in arguments) {
- if (argument is ast.NamedExpression &&
- argument.name != null &&
- argument.name.label != null &&
- argument.name.label.name == name) {
- return argument.expression;
- }
- }
- }
- return null;
- }
-
- /// Initialize the processor working in the given [target].
- void initAnnotationProcessor(Source source) {
- assert(errorReporter == null);
- errorReporter = new ErrorReporter(errorListener, source);
- }
-
- /// Returns `true` is the given [node] is resolved to a creation of an Angular
- /// annotation class with the given [name].
- bool isAngularAnnotation(ast.Annotation node, String name) {
- if (node.element is ConstructorElement) {
- final clazz = node.element.enclosingElement;
- // TODO only support angular/
- return (clazz.library.source.uri.path
- .endsWith('angular/src/core/metadata.dart') ||
- clazz.library.source.uri.path
- .endsWith('angular2/src/core/metadata.dart')) &&
- clazz.name == name;
- }
- return false;
- }
-}
-
-class OffsettingConstantEvaluator extends utils.ConstantEvaluator {
- bool offsetsAreValid = true;
- Object value;
- ast.AstNode lastUnoffsettableNode;
-
- @override
- Object visitAdjacentStrings(ast.AdjacentStrings node) {
- final buffer = new StringBuffer();
- int lastEndingOffset;
- for (final string in node.strings) {
- final value = string.accept(this);
- if (identical(value, utils.ConstantEvaluator.NOT_A_CONSTANT)) {
- return value;
- }
- // preserve offsets across the split by padding
- if (lastEndingOffset != null) {
- buffer.write(' ' * (string.offset - lastEndingOffset));
- }
- lastEndingOffset = string.offset + string.length;
- buffer.write(value);
- }
- return buffer.toString();
- }
-
- @override
- Object visitBinaryExpression(ast.BinaryExpression node) {
- if (node.operator.type == TokenType.PLUS) {
- // ignore: omit_local_variable_types
- final Object leftOperand = node.leftOperand.accept(this);
- if (identical(leftOperand, utils.ConstantEvaluator.NOT_A_CONSTANT)) {
- return leftOperand;
- }
- // ignore: omit_local_variable_types
- final Object rightOperand = node.rightOperand.accept(this);
- if (identical(rightOperand, utils.ConstantEvaluator.NOT_A_CONSTANT)) {
- return rightOperand;
- }
- // numeric or {@code null}
- if (leftOperand is String && rightOperand is String) {
- final gap = node.rightOperand.offset -
- node.leftOperand.offset -
- node.leftOperand.length;
- // ignore: prefer_interpolation_to_compose_strings
- return leftOperand + (' ' * gap) + rightOperand;
- }
- }
-
- return super.visitBinaryExpression(node);
- }
-
- @override
- Object visitMethodInvocation(ast.MethodInvocation node) {
- offsetsAreValid = false;
- lastUnoffsettableNode = node;
- return super.visitMethodInvocation(node);
- }
-
- @override
- Object visitParenthesizedExpression(ast.ParenthesizedExpression node) {
- offsetsAreValid = false;
- lastUnoffsettableNode = node;
- final preGap = node.expression.offset - node.offset;
- final postGap = node.offset +
- node.length -
- node.expression.offset -
- node.expression.length;
- // ignore: omit_local_variable_types
- final Object value = super.visitParenthesizedExpression(node);
- if (value is String) {
- // ignore: prefer_interpolation_to_compose_strings
- return ' ' * preGap + value + ' ' * postGap;
- }
-
- return value;
- }
-
- @override
- Object visitPrefixedIdentifier(ast.PrefixedIdentifier node) {
- offsetsAreValid = false;
- lastUnoffsettableNode = node;
- return super.visitPrefixedIdentifier(node);
- }
-
- @override
- Object visitPropertyAccess(ast.PropertyAccess node) {
- offsetsAreValid = false;
- lastUnoffsettableNode = node;
- return super.visitPropertyAccess(node);
- }
-
- @override
- Object visitSimpleIdentifier(ast.SimpleIdentifier node) {
- offsetsAreValid = false;
- lastUnoffsettableNode = node;
- return super.visitSimpleIdentifier(node);
- }
-
- @override
- Object visitSimpleStringLiteral(ast.SimpleStringLiteral node) {
- final gap = node.contentsOffset - node.offset;
- lastUnoffsettableNode = node;
- // ignore: prefer_interpolation_to_compose_strings
- return ' ' * gap + node.value + ' ';
- }
-
- @override
- Object visitStringInterpolation(ast.StringInterpolation node) {
- offsetsAreValid = false;
- lastUnoffsettableNode = node;
- return super.visitStringInterpolation(node);
- }
-}
diff --git a/angular_analyzer_plugin/lib/src/tuple.dart b/angular_analyzer_plugin/lib/src/tuple.dart
deleted file mode 100644
index 46f4056..0000000
--- a/angular_analyzer_plugin/lib/src/tuple.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// package:tuple does not yet support Dart 2. In the meantime, hardcode the two
-// tuple types used in this project.
-
-class Tuple2<A, B> {
- final A item1;
- final B item2;
- Tuple2(this.item1, this.item2);
-}
-
-class Tuple4<A, B, C, D> {
- final A item1;
- final B item2;
- final C item3;
- final D item4;
- Tuple4(this.item1, this.item2, this.item3, this.item4);
-}
diff --git a/angular_analyzer_plugin/lib/src/view_extraction.dart b/angular_analyzer_plugin/lib/src/view_extraction.dart
deleted file mode 100644
index d318d84..0000000
--- a/angular_analyzer_plugin/lib/src/view_extraction.dart
+++ /dev/null
@@ -1,340 +0,0 @@
-import 'dart:collection';
-
-import 'package:analyzer/dart/ast/ast.dart' as ast;
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/errors.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/standard_components.dart';
-import 'package:angular_ast/angular_ast.dart' as ng_ast;
-
-import 'tasks.dart';
-
-void setIgnoredErrors(Template template, List<ng_ast.TemplateAst> asts) {
- if (asts == null || asts.isEmpty) {
- return;
- }
- for (final ast in asts) {
- if (ast is ng_ast.TextAst && ast.value.trim().isEmpty) {
- continue;
- } else if (ast is ng_ast.CommentAst) {
- var text = ast.value.trim();
- if (text.startsWith("@ngIgnoreErrors")) {
- text = text.substring("@ngIgnoreErrors".length);
- // Per spec: optional color
- if (text.startsWith(":")) {
- text = text.substring(1);
- }
- // Per spec: optional commas
- final delim = !text.contains(',') ? ' ' : ',';
- template.ignoredErrors.addAll(new HashSet.from(
- text.split(delim).map((c) => c.trim().toUpperCase())));
- }
- } else {
- return;
- }
- }
-}
-
-class TemplateParser {
- //Todo(Max): remove errorMap after new ast implemented
- static const errorMap = const {
- ng_ast.NgParserWarningCode.UNTERMINATED_MUSTACHE:
- AngularWarningCode.UNTERMINATED_MUSTACHE,
- ng_ast.NgParserWarningCode.UNOPENED_MUSTACHE:
- AngularWarningCode.UNOPENED_MUSTACHE,
- };
-
- List<ng_ast.StandaloneTemplateAst> rawAst;
- final parseErrors = <AnalysisError>[];
-
- void parse(String content, Source source, {int offset = 0}) {
- if (offset != null) {
- // ignore: prefer_interpolation_to_compose_strings, parameter_assignments
- content = ' ' * offset + content;
- }
- final exceptionHandler = new ng_ast.RecoveringExceptionHandler();
- rawAst = ng_ast.parse(
- content,
- sourceUrl: source.uri.toString(),
- desugar: false,
- parseExpressions: false,
- exceptionHandler: exceptionHandler,
- ) as List<ng_ast.StandaloneTemplateAst>;
-
- for (final e in exceptionHandler.exceptions) {
- if (e.errorCode is ng_ast.NgParserWarningCode) {
- parseErrors.add(new AnalysisError(
- source,
- e.offset,
- e.length,
- errorMap[e.errorCode] ?? e.errorCode,
- ));
- }
- }
- }
-}
-
-class ViewExtractor extends AnnotationProcessorMixin {
- AnalysisContext context;
- Source source;
- ast.CompilationUnit unit;
- List<AbstractDirective> directivesDefinedInFile;
- StandardAngular standardAngular;
-
- ViewExtractor(this.unit, this.directivesDefinedInFile, this.context,
- this.source, this.standardAngular);
-
- DirectivesStrategy findDirectives(
- ast.Annotation annotation, ClassElement classElement) {
- // Prepare directives and elementTags
- // ignore: omit_local_variable_types
- final ast.Expression listExpression =
- getNamedArgument(annotation, 'directives');
- if (listExpression is ast.ListLiteral) {
- final directiveReferences = <DirectiveReference>[];
- // ignore: omit_local_variable_types
- for (final ast.Expression item in listExpression.elements) {
- if (item is ast.Identifier) {
- final name = item.name;
- var prefix = "";
- if (item is ast.PrefixedIdentifier) {
- prefix = item.prefix.name;
- }
- final element = item.staticElement;
- // LIST_OF_DIRECTIVES or TypeLiteral
- if (element is ClassElement ||
- element is FunctionElement ||
- element is PropertyAccessorElement &&
- element.variable.constantValue != null) {
- directiveReferences.add(new DirectiveReference(
- name, prefix, new SourceRange(item.offset, item.length)));
- continue;
- }
- }
- // unknown
- errorReporter.reportErrorForNode(
- AngularWarningCode.TYPE_LITERAL_EXPECTED, item);
- }
- return new ArrayOfDirectiveReferencesStrategy(directiveReferences);
- }
-
- return new UseConstValueStrategy(classElement, standardAngular,
- new SourceRange(listExpression?.offset, listExpression?.length));
- }
-
- void findExports(
- ast.Annotation annotation, List<ExportedIdentifier> exports) {
- // ignore: omit_local_variable_types
- final ast.Expression listExpression =
- getNamedArgument(annotation, 'exports');
- final alreadyExported = new HashSet<String>();
- if (listExpression is ast.ListLiteral) {
- // ignore: omit_local_variable_types
- for (final ast.Expression item in listExpression.elements) {
- if (item is ast.Identifier) {
- // Be wary: item.name includes prefix for PrefixedIdentifier.
- var name = item.name;
-
- // Check dupes BEFORE separating the identifier & prefix
- if (alreadyExported.contains(name)) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.DUPLICATE_EXPORT, item, [name]);
- }
- alreadyExported.add(name);
-
- // Separate the identifier & prefix
- var prefix = '';
- if (item is ast.PrefixedIdentifier) {
- prefix = item.prefix.name;
- name = item.identifier.name;
- }
-
- // Record
- exports.add(new ExportedIdentifier(
- name, new SourceRange(item.offset, item.length),
- prefix: prefix));
- } else {
- errorReporter.reportErrorForNode(
- AngularWarningCode.EXPORTS_MUST_BE_PLAIN_IDENTIFIERS, item);
- }
- continue;
- }
- } else if (listExpression != null) {
- // unknown
- errorReporter.reportErrorForNode(
- AngularWarningCode.TYPE_LITERAL_EXPECTED, listExpression);
- }
- }
-
- void findPipes(
- ast.Annotation annotation, List<PipeReference> pipeReferences) {
- // Prepare directives and elementTags
- // ignore: omit_local_variable_types
- final ast.Expression listExpression = getNamedArgument(annotation, 'pipes');
- if (listExpression is ast.ListLiteral) {
- // ignore: omit_local_variable_types
- for (final ast.Expression item in listExpression.elements) {
- if (item is ast.Identifier) {
- final name = item.name;
- var prefix = "";
- if (item is ast.PrefixedIdentifier) {
- prefix = item.prefix.name;
- }
- final element = item.staticElement;
- // LIST_OF_PIPES or TypeLiteral
- if (element is ClassElement ||
- element is PropertyAccessorElement &&
- element.variable.constantValue != null) {
- pipeReferences.add(new PipeReference(
- name, new SourceRange(item.offset, item.length),
- prefix: prefix));
- continue;
- }
- }
- // unknown
- errorReporter.reportErrorForNode(
- AngularWarningCode.TYPE_LITERAL_EXPECTED, item);
- }
- }
- }
-
- List<View> getViews() {
- initAnnotationProcessor(source);
- //
- // Prepare inputs.
- //
-
- //
- // Process all classes.
- //
- final views = <View>[];
- for (final unitMember in unit.declarations) {
- if (unitMember is ast.ClassDeclaration) {
- final classElement = unitMember.declaredElement;
- ast.Annotation componentAnnotation;
-
- for (final annotation in unitMember.metadata) {
- if (isAngularAnnotation(annotation, 'Component')) {
- componentAnnotation = annotation;
- }
- }
-
- if (componentAnnotation == null) {
- continue;
- }
-
- final view = _createView(classElement, componentAnnotation);
-
- if (view != null) {
- views.add(view);
- }
- }
- }
-
- return views;
- }
-
- /// Create a new [View] for the given [annotation], may return `null`
- /// if [annotation] or [classElement] don't provide enough information.
- View _createView(ClassElement classElement, ast.Annotation annotation) {
- // Template in a separate HTML file.
- Source templateUriSource;
- var definesTemplate = false;
- var definesTemplateUrl = false;
- SourceRange templateUrlRange;
- {
- // ignore: omit_local_variable_types
- final ast.Expression templateUrlExpression =
- getNamedArgument(annotation, 'templateUrl');
- definesTemplateUrl = templateUrlExpression != null;
- final templateUrl = getExpressionString(templateUrlExpression);
- if (templateUrl != null) {
- final sourceFactory = context.sourceFactory;
- templateUriSource =
- sourceFactory.resolveUri(classElement.library.source, templateUrl);
-
- if (templateUriSource == null || !templateUriSource.exists()) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.REFERENCED_HTML_FILE_DOESNT_EXIST,
- templateUrlExpression);
- }
-
- templateUrlRange = new SourceRange(
- templateUrlExpression.offset, templateUrlExpression.length);
- }
- }
- // Try to find inline "template".
- String templateText;
- var templateOffset = 0;
- {
- // ignore: omit_local_variable_types
- final ast.Expression expression =
- getNamedArgument(annotation, 'template');
- if (expression != null) {
- templateOffset = expression.offset;
- definesTemplate = true;
- // ignore: omit_local_variable_types
- final OffsettingConstantEvaluator constantEvaluation =
- calculateStringWithOffsets(expression);
-
- // highly dynamically generated constant expressions can't be validated
- if (constantEvaluation == null ||
- !constantEvaluation.offsetsAreValid ||
- constantEvaluation.value is! String) {
- templateText = '';
- } else {
- templateText = constantEvaluation.value as String;
- }
- }
- }
-
- if (definesTemplate && definesTemplateUrl) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.TEMPLATE_URL_AND_TEMPLATE_DEFINED, annotation);
-
- return null;
- }
-
- if (!definesTemplate && !definesTemplateUrl) {
- errorReporter.reportErrorForNode(
- AngularWarningCode.NO_TEMPLATE_URL_OR_TEMPLATE_DEFINED, annotation);
-
- return null;
- }
-
- // Find the corresponding Component.
- final component = _findComponentAnnotationOrReportError(classElement);
- if (component == null) {
- return null;
- }
- final pipeReferences = <PipeReference>[];
- final directivesStrategy = findDirectives(annotation, classElement);
- findPipes(annotation, pipeReferences);
- final exports = <ExportedIdentifier>[];
- findExports(annotation, exports);
- // Create View.
- return new View(classElement, component, <AbstractDirective>[], <Pipe>[],
- templateText: templateText,
- templateOffset: templateOffset,
- templateUriSource: templateUriSource,
- templateUrlRange: templateUrlRange,
- directivesStrategy: directivesStrategy,
- pipeReferences: pipeReferences,
- annotation: annotation,
- exports: exports);
- }
-
- Component _findComponentAnnotationOrReportError(ClassElement classElement) {
- for (final directive in directivesDefinedInFile) {
- if (directive is Component && directive.classElement == classElement) {
- return directive;
- }
- }
- errorReporter.reportErrorForElement(
- AngularWarningCode.COMPONENT_ANNOTATION_MISSING, classElement, []);
- return null;
- }
-}
diff --git a/angular_analyzer_plugin/lib/starter.dart b/angular_analyzer_plugin/lib/starter.dart
deleted file mode 100644
index e0349fb..0000000
--- a/angular_analyzer_plugin/lib/starter.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:isolate';
-
-import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer_plugin/starter.dart';
-import 'package:angular_analyzer_plugin/plugin.dart';
-
-void start(List<String> args, SendPort sendPort) {
- new ServerPluginStarter(
- new AngularAnalyzerPlugin(PhysicalResourceProvider.INSTANCE))
- .start(sendPort);
-}
diff --git a/angular_analyzer_plugin/pubspec.yaml b/angular_analyzer_plugin/pubspec.yaml
deleted file mode 100644
index 43f094c..0000000
--- a/angular_analyzer_plugin/pubspec.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
-name: angular_analyzer_plugin
-version: 0.0.17+6
-description: Dart analyzer plugin for Angular 2+
-authors:
- - Konstantin Scheglov <scheglov@google.com>
- - Mike Fairhurst <mfairhurst@google.com>
- - Max Kim <maxkim@google.com>
-homepage: https://github.com/dart-lang/angular_analyzer_plugin
-environment:
- sdk: '>=2.0.0 <3.0.0'
-dependencies:
- analyzer: '0.34.2'
- plugin: '^0.2.0'
- # tuple: '^1.0.1' Does not yet support Dart 2
- analyzer_plugin: '0.0.1-alpha.6'
- angular_ast: '^0.5.0'
- meta: ^1.0.2
- yaml: ^2.1.2
- crypto: '>=1.1.1 <3.0.0'
-dev_dependencies:
- test_reflective_loader: '^0.1.0'
- test: '^1.2.0'
- mockito: '^3.0.0'
diff --git a/angular_analyzer_plugin/test/abstract_angular.dart b/angular_analyzer_plugin/test/abstract_angular.dart
deleted file mode 100644
index 1e43269..0000000
--- a/angular_analyzer_plugin/test/abstract_angular.dart
+++ /dev/null
@@ -1,351 +0,0 @@
-import 'package:analyzer/context/context_root.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
-import 'package:analyzer/src/dart/analysis/byte_store.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart'
- show AnalysisDriver, AnalysisDriverScheduler;
-import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/dart/analysis/file_state.dart';
-import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/source_io.dart';
-import 'package:angular_analyzer_plugin/notification_manager.dart';
-import 'package:angular_analyzer_plugin/src/angular_driver.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/options.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-import 'package:angular_analyzer_plugin/src/tuple.dart';
-import 'package:mockito/mockito.dart';
-import 'package:test/test.dart';
-
-import 'mock_angular.dart';
-import 'mock_sdk.dart';
-
-void assertComponentReference(
- ResolvedRange resolvedRange, Component component) {
- final selector = component.selector as ElementNameSelector;
- final element = resolvedRange.element;
- expect(element, selector.nameElement);
- expect(resolvedRange.range.length, selector.nameElement.name.length);
-}
-
-PropertyAccessorElement assertGetter(ResolvedRange resolvedRange) {
- final element =
- (resolvedRange.element as DartElement).element as PropertyAccessorElement;
- expect(element.isGetter, isTrue);
- return element;
-}
-
-void assertPropertyReference(
- ResolvedRange resolvedRange, AbstractDirective directive, String name) {
- final element = resolvedRange.element;
- for (final input in directive.inputs) {
- if (input.name == name) {
- expect(element, same(input));
- return;
- }
- }
- fail('Expected input "$name", but $element found.');
-}
-
-Component getComponentByName(List<AbstractDirective> directives, String name) =>
- getDirectiveByName(directives, name) as Component;
-
-AbstractDirective getDirectiveByName(
- List<AbstractDirective> directives, String name) =>
- directives.firstWhere((directive) => directive.name == name, orElse: () {
- fail('DirectiveMetadata with the class "$name" was not found.');
- });
-
-ResolvedRange getResolvedRangeAtString(
- String code, List<ResolvedRange> ranges, String str,
- [ResolvedRangeCondition condition]) {
- final offset = code.indexOf(str);
- return ranges.firstWhere((range) {
- if (range.range.offset == offset) {
- return condition == null || condition(range);
- }
- return false;
- }, orElse: () {
- fail(
- 'ResolvedRange at $offset of $str was not found in [\n${ranges.join('\n')}]');
- });
-}
-
-View getViewByClassName(List<View> views, String className) =>
- views.firstWhere((view) => view.classElement.name == className, orElse: () {
- fail('View with the class "$className" was not found.');
- });
-
-typedef bool ResolvedRangeCondition(ResolvedRange range);
-
-class AbstractAngularTest {
- MemoryResourceProvider resourceProvider;
-
- DartSdk sdk;
- AngularDriver angularDriver;
- AnalysisDriver dartDriver;
- AnalysisDriverScheduler scheduler;
-
- GatheringErrorListener errorListener;
-
- AngularOptions ngOptions = new AngularOptions(
- customTagNames: [
- 'my-first-custom-tag',
- 'my-second-custom-tag'
- ],
- customEvents: {
- 'custom-event': new CustomEvent('custom-event', 'CustomEvent',
- 'package:test_package/custom_event.dart', 10)
- },
- source: () {
- final mock = new MockSource();
- when(mock.fullName).thenReturn('/analysis_options.yaml');
- return mock;
- }());
-
- // flags specific to handling multiple versions of angular which may differ,
- // but we still need to support.
- final bool includeQueryList;
-
- AbstractAngularTest() : includeQueryList = true;
- AbstractAngularTest.future() : includeQueryList = false;
-
- /// Assert that the [errCode] is reported for [code], highlighting the
- /// [snippet]. Optionally, expect [additionalErrorCodes] to appear at any
- /// location.
- void assertErrorInCodeAtPosition(
- ErrorCode errCode, String code, String snippet,
- {List<ErrorCode> additionalErrorCodes}) {
- final snippetIndex = code.indexOf(snippet);
- expect(snippetIndex, greaterThan(-1),
- reason: 'Error in test: snippet $snippet not part of code $code');
- final expectedErrorCodes = (additionalErrorCodes ?? <ErrorCode>[])
- ..add(errCode);
- errorListener.assertErrorsWithCodes(expectedErrorCodes);
- final error =
- errorListener.errors.singleWhere((e) => e.errorCode == errCode);
- expect(error.offset, snippetIndex);
- expect(error.length, snippet.length);
- }
-
- /// For [expectedErrors], it is a List of Tuple4 (1 per error):
- /// code segment where offset begins,
- /// length of error highlight,
- /// errorCode,
- /// and optional error args - pass empty list if not needed.
- void assertMultipleErrorsExplicit(
- Source source,
- String code,
- List<Tuple4<String, int, ErrorCode, List<Object>>> expectedErrors,
- ) {
- final realErrors = errorListener.errors;
- for (final expectedError in expectedErrors) {
- final offset = code.indexOf(expectedError.item1);
- assert(offset != -1);
- final currentExpectedError = new AnalysisError(
- source,
- offset,
- expectedError.item2,
- expectedError.item3,
- expectedError.item4,
- );
- expect(
- realErrors.contains(currentExpectedError),
- true,
- reason: 'Expected error code ${expectedError.item3} never occurs at '
- 'location $offset of length ${expectedError.item2}.',
- );
- expect(realErrors.length, expectedErrors.length,
- reason: 'Expected error counts do not match.');
- }
- }
-
- void fillErrorListener(List<AnalysisError> errors) {
- errorListener.addAll(errors);
- }
-
- Source newSource(String path, [String content = '']) {
- final file = resourceProvider.newFile(path, content);
- final source = file.createSource();
- angularDriver.addFile(path);
- dartDriver.addFile(path);
- return source;
- }
-
- void setUp() {
- final logger = new PerformanceLog(new StringBuffer());
- final byteStore = new MemoryByteStore();
-
- scheduler = new AnalysisDriverScheduler(logger)..start();
- resourceProvider = new MemoryResourceProvider();
-
- sdk = new MockSdk(resourceProvider: resourceProvider);
- final packageMap = <String, List<Folder>>{
- 'angular2': [resourceProvider.getFolder('/angular2')],
- 'angular': [resourceProvider.getFolder('/angular')],
- 'test_package': [resourceProvider.getFolder('/')],
- };
- final packageResolver =
- new PackageMapUriResolver(resourceProvider, packageMap);
- final sf = new SourceFactory([
- new DartUriResolver(sdk),
- packageResolver,
- new ResourceUriResolver(resourceProvider)
- ]);
- final testPath = resourceProvider.convertPath('/test');
- final contextRoot = new ContextRoot(testPath, [],
- pathContext: resourceProvider.pathContext);
-
- dartDriver = new AnalysisDriver(
- new AnalysisDriverScheduler(logger)..start(),
- logger,
- resourceProvider,
- byteStore,
- new FileContentOverlay(),
- contextRoot,
- sf,
- new AnalysisOptionsImpl());
- angularDriver = new AngularDriver(
- resourceProvider,
- new MockNotificationManager(),
- dartDriver,
- scheduler,
- byteStore,
- sf,
- new FileContentOverlay(),
- ngOptions);
-
- errorListener = new GatheringErrorListener();
- addAngularSources(newSource, includeQueryList: includeQueryList);
- }
-}
-
-/// Instances of the class [GatheringErrorListener] implement an error listener
-/// that collects all of the errors passed to it for later examination.
-class GatheringErrorListener implements AnalysisErrorListener {
- /// A list containing the errors that were collected.
- final errors = <AnalysisError>[];
-
- /// Add all of the given errors to this listener.
- void addAll(List<AnalysisError> errors) {
- for (final error in errors) {
- onError(error);
- }
- }
-
- /// Assert that the number of errors that have been gathered matches the number
- /// of errors that are given and that they have the expected error codes. The
- /// order in which the errors were gathered is ignored.
- void assertErrorsWithCodes(
- [List<ErrorCode> expectedErrorCodes = const <ErrorCode>[]]) {
- final buffer = new StringBuffer();
- //
- // Verify that the expected error codes have a non-empty message.
- //
- for (final errorCode in expectedErrorCodes) {
- expect(errorCode.message.isEmpty, isFalse,
- reason: "Empty error code message");
- }
- //
- // Compute the expected number of each type of error.
- //
- final expectedCounts = <ErrorCode, int>{};
- for (final code in expectedErrorCodes) {
- var count = expectedCounts[code];
- if (count == null) {
- count = 1;
- } else {
- count = count + 1;
- }
- expectedCounts[code] = count;
- }
- //
- // Compute the actual number of each type of error.
- //
- final errorsByCode = <ErrorCode, List<AnalysisError>>{};
- for (final error in errors) {
- final code = error.errorCode;
- var list = errorsByCode[code];
- if (list == null) {
- list = <AnalysisError>[];
- errorsByCode[code] = list;
- }
- list.add(error);
- }
- //
- // Compare the expected and actual number of each type of error.
- //
- expectedCounts.forEach((code, expectedCount) {
- int actualCount;
- final list = errorsByCode.remove(code);
- if (list == null) {
- actualCount = 0;
- } else {
- actualCount = list.length;
- }
- if (actualCount != expectedCount) {
- if (buffer.length == 0) {
- buffer.write("Expected ");
- } else {
- buffer.write("; ");
- }
- buffer
- ..write(expectedCount)
- ..write(" errors of type ")
- ..write(code.uniqueName)
- ..write(", found ")
- ..write(actualCount);
- }
- });
- //
- // Check that there are no more errors in the actual-errors map,
- // otherwise record message.
- //
- errorsByCode.forEach((code, actualErrors) {
- final actualCount = actualErrors.length;
- if (buffer.isEmpty) {
- buffer.write("Expected ");
- } else {
- buffer.write("; ");
- }
- buffer
- ..write("0 errors of type ")
- ..write(code.uniqueName)
- ..write(", found ")
- ..write(actualCount)
- ..write(" (");
- for (var i = 0; i < actualErrors.length; i++) {
- final error = actualErrors[i];
- if (i > 0) {
- buffer.write(", ");
- }
- buffer.write(error.offset);
- }
- buffer.write(")");
- });
- if (buffer.length > 0) {
- fail(buffer.toString());
- }
- }
-
- /// Assert that no errors have been gathered.
- void assertNoErrors() {
- assertErrorsWithCodes();
- }
-
- @override
- void onError(AnalysisError error) {
- errors.add(error);
- }
-}
-
-class MockNotificationManager extends Mock implements NotificationManager {}
-
-class MockSource extends Mock implements Source {}
diff --git a/angular_analyzer_plugin/test/angular_driver_test.dart b/angular_analyzer_plugin/test/angular_driver_test.dart
deleted file mode 100644
index 11c17cf..0000000
--- a/angular_analyzer_plugin/test/angular_driver_test.dart
+++ /dev/null
@@ -1,5337 +0,0 @@
-import 'dart:async';
-
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/ast.dart';
-import 'package:angular_analyzer_plugin/errors.dart';
-import 'package:angular_analyzer_plugin/src/directive_linking.dart';
-import 'package:angular_analyzer_plugin/src/from_file_prefixed_error.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/options.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-import 'package:angular_analyzer_plugin/src/view_extraction.dart';
-import 'package:angular_ast/angular_ast.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'abstract_angular.dart';
-
-// ignore_for_file: deprecated_member_use
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(AngularParseHtmlTest);
- defineReflectiveTests(BuildStandardHtmlComponentsTest);
- defineReflectiveTests(BuildStandardHtmlTest);
- defineReflectiveTests(BuildStandardAngularTest);
- defineReflectiveTests(GatherAnnotationsTest);
- defineReflectiveTests(GatherAnnotationsOnFutureAngularTest);
- defineReflectiveTests(BuildUnitViewsTest);
- defineReflectiveTests(ResolveDartTemplatesTest);
- defineReflectiveTests(LinkDirectivesTest);
- defineReflectiveTests(ResolveHtmlTemplatesTest);
- defineReflectiveTests(ResolveHtmlTemplateTest);
- });
-}
-
-@reflectiveTest
-class AngularParseHtmlTest extends AbstractAngularTest {
- // ignore: non_constant_identifier_names
- void test_perform() {
- final code = r'''
-<!DOCTYPE html>
-<html>
- <head>
- <title> test page </title>
- </head>
- <body>
- <h1 myAttr='my value'>Test</h1>
- </body>
-</html>
- ''';
- final source = newSource('/test.html', code);
- final tplParser = new TemplateParser()..parse(code, source);
- expect(tplParser.parseErrors, isEmpty);
- // HTML_DOCUMENT
- {
- final asts = tplParser.rawAst;
- expect(asts, isNotNull);
- // verify that attributes are not lower-cased
- final element = asts[1].childNodes[3].childNodes[1] as ElementAst;
- expect(element.attributes.length, 1);
- expect(element.attributes[0].name, 'myAttr');
- expect(element.attributes[0].value, 'my value');
- }
- }
-
- // ignore: non_constant_identifier_names
- void test_perform_noDocType() {
- final code = r'''
-<div>AAA</div>
-<span>BBB</span>
-''';
- final source = newSource('/test.html', code);
- final tplParser = new TemplateParser()..parse(code, source);
- // validate Document
- {
- final asts = tplParser.rawAst;
- expect(asts, isNotNull);
- expect(asts.length, 4);
- expect((asts[0] as ElementAst).name, 'div');
- expect((asts[2] as ElementAst).name, 'span');
- }
- // it's OK to don't have DOCTYPE
- expect(tplParser.parseErrors, isEmpty);
- }
-
- // ignore: non_constant_identifier_names
- // ignore: non_constant_identifier_names
- void test_perform_noDocType_with_dangling_unclosed_tag() {
- final code = r'''
-<div>AAA</div>
-<span>BBB</span>
-<di''';
- final source = newSource('/test.html', code);
- final tplParser = new TemplateParser()..parse(code, source);
- // quick validate Document
- {
- final asts = tplParser.rawAst;
- expect(asts, isNotNull);
- expect(asts.length, 5);
- expect((asts[0] as ElementAst).name, 'div');
- expect((asts[2] as ElementAst).name, 'span');
- expect((asts[4] as ElementAst).name, 'di');
- }
- }
-}
-
-@reflectiveTest
-class BuildStandardAngularTest extends AbstractAngularTest {
- // ignore: non_constant_identifier_names
- Future test_perform() async {
- final ng = await angularDriver.getStandardAngular();
- // validate
- expect(ng, isNotNull);
- expect(ng.templateRef, isNotNull);
- expect(ng.elementRef, isNotNull);
- expect(ng.queryList, isNotNull);
- expect(ng.pipeTransform, isNotNull);
- expect(ng.component, isNotNull);
- }
-
- // ignore: non_constant_identifier_names
- Future test_securitySchema() async {
- final ng = await angularDriver.getStandardAngular();
- // validate
- expect(ng, isNotNull);
- expect(ng.securitySchema, isNotNull);
-
- final imgSrcSecurity = ng.securitySchema.lookup('img', 'src');
- expect(imgSrcSecurity, isNotNull);
- expect(imgSrcSecurity.safeTypes[0].toString(), 'SafeUrl');
- expect(imgSrcSecurity.sanitizationAvailable, true);
-
- final aHrefSecurity = ng.securitySchema.lookup('a', 'href');
- expect(aHrefSecurity, isNotNull);
- expect(aHrefSecurity.safeTypes[0].toString(), 'SafeUrl');
- expect(aHrefSecurity.sanitizationAvailable, true);
-
- final innerHtmlSecurity = ng.securitySchema.lookupGlobal('innerHTML');
- expect(innerHtmlSecurity, isNotNull);
- expect(innerHtmlSecurity.safeTypes[0].toString(), 'SafeHtml');
- expect(innerHtmlSecurity.sanitizationAvailable, true);
-
- final iframeSrcdocSecurity = ng.securitySchema.lookup('iframe', 'srcdoc');
- expect(iframeSrcdocSecurity, isNotNull);
- expect(iframeSrcdocSecurity.safeTypes[0].toString(), 'SafeHtml');
- expect(iframeSrcdocSecurity.sanitizationAvailable, true);
-
- final styleSecurity = ng.securitySchema.lookupGlobal('style');
- expect(styleSecurity, isNotNull);
- expect(styleSecurity.safeTypes[0].toString(), 'SafeStyle');
- expect(styleSecurity.sanitizationAvailable, true);
-
- final iframeSrcSecurity = ng.securitySchema.lookup('iframe', 'src');
- expect(iframeSrcSecurity, isNotNull);
- expect(iframeSrcSecurity.safeTypes[0].toString(), 'SafeResourceUrl');
- expect(iframeSrcSecurity.sanitizationAvailable, false);
-
- final scriptSrcSecurity = ng.securitySchema.lookup('script', 'src');
- expect(scriptSrcSecurity, isNotNull);
- expect(scriptSrcSecurity.safeTypes[0].toString(), 'SafeResourceUrl');
- expect(scriptSrcSecurity.sanitizationAvailable, false);
- }
-}
-
-@reflectiveTest
-class BuildStandardHtmlComponentsTest extends AbstractAngularTest {
- // ignore: non_constant_identifier_names
- // ignore: non_constant_identifier_names
- Future test_buildStandardHtmlAttributes() async {
- final stdhtml = await angularDriver.getStandardHtml();
- final inputElements = stdhtml.attributes;
- {
- final input = inputElements['tabIndex'];
- expect(input, isNotNull);
- expect(input.setter, isNotNull);
- expect(input.setterType.toString(), equals("int"));
- }
- {
- final input = inputElements['hidden'];
- expect(input, isNotNull);
- expect(input.setter, isNotNull);
- expect(input.setterType.toString(), equals("bool"));
- }
- {
- final input = inputElements['innerHtml'];
- expect(input, isNotNull);
- expect(identical(input, inputElements['innerHTML']), true);
- expect(input.setter, isNotNull);
- expect(input.setterType.toString(), equals('String'));
- expect(input.securityContext, isNotNull);
- expect(input.securityContext.safeTypes[0].toString(), equals('SafeHtml'));
- expect(input.securityContext.sanitizationAvailable, equals(true));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_buildStandardHtmlClasses() async {
- final stdhtml = await angularDriver.getStandardHtml();
- expect(stdhtml.elementClass, isNotNull);
- expect(stdhtml.elementClass.name, 'Element');
- expect(stdhtml.htmlElementClass, isNotNull);
- expect(stdhtml.htmlElementClass.name, 'HtmlElement');
- }
-
- // ignore: non_constant_identifier_names
- Future test_buildStandardHtmlEvents() async {
- final stdhtml = await angularDriver.getStandardHtml();
- final outputElements = stdhtml.events;
- {
- // This one is important because it proves we're using @DomAttribute
- // to generate the output name and not the method in the sdk.
- final outputElement = outputElements['keyup'];
- expect(outputElement, isNotNull);
- expect(outputElement.getter, isNotNull);
- expect(outputElement.eventType, isNotNull);
- }
- {
- final outputElement = outputElements['cut'];
- expect(outputElement, isNotNull);
- expect(outputElement.getter, isNotNull);
- expect(outputElement.eventType, isNotNull);
- }
- {
- final outputElement = outputElements['click'];
- expect(outputElement, isNotNull);
- expect(outputElement.getter, isNotNull);
- expect(outputElement.eventType, isNotNull);
- expect(outputElement.eventType.toString(), 'MouseEvent');
- }
- {
- final outputElement = outputElements['change'];
- expect(outputElement, isNotNull);
- expect(outputElement.getter, isNotNull);
- expect(outputElement.eventType, isNotNull);
- }
- {
- // used to happen from "id" which got truncated by 'on'.length
- final outputElement = outputElements[''];
- expect(outputElement, isNull);
- }
- {
- // used to happen from "hidden" which got truncated by 'on'.length
- final outputElement = outputElements['dden'];
- expect(outputElement, isNull);
- }
- {
- // missing from dart:html, and supplied manually (with no getter)
- final outputElement = outputElements['focusin'];
- expect(outputElement, isNotNull);
- expect(outputElement.eventType, isNotNull);
- expect(outputElement.eventType.toString(), 'FocusEvent');
- }
- {
- // missing from dart:html, and supplied manually (with no getter)
- final outputElement = outputElements['focusout'];
- expect(outputElement, isNotNull);
- expect(outputElement.eventType, isNotNull);
- expect(outputElement.eventType.toString(), 'FocusEvent');
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_perform() async {
- final stdhtml = await angularDriver.getStandardHtml();
- // validate
- final map = stdhtml.components;
- expect(map, isNotNull);
- // a
- {
- final component = map['a'];
- expect(component, isNotNull);
- expect(component.classElement.displayName, 'AnchorElement');
- expect(component.selector.toString(), 'a');
- final inputs = component.inputs;
- final outputElements = component.outputs;
- {
- final input = inputs.singleWhere((i) => i.name == 'href');
- expect(input, isNotNull);
- expect(input.setter, isNotNull);
- expect(input.setterType.toString(), equals("String"));
- expect(input.securityContext, isNotNull);
- expect(
- input.securityContext.safeTypes[0].toString(), equals('SafeUrl'));
- expect(input.securityContext.sanitizationAvailable, equals(true));
- }
- expect(outputElements, hasLength(0));
- expect(inputs.where((i) => i.name == '_privateField'), hasLength(0));
- }
- // button
- {
- final component = map['button'];
- expect(component, isNotNull);
- expect(component.classElement.displayName, 'ButtonElement');
- expect(component.selector.toString(), 'button');
- final inputs = component.inputs;
- final outputElements = component.outputs;
- {
- final input = inputs.singleWhere((i) => i.name == 'autofocus');
- expect(input, isNotNull);
- expect(input.setter, isNotNull);
- expect(input.setterType.toString(), equals("bool"));
- expect(input.securityContext, isNull);
- }
- expect(outputElements, hasLength(0));
- }
- // iframe
- {
- final component = map['iframe'];
- expect(component, isNotNull);
- expect(component.classElement.displayName, 'IFrameElement');
- expect(component.selector.toString(), 'iframe');
- final inputs = component.inputs;
- {
- final input = inputs.singleWhere((i) => i.name == 'src');
- expect(input, isNotNull);
- expect(input.setter, isNotNull);
- expect(input.setterType.toString(), equals("String"));
- expect(input.securityContext, isNotNull);
- expect(input.securityContext.safeTypes[0].toString(),
- equals('SafeResourceUrl'));
- expect(input.securityContext.sanitizationAvailable, equals(false));
- }
- }
- // input
- {
- final component = map['input'];
- expect(component, isNotNull);
- expect(component.classElement.displayName, 'InputElement');
- expect(component.selector.toString(), 'input');
- final outputElements = component.outputs;
- expect(outputElements, hasLength(0));
- }
- // body is one of the few elements with special events
- {
- final component = map['body'];
- expect(component, isNotNull);
- expect(component.classElement.displayName, 'BodyElement');
- expect(component.selector.toString(), 'body');
- final outputElements = component.outputs;
- expect(outputElements, hasLength(1));
- {
- final output = outputElements[0];
- expect(output.name, equals("unload"));
- expect(output.getter, isNotNull);
- expect(output.eventType, isNotNull);
- }
- }
- // h1, h2, h3
- expect(map['h1'], isNotNull);
- expect(map['h2'], isNotNull);
- expect(map['h3'], isNotNull);
- // has no mention of 'option' in the source, is hardcoded
- expect(map['option'], isNotNull);
- // <template> is special, not actually a TemplateElement
- expect(map['template'], isNull);
- // <audio> is a "specialElementClass", its ctor isn't analyzable.
- expect(map['audio'], isNotNull);
- }
-}
-
-@reflectiveTest
-class BuildStandardHtmlTest extends AbstractAngularTest {
- @override
- void setUp() {
- // Don't perform setup before tests. Tests will run `super.setUp()`.
- }
-
- // ignore: non_constant_identifier_names
- Future test_customEvents_coreTypes() async {
- ngOptions = new AngularOptions.fromString(r'''
-analyzer:
- plugins:
- angular:
- enabled: true
- custom_events:
- strEventImplicitCore:
- type: String
- strEventExplicitCore:
- type: String
- path: 'dart:core'
- boolEventImplicitCore:
- type: bool
- boolEventExplicitCore:
- type: bool
- path: 'dart:core'
-''', null);
-
- super.setUp();
-
- final html = await angularDriver.getStandardHtml();
- // validate
- expect(html, isNotNull);
- expect(html.customEvents, isNotNull);
- expect(html.customEvents, hasLength(4));
- {
- final event = html.customEvents['strEventImplicitCore'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'String');
- expect(
- event.eventType.element.source.fullName, '/sdk/lib/core/core.dart');
- }
- {
- final event = html.customEvents['strEventExplicitCore'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'String');
- expect(
- event.eventType.element.source.fullName, '/sdk/lib/core/core.dart');
- }
- {
- final event = html.customEvents['boolEventImplicitCore'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'bool');
- expect(
- event.eventType.element.source.fullName, '/sdk/lib/core/core.dart');
- }
- {
- final event = html.customEvents['boolEventExplicitCore'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'bool');
- expect(
- event.eventType.element.source.fullName, '/sdk/lib/core/core.dart');
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_customEvents_enum() async {
- ngOptions = new AngularOptions.fromString(r'''
-analyzer:
- plugins:
- angular:
- enabled: true
- custom_events:
- enumType:
- type: EnumType
- path: 'package:test_package/enum.dart'
-''', null);
-
- super.setUp();
-
- newSource('/enum.dart', r'''
-enum EnumType {}
-''');
- final html = await angularDriver.getStandardHtml();
- // validate
- expect(html, isNotNull);
- expect(html.customEvents, isNotNull);
- expect(html.customEvents, hasLength(1));
- {
- final event = html.customEvents['enumType'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'EnumType');
- expect(event.eventType.element.source.fullName, '/enum.dart');
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_customEvents_generic() async {
- ngOptions = new AngularOptions.fromString(r'''
-analyzer:
- plugins:
- angular:
- enabled: true
- custom_events:
- generic:
- type: Generic
- path: 'package:test_package/generic.dart'
-''', null);
-
- super.setUp();
-
- newSource('/generic.dart', r'''
-class Generic<T> {}
-''');
- final html = await angularDriver.getStandardHtml();
- // validate
- expect(html, isNotNull);
- expect(html.customEvents, isNotNull);
- expect(html.customEvents, hasLength(1));
- {
- final event = html.customEvents['generic'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'Generic<dynamic>');
- expect(event.eventType.element.source.fullName, '/generic.dart');
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_customEvents_noSource_dynamic() async {
- ngOptions = new AngularOptions.fromString(r'''
-analyzer:
- plugins:
- angular:
- enabled: true
- custom_events:
- noSuchSource:
- typePath: nonexist.dart
-''', null);
-
- super.setUp();
- final html = await angularDriver.getStandardHtml();
- // validate
- expect(html, isNotNull);
- expect(html.customEvents, isNotNull);
- expect(html.customEvents, hasLength(1));
- {
- final event = html.customEvents['noSuchSource'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'dynamic');
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_customEvents_noSuchIdentifier_dynamic() async {
- ngOptions = new AngularOptions.fromString(r'''
-analyzer:
- plugins:
- angular:
- enabled: true
- custom_events:
- noSuchIdentifier:
- type: NonExistEvent
- path: 'package:test_package/customevent.dart'
-''', null);
-
- super.setUp();
-
- newSource('/customevent.dart', r'''
-class NotTheCorrectEvent {}
-''');
-
- final html = await angularDriver.getStandardHtml();
- // validate
- expect(html, isNotNull);
- expect(html.customEvents, isNotNull);
- expect(html.customEvents, hasLength(1));
- {
- final event = html.customEvents['noSuchIdentifier'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'dynamic');
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_customEvents_resolved() async {
- ngOptions = new AngularOptions.fromString(r'''
-analyzer:
- plugins:
- angular:
- enabled: true
- custom_events:
- bar:
- type: BarEvent
- path: 'package:test_package/bar.dart'
-''', null);
-
- super.setUp();
-
- newSource('/bar.dart', r'''
-class BarEvent {}
-''');
- final html = await angularDriver.getStandardHtml();
- // validate
- expect(html, isNotNull);
- expect(html.customEvents, isNotNull);
- expect(html.customEvents, hasLength(1));
- {
- final event = html.customEvents['bar'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'BarEvent');
- expect(event.eventType.element.source.fullName, '/bar.dart');
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_customEvents_typedef() async {
- ngOptions = new AngularOptions.fromString(r'''
-analyzer:
- plugins:
- angular:
- enabled: true
- custom_events:
- typedef:
- type: TypeDef
- path: 'package:test_package/typedef.dart'
-''', null);
-
- super.setUp();
-
- newSource('/typedef.dart', r'''
-typedef TypeDef = int Function<T>();
-''');
- final html = await angularDriver.getStandardHtml();
- // validate
- expect(html, isNotNull);
- expect(html.customEvents, isNotNull);
- expect(html.customEvents, hasLength(1));
- {
- final event = html.customEvents['typedef'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), '() → int');
- expect(event.eventType.element.source.fullName, '/typedef.dart');
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_customEvents_typeIsNotAType_dynamic() async {
- ngOptions = new AngularOptions.fromString(r'''
-analyzer:
- plugins:
- angular:
- enabled: true
- custom_events:
- notAType:
- type: foo
- path: 'package:test_package/customevent.dart'
-''', null);
-
- super.setUp();
-
- newSource('/customevent.dart', r'''
-int foo;
-''');
- final html = await angularDriver.getStandardHtml();
- // validate
- expect(html, isNotNull);
- expect(html.customEvents, isNotNull);
- expect(html.customEvents, hasLength(1));
- {
- final event = html.customEvents['notAType'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'dynamic');
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_customEvents_untyped() async {
- ngOptions = new AngularOptions.fromString(r'''
-analyzer:
- plugins:
- angular:
- enabled: true
- custom_events:
- foo:
- bar:
-''', null);
-
- super.setUp();
- final html = await angularDriver.getStandardHtml();
- // validate
- expect(html, isNotNull);
- expect(html.customEvents, isNotNull);
- expect(html.customEvents, hasLength(2));
- {
- final event = html.customEvents['foo'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'dynamic');
- }
- {
- final event = html.customEvents['bar'];
- expect(event, isNotNull);
- expect(event.getter, isNull);
- expect(event.eventType, isNotNull);
- expect(event.eventType.toString(), 'dynamic');
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_perform() async {
- super.setUp();
- final html = await angularDriver.getStandardHtml();
- // validate
- expect(html, isNotNull);
- expect(html.events, isNotNull);
- expect(html.standardEvents, isNotNull);
- expect(html.customEvents, isNotNull);
- }
-}
-
-@reflectiveTest
-class BuildUnitViewsTest extends AbstractAngularTest {
- List<AbstractDirective> directives;
- List<Pipe> pipes;
- List<View> views;
- List<AnalysisError> errors;
-
- Future getViews(final Source source) async {
- final dartResult = await dartDriver.getResult(source.fullName);
- fillErrorListener(dartResult.errors);
- final result = await angularDriver.getAngularTopLevels(source.fullName);
- directives = result.directives;
- pipes = result.pipes;
-
- final linker = new ChildDirectiveLinker(
- angularDriver,
- angularDriver,
- await angularDriver.getStandardAngular(),
- await angularDriver.getStandardHtml(),
- new ErrorReporter(errorListener, source));
- await linker.linkDirectivesAndPipes(
- directives, pipes, dartResult.unit.element.library);
- views = directives
- .map((d) => d is Component ? d.view : null)
- .where((d) => d != null)
- .toList();
- errors = result.errors;
- fillErrorListener(errors);
- }
-
- // ignore: non_constant_identifier_names
- Future test_buildViewsDoesntGetDependentDirectives() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'other_file.dart';
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [OtherComponent])
-class MyComponent {}
-''';
- final otherCode = r'''
-import 'package:angular2/angular2.dart';
-@Component(selector: 'other-component', template: 'My template',
- directives: const [NgFor])
-class OtherComponent {}
-''';
- final source = newSource('/test.dart', code);
- newSource('/other_file.dart', otherCode);
- await getViews(source);
- {
- final view = getViewByClassName(views, 'MyComponent');
- {
- expect(view.directives, hasLength(1));
- }
-
- // shouldn't be run yet
- for (final directive in view.directives) {
- if (directive is Component) {
- expect(directive.view.directives, hasLength(0));
- }
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_constantExpressionTemplateComplexIsOnlyError() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-const String tooComplex = 'bcd';
-
-@Component(selector: 'aaa', template: 'abc' + tooComplex + "{{invalid {{stuff")
-class ComponentA {
-}
-''');
- await getViews(source);
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[AngularHintCode.OFFSETS_CANNOT_BE_CREATED]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_constantExpressionTemplateOk() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'aaa', template: 'abc' + 'bcd')
-class ComponentA {
-}
-''');
- await getViews(source);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_directives() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: '[aaa]')
-class DirectiveA {}
-
-@Directive(selector: '[bbb]')
-class DirectiveB {}
-
-@Directive(selector: '[ccc]')
-class DirectiveC {}
-
-const DIR_AB = const [DirectiveA, DirectiveB];
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [DIR_AB, DirectiveC])
-class MyComponent {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- {
- final view = getViewByClassName(views, 'MyComponent');
- {
- expect(view.directives, hasLength(3));
- final directiveClassNames =
- view.directives.map((directive) => directive.name).toList();
- expect(directiveClassNames,
- unorderedEquals(['DirectiveA', 'DirectiveB', 'DirectiveC']));
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_directives_hasError_notListVariable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-const NOT_DIRECTIVE_LIST = 42;
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [NOT_DIRECTIVE_LIST])
-class MyComponent {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[AngularWarningCode.TYPE_IS_NOT_A_DIRECTIVE]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_directives_not_list_syntax() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: '[aaa]')
-class DirectiveA {}
-
-@Directive(selector: '[bbb]')
-class DirectiveB {}
-
-const VARIABLE = const [DirectiveA, DirectiveB];
-
-@Component(selector: 'my-component', template: 'My template',
- directives: VARIABLE)
-class MyComponent {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final view = getViewByClassName(views, 'MyComponent');
- expect(
- view.directivesStrategy, const isInstanceOf<UseConstValueStrategy>());
- final directiveClassNames =
- view.directives.map((directive) => directive.name).toList();
- expect(directiveClassNames, unorderedEquals(['DirectiveA', 'DirectiveB']));
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_directives_not_list_syntax_errorWithinVariable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: 'My template',
- directives: VARIABLE)
-class MyComponent {}
-
-// A non-array is a type error in the analyzer; a non-component in an array is
-// not so we must test it. Define below usage for asserting position.
-const VARIABLE = const [Object];
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final view = getViewByClassName(views, 'MyComponent');
- expect(
- view.directivesStrategy, const isInstanceOf<UseConstValueStrategy>());
- assertErrorInCodeAtPosition(
- AngularWarningCode.TYPE_IS_NOT_A_DIRECTIVE, code, 'VARIABLE');
- }
-
- // ignore: non_constant_identifier_names
- Future test_directivesList_invalidDirectiveEntries() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: '[aaa]')
-class DirectiveA {}
-
-@Directive(selector: '[bbb]')
-void directiveB() {}
-
-void notADirective() {}
-class NotADirectiveEither {}
-
-const DIR_AB_DEEP = const [ const [ const [
- DirectiveA, directiveB, notADirective, NotADirectiveEither]]];
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [DIR_AB_DEEP])
-class MyComponent {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- {
- final view = getViewByClassName(views, 'MyComponent');
- {
- expect(view.directives, hasLength(2));
- final directiveNames =
- view.directives.map((directive) => directive.name).toList();
- expect(directiveNames, unorderedEquals(['DirectiveA', 'directiveB']));
- }
- }
-
- errorListener.assertErrorsWithCodes([
- AngularWarningCode.TYPE_IS_NOT_A_DIRECTIVE,
- AngularWarningCode.FUNCTION_IS_NOT_A_DIRECTIVE
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildChildrenSetter() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(ContentChildComp) // 1
- void set contentChild(ContentChildComp contentChild) => null;
- @ContentChildren(ContentChildComp) // 2
- void set contentChildren(List<ContentChildComp> contentChildren) => null;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
-
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(
- childrens.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final children = childrens.first.query as DirectiveQueriedChildType;
-
- expect(children.directive, equals(directives[1]));
-
- final childs = component.contentChilds;
- expect(childs, hasLength(1));
- expect(childs.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final child = childs.first.query as DirectiveQueriedChildType;
-
- expect(child.directive, equals(directives[1]));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildComponent() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(ContentChildComp)
- ContentChildComp contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childs = component.contentChilds;
- expect(childs, hasLength(1));
- expect(childs.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final child = childs.first.query as DirectiveQueriedChildType;
-
- expect(child.directive, equals(directives[1]));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildDirective_dynamicOk() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(ContentChildComp)
- dynamic contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childs = component.contentChilds;
- expect(childs, hasLength(1));
- expect(childs.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final child = childs.first.query as DirectiveQueriedChildType;
-
- expect(child.directive, equals(directives[1]));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildDirective_htmlNotAllowed() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'dart:html';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(AnchorElement)
- AnchorElement contentChild;
-}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childs = component.contentChilds;
- expect(childs, hasLength(0));
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.UNKNOWN_CHILD_QUERY_TYPE, code, 'AnchorElement');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildDirective_notAssignable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(ContentChildComp)
- String contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childs = component.contentChilds;
- expect(childs, hasLength(1));
- expect(childs.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final child = childs.first.query as DirectiveQueriedChildType;
- expect(child.directive, equals(directives[1]));
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY, code, 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildDirective_notRecognizedType() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(String)
- ElementRef contentChild;
-}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childs = component.contentChilds;
- expect(childs, hasLength(0));
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.UNKNOWN_CHILD_QUERY_TYPE, code, 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildDirective_notTypeOrString() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(const [])
- ElementRef contentChild;
-}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childs = component.contentChilds;
- expect(childs, hasLength(0));
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.UNKNOWN_CHILD_QUERY_TYPE, code, 'const []');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildDirective_subTypeNotAssignable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(ContentChildComp)
- ContentChildCompSub contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-
-class ContentChildCompSub extends ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childs = component.contentChilds;
- expect(childs, hasLength(1));
- expect(childs.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final child = childs.first.query as DirectiveQueriedChildType;
- expect(child.directive, equals(directives[1]));
-
- // validate
- assertErrorInCodeAtPosition(AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY,
- code, 'ContentChildCompSub');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildElementRef() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(ElementRef)
- ElementRef contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childs = component.contentChilds;
- expect(childs, hasLength(1));
- expect(childs.first.query, const isInstanceOf<ElementQueriedChildType>());
-
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildElementRef_notAssignable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(ElementRef)
- String contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY, code, 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildLetBound() async {
- final code = r'''
-import 'dart:html';
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild('foo')
- ContentChildComp contentChildDirective;
- @ContentChild('fooTpl')
- TemplateRef contentChildTpl;
- @ContentChild('fooElemRef')
- ElementRef contentChildElemRef;
- @ContentChild('fooElem', read: Element)
- Element contentChildElem;
- @ContentChild('fooHtmlElem', read: HtmlElement)
- HtmlElement contentChildHtmlElem;
- @ContentChild('fooDynamic')
- dynamic contentChildDynamic;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childs = component.contentChilds;
- expect(childs, hasLength(6));
-
- final childDirective = childs
- .singleWhere((c) => c.field.fieldName == "contentChildDirective")
- .query as LetBoundQueriedChildType;
- expect(childDirective, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childDirective.letBoundName, equals("foo"));
- expect(childDirective.containerType.toString(), equals("ContentChildComp"));
-
- final childTemplate = childs
- .singleWhere((c) => c.field.fieldName == "contentChildTpl")
- .query as LetBoundQueriedChildType;
- expect(childTemplate, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childTemplate.letBoundName, equals("fooTpl"));
- expect(childTemplate.containerType.toString(), equals("TemplateRef"));
-
- final childElement = childs
- .singleWhere((c) => c.field.fieldName == "contentChildElem")
- .query as LetBoundQueriedChildType;
- expect(childElement, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childElement.letBoundName, equals("fooElem"));
- expect(childElement.containerType.toString(), equals("Element"));
-
- final childHtmlElement = childs
- .singleWhere((c) => c.field.fieldName == "contentChildHtmlElem")
- .query as LetBoundQueriedChildType;
- expect(childHtmlElement, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childHtmlElement.letBoundName, equals("fooHtmlElem"));
- expect(childHtmlElement.containerType.toString(), equals("HtmlElement"));
-
- final childElementRef = childs
- .singleWhere((c) => c.field.fieldName == "contentChildElemRef")
- .query as LetBoundQueriedChildType;
- expect(childElementRef, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childElementRef.letBoundName, equals("fooElemRef"));
- expect(childElementRef.containerType.toString(), equals("ElementRef"));
-
- final childDynamic = childs
- .singleWhere((c) => c.field.fieldName == "contentChildDynamic")
- .query as LetBoundQueriedChildType;
- expect(childDynamic, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childDynamic.letBoundName, equals("fooDynamic"));
- expect(childDynamic.containerType.toString(), equals("dynamic"));
-
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- List<ContentChildComp> contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(
- childrens.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final children = childrens.first.query as DirectiveQueriedChildType;
-
- expect(children.directive, equals(directives[1]));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_dynamicIterableOk() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- Iterable contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(
- childrens.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final children = childrens.first.query as DirectiveQueriedChildType;
-
- expect(children.directive, equals(directives[1]));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_dynamicListOk() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- List contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(
- childrens.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final children = childrens.first.query as DirectiveQueriedChildType;
-
- expect(children.directive, equals(directives[1]));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_dynamicOk() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- dynamic contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(
- childrens.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final children = childrens.first.query as DirectiveQueriedChildType;
-
- expect(children.directive, equals(directives[1]));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_iterableNotAssignable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- Iterable<String> contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
-
- // validate
- assertErrorInCodeAtPosition(AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY,
- code, 'Iterable<String>');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_iterableOk() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- Iterable<ContentChildComp> contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(
- childrens.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final children = childrens.first.query as DirectiveQueriedChildType;
-
- expect(children.directive, equals(directives[1]));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_notAssignable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- List<String> contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY, code, 'List<String>');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_notList() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- String contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(
- childrens.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final children = childrens.first.query as DirectiveQueriedChildType;
- expect(children.directive, equals(directives[1]));
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.CONTENT_OR_VIEW_CHILDREN_REQUIRES_LIST,
- code,
- 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_subtypingListNotOk() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- // this is not allowed. Angular makes a List, regardless of your subtype
- CannotSubtypeList contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-
-abstract class CannotSubtypeList extends List {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(
- childrens.first.query, const isInstanceOf<DirectiveQueriedChildType>());
- final children = childrens.first.query as DirectiveQueriedChildType;
- expect(children.directive, equals(directives[1]));
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.CONTENT_OR_VIEW_CHILDREN_REQUIRES_LIST,
- code,
- 'CannotSubtypeList');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_withReadSet() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(ContentChildComp, read: ViewContainerRef)
- ViewContainerRef contentChild;
- @ContentChildren(ContentChildComp, read: ViewContainerRef)
- List<ViewContainerRef> contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(childrens.first.read.toString(), equals('ViewContainerRef'));
- final childs = component.contentChildren;
- expect(childs, hasLength(1));
- expect(childs.first.read.toString(), equals('ViewContainerRef'));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenElementRef() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ElementRef)
- List<ElementRef> contentChildren;
-}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(
- childrens.first.query, const isInstanceOf<ElementQueriedChildType>());
-
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenElementRef_notAssignable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ElementRef)
- List<String> contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY, code, 'List<String>');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenLetBound() async {
- final code = r'''
-import 'dart:html';
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren('foo')
- List<ContentChildComp> contentChildDirective;
- @ContentChildren('fooTpl')
- List<TemplateRef> contentChildTpl;
- @ContentChildren('fooElem', read: Element)
- List<Element> contentChildElem;
- @ContentChildren('fooHtmlElem', read: HtmlElement)
- List<HtmlElement> contentChildHtmlElem;
- @ContentChildren('fooElemRef')
- List<ElementRef> contentChildElemRef;
- @ContentChildren('fooDynamic')
- List contentChildDynamic;
- @ContentChildren('fooQueryList')
- QueryList<ContentChildComp> contentChildQueryList;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(7));
-
- final childrenDirective = childrens
- .singleWhere((c) => c.field.fieldName == "contentChildDirective")
- .query as LetBoundQueriedChildType;
- expect(childrenDirective, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childrenDirective.letBoundName, equals("foo"));
- expect(
- childrenDirective.containerType.toString(), equals("ContentChildComp"));
-
- final childrenTemplate = childrens
- .singleWhere((c) => c.field.fieldName == "contentChildTpl")
- .query as LetBoundQueriedChildType;
- expect(childrenTemplate, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childrenTemplate.letBoundName, equals("fooTpl"));
- expect(childrenTemplate.containerType.toString(), equals("TemplateRef"));
-
- final childrenElement = childrens
- .singleWhere((c) => c.field.fieldName == "contentChildElem")
- .query as LetBoundQueriedChildType;
- expect(childrenElement, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childrenElement.letBoundName, equals("fooElem"));
- expect(childrenElement.containerType.toString(), equals("Element"));
-
- final childrenHtmlElement = childrens
- .singleWhere((c) => c.field.fieldName == "contentChildHtmlElem")
- .query as LetBoundQueriedChildType;
- expect(childrenHtmlElement, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childrenHtmlElement.letBoundName, equals("fooHtmlElem"));
- expect(childrenHtmlElement.containerType.toString(), equals("HtmlElement"));
-
- final childrenElementRef = childrens
- .singleWhere((c) => c.field.fieldName == "contentChildElemRef")
- .query as LetBoundQueriedChildType;
- expect(childrenElementRef, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childrenElementRef.letBoundName, equals("fooElemRef"));
- expect(childrenElementRef.containerType.toString(), equals("ElementRef"));
-
- final childrenDynamic = childrens
- .singleWhere((c) => c.field.fieldName == "contentChildDynamic")
- .query as LetBoundQueriedChildType;
- expect(childrenDynamic, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childrenDynamic.letBoundName, equals("fooDynamic"));
- expect(childrenDynamic.containerType.toString(), equals("dynamic"));
-
- final childrenQueryList = childrens
- .singleWhere((c) => c.field.fieldName == "contentChildQueryList")
- .query as LetBoundQueriedChildType;
- expect(childrenQueryList, const isInstanceOf<LetBoundQueriedChildType>());
- expect(childrenQueryList.letBoundName, equals("fooQueryList"));
- expect(
- childrenQueryList.containerType.toString(), equals("ContentChildComp"));
-
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenLetBound_elementReadDoesntMatchType() async {
- final code = r'''
-import 'dart:html';
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild('el', read: Element)
- ElementRef elemRefNotElem;
- @ContentChild('el', read: HtmlElement)
- ElementRef elemRefNotHtmlElem;
- @ContentChild('el', read: Element)
- HtmlElement htmlElemNotElem;
-}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
-
- errorListener.assertErrorsWithCodes([
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY,
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY,
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY,
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenLetBound_elementWithoutReadError() async {
- final code = r'''
-import 'dart:html';
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren('el') // missing read: Element
- List<Element> contentChildrenElem;
- @ContentChild('el') // missing read: Element
- Element contentChildElem;
- @ContentChild('el') // missing read: HtmlElement
- HtmlElement contentChildHtmlElem;
- @ContentChildren('el') // missing read: HtmlElement
- List<HtmlElement> contentChildrenHtmlElem;
- @ContentChildren('el', read: Element) // not HtmlElement
- List<HtmlElement> contentChildrenNotHtmlElem;
- @ContentChild('el', read: Element) // not HtmlElement
- HtmlElement contentChildNotHtmlElem;
-}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
-
- errorListener.assertErrorsWithCodes([
- AngularWarningCode.CHILD_QUERY_TYPE_REQUIRES_READ,
- AngularWarningCode.CHILD_QUERY_TYPE_REQUIRES_READ,
- AngularWarningCode.CHILD_QUERY_TYPE_REQUIRES_READ,
- AngularWarningCode.CHILD_QUERY_TYPE_REQUIRES_READ,
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY,
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY,
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenLetBound_readSubtypeOfAttribute() async {
- final code = r'''
-import 'dart:html';
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild('el', read: Element)
- Object objectNotElem;
- @ContentChild('el', read: HtmlElement)
- Element elemNotHtmlElem;
- @ContentChild('el', read: HtmlElement)
- Object objectNotHtmlElem;
-}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final children = component.contentChilds;
- expect(children, hasLength(3));
-
- final objectNotElem = children
- .singleWhere((c) => c.field.fieldName == 'objectNotElem')
- .query as LetBoundQueriedChildType;
- expect(objectNotElem, const isInstanceOf<LetBoundQueriedChildType>());
- expect(objectNotElem.letBoundName, equals('el'));
- expect(objectNotElem.containerType.toString(), equals('Element'));
-
- final elemNotHtmlElem = children
- .singleWhere((c) => c.field.fieldName == 'elemNotHtmlElem')
- .query as LetBoundQueriedChildType;
- expect(elemNotHtmlElem, const isInstanceOf<LetBoundQueriedChildType>());
- expect(elemNotHtmlElem.letBoundName, equals('el'));
- expect(elemNotHtmlElem.containerType.toString(), equals('HtmlElement'));
-
- final objectNotHtmlElem = children
- .singleWhere((c) => c.field.fieldName == 'objectNotHtmlElem')
- .query as LetBoundQueriedChildType;
- expect(objectNotHtmlElem, const isInstanceOf<LetBoundQueriedChildType>());
- expect(objectNotHtmlElem.letBoundName, equals('el'));
- expect(objectNotHtmlElem.containerType.toString(), equals('HtmlElement'));
-
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenTemplateRef() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(TemplateRef)
- List<TemplateRef> contentChildren;
-}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childrens = component.contentChildren;
- expect(childrens, hasLength(1));
- expect(childrens.first.query,
- const isInstanceOf<TemplateRefQueriedChildType>());
-
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenTemplateRef_notAssignable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(TemplateRef)
- List<String> contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY, code, 'List<String>');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildTemplateRef() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(TemplateRef)
- TemplateRef contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- final component = directives.first;
- final childs = component.contentChilds;
- expect(childs, hasLength(1));
- expect(
- childs.first.query, const isInstanceOf<TemplateRefQueriedChildType>());
-
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildTemplateRef_notAssignable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(TemplateRef)
- String contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
-
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.INVALID_TYPE_FOR_CHILD_QUERY, code, 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_missingHtmlFile() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', templateUrl: 'missing-template.html')
-class MyComponent {}
-''';
- final dartSource = newSource('/test.dart', code);
- await getViews(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.REFERENCED_HTML_FILE_DOESNT_EXIST,
- code,
- "'missing-template.html'");
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_NeitherTemplateNorTemplateUrlDefined() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'aaa')
-class ComponentA {
-}
-''');
- await getViews(source);
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[AngularWarningCode.NO_TEMPLATE_URL_OR_TEMPLATE_DEFINED]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_StringValueExpected() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'aaa', template: 55)
-class ComponentA {
-}
-''');
- await getViews(source);
- errorListener.assertErrorsWithCodes(<ErrorCode>[
- AngularWarningCode.STRING_VALUE_EXPECTED,
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_TemplateAndTemplateUrlDefined() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'aaa', template: 'AAA', templateUrl: 'a.html')
-class ComponentA {
-}
-''');
- newSource('/a.html', '');
- await getViews(source);
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[AngularWarningCode.TEMPLATE_URL_AND_TEMPLATE_DEFINED]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_TypeLiteralExpected() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'aaa', template: 'AAA', directives: const [42])
-class ComponentA {
-}
-''');
- await getViews(source);
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[AngularWarningCode.TYPE_LITERAL_EXPECTED]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_pipe_hasError_TypeLiteralExpected() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'aaa', template: 'AAA', pipes: const [42])
-class ComponentA {
-}
-''');
- await getViews(source);
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[AngularWarningCode.TYPE_LITERAL_EXPECTED]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_pipes() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Pipe('pipeA')
-class PipeA extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-@Pipe('pipeB', pure: false)
-class PipeB extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-@Component(selector: 'my-component', template: 'MyTemplate',
- pipes: const [PipeA, PipeB])
-class MyComponent {}
- ''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- {
- final view = getViewByClassName(views, 'MyComponent');
- {
- expect(view.pipes, hasLength(2));
- final pipeNames =
- view.pipes.map((pipe) => pipe.classElement.name).toList();
- expect(pipeNames, unorderedEquals(['PipeA', 'PipeB']));
- }
- }
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_pipes_hasError_notListVariable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-const NOT_PIPES_LIST = 42;
-
-@Component(selector: 'my-component', template: 'My template',
- pipes: const [NOT_PIPES_LIST])
-class MyComponent {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[AngularWarningCode.TYPE_IS_NOT_A_PIPE]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_pipes_list_recursive() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Pipe('pipeA')
-class PipeA extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-@Pipe('pipeB', pure: false)
-class PipeB extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-@Pipe('pipeC')
-class PipeC extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-@Pipe('pipeD')
-class PipeD extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-const PIPELIST_ONE = const [ const [PipeA, PipeB]];
-const PIPELIST_TWO = const [ const [ const [PipeC, PipeD]]];
-const BIGPIPELIST = const [PIPELIST_ONE, PIPELIST_TWO];
-
-@Component(selector: 'my-component', template: 'MyTemplate',
- pipes: const [BIGPIPELIST])
-class MyComponent {}
- ''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- {
- final view = getViewByClassName(views, 'MyComponent');
- {
- expect(view.pipes, hasLength(4));
- final pipeNames =
- view.pipes.map((pipe) => pipe.classElement.name).toList();
- expect(
- pipeNames, unorderedEquals(['PipeA', 'PipeB', 'PipeC', 'PipeD']));
- }
- }
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_pipes_selective() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Pipe('pipeA')
-class PipeA extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-@Pipe('pipeB', pure: false)
-class PipeB extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-@Pipe('pipeC')
-class PipeC extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-@Component(selector: 'my-component', template: 'MyTemplate',
- pipes: const [PipeC, PipeB])
-class MyComponent {}
- ''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- {
- final view = getViewByClassName(views, 'MyComponent');
- {
- expect(view.pipes, hasLength(2));
- final pipeNames =
- view.pipes.map((pipe) => pipe.classElement.name).toList();
- expect(pipeNames, unorderedEquals(['PipeC', 'PipeB']));
- }
- }
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_prefixedDirectives() async {
- final otherCode = r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: '[aaa]')
-class DirectiveA {}
-
-@Directive(selector: '[bbb]')
-class DirectiveB {}
-
-@Directive(selector: '[ccc]')
-class DirectiveC {}
-
-const DIR_AB = const [DirectiveA, DirectiveB];
-''';
-
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'other.dart' as other;
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [other.DIR_AB, other.DirectiveC])
-class MyComponent {}
-''';
- final source = newSource('/test.dart', code);
- newSource('/other.dart', otherCode);
- await getViews(source);
- {
- final view = getViewByClassName(views, 'MyComponent');
- {
- expect(view.directives, hasLength(3));
- final directiveClassNames =
- view.directives.map((directive) => directive.name).toList();
- expect(directiveClassNames,
- unorderedEquals(['DirectiveA', 'DirectiveB', 'DirectiveC']));
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_recursiveDirectivesList() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: '[aaa]')
-class DirectiveA {}
-
-@Directive(selector: '[bbb]')
-class DirectiveB {}
-
-const DIR_AB_DEEP = const [ const [ const [DirectiveA, DirectiveB]]];
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [DIR_AB_DEEP])
-class MyComponent {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- {
- final view = getViewByClassName(views, 'MyComponent');
- {
- expect(view.directives, hasLength(2));
- final directiveClassNames =
- view.directives.map((directive) => directive.name).toList();
- expect(
- directiveClassNames, unorderedEquals(['DirectiveA', 'DirectiveB']));
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_template_relativeToLibForParts() async {
- final libCode = r'''
-import 'package:angular2/angular2.dart';
-part 'parts/part.dart';
- ''';
- final partCode = r'''
-part of '../lib.dart';
-@Component(selector: 'my-component', templateUrl: 'parts/my-template.html')
-class MyComponent {}
-''';
- final dartLibSource = newSource('/lib.dart', libCode);
- final dartPartSource = newSource('/parts/part.dart', partCode);
- final htmlSource = newSource('/parts/my-template.html', '');
- await getViews(dartPartSource);
- errorListener.assertNoErrors();
- expect(views, hasLength(1));
- // MyComponent
- final view = getViewByClassName(views, 'MyComponent');
- expect(view.component, getComponentByName(directives, 'MyComponent'));
- expect(view.templateText, isNull);
- expect(view.templateUriSource, isNotNull);
- expect(view.templateUriSource, htmlSource);
- expect(view.templateSource, htmlSource);
- {
- final url = "'parts/my-template.html'";
- expect(view.templateUrlRange,
- new SourceRange(partCode.indexOf(url), url.length));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_templateExternal() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', templateUrl: 'my-template.html')
-class MyComponent {}
-''';
- final dartSource = newSource('/test.dart', code);
- final htmlSource = newSource('/my-template.html', '');
- await getViews(dartSource);
- expect(views, hasLength(1));
- // MyComponent
- final view = getViewByClassName(views, 'MyComponent');
- expect(view.component, getComponentByName(directives, 'MyComponent'));
- expect(view.templateText, isNull);
- expect(view.templateUriSource, isNotNull);
- expect(view.templateUriSource, htmlSource);
- expect(view.templateSource, htmlSource);
- {
- final url = "'my-template.html'";
- expect(view.templateUrlRange,
- new SourceRange(code.indexOf(url), url.length));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_templateInline() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: 'my-directive')
-class MyDirective {}
-
-@Component(selector: 'other-component', template: 'Other template')
-class OtherComponent {}
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [MyDirective, OtherComponent])
-class MyComponent {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- expect(views, hasLength(2));
- {
- final view = getViewByClassName(views, 'MyComponent');
- expect(view.component, getComponentByName(directives, 'MyComponent'));
- expect(view.templateText, ' My template '); // spaces preserve offsets
- expect(view.templateOffset, code.indexOf('My template') - 1);
- expect(view.templateUriSource, isNull);
- expect(view.templateSource, source);
- {
- expect(view.directives, hasLength(2));
- final directiveClassNames =
- view.directives.map((directive) => directive.name).toList();
- expect(directiveClassNames,
- unorderedEquals(['OtherComponent', 'MyDirective']));
- }
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_useFunctionalDirective() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: 'my-directive')
-void myDirective() {}
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [myDirective])
-class MyComponent {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- errorListener.assertNoErrors();
- expect(views, hasLength(1));
- final view = views.single;
- expect(view.component.name, 'MyComponent');
- expect(view.directives, hasLength(1));
- final directive = view.directives.single;
- expect(directive.name, 'myDirective');
- expect(directive, const isInstanceOf<FunctionalDirective>());
- }
-
- // ignore: non_constant_identifier_names
- Future test_useFunctionNotFunctionalDirective() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [notDirective])
-class MyComponent {}
-
-// put this after component, so indexOf works in assertErrorInCodeAtPosition
-void notDirective() {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- assertErrorInCodeAtPosition(
- AngularWarningCode.FUNCTION_IS_NOT_A_DIRECTIVE, code, 'notDirective');
- }
-
- // ignore: non_constant_identifier_names
- Future test_validFunctionalDirectivesList() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: '[aaa]')
-void directiveA() {}
-
-@Directive(selector: '[bbb]')
-void directiveB() {}
-
-const DIR_AB_DEEP = const [ const [ const [directiveA, directiveB]]];
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [DIR_AB_DEEP])
-class MyComponent {}
-''';
- final source = newSource('/test.dart', code);
- await getViews(source);
- errorListener.assertNoErrors();
- {
- final view = getViewByClassName(views, 'MyComponent');
- {
- expect(view.directives, hasLength(2));
- final directiveNames =
- view.directives.map((directive) => directive.name).toList();
- expect(directiveNames, unorderedEquals(['directiveA', 'directiveB']));
- }
- }
- }
-}
-
-@reflectiveTest
-class GatherAnnotationsOnFutureAngularTest extends AbstractAngularTest
- with GatherAnnotationsTestMixin {
- GatherAnnotationsOnFutureAngularTest() : super.future();
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_worksInFuture() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- List<ContentChildComp> contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.first;
- final childrenFields = component.contentChildrenFields;
- expect(childrenFields, hasLength(1));
- final children = childrenFields.first;
- expect(children.fieldName, equals("contentChildren"));
- expect(
- children.nameRange.offset, equals(code.indexOf("ContentChildComp)")));
- expect(children.nameRange.length, equals("ContentChildComp".length));
- expect(children.typeRange.offset,
- equals(code.indexOf("List<ContentChildComp>")));
- expect(children.typeRange.length, equals("List<ContentChildComp>".length));
- // validate
- errorListener.assertNoErrors();
- }
-}
-
-@reflectiveTest
-class GatherAnnotationsTest extends AbstractAngularTest
- with GatherAnnotationsTestMixin {
- // ignore: non_constant_identifier_names
- Future test_Component() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'comp-a', template:'')
-class ComponentA {
-}
-
-@Component(selector: 'comp-b', template:'')
-class ComponentB {
-}
-''');
- await getDirectives(source);
- expect(directives, hasLength(2));
- {
- final component = directives[0];
- expect(component, const isInstanceOf<Component>());
- {
- final selector = component.selector;
- expect(selector, const isInstanceOf<ElementNameSelector>());
- expect(selector.toString(), 'comp-a');
- }
- {
- expect(component.elementTags, hasLength(1));
- final selector = component.elementTags[0];
- expect(selector, const isInstanceOf<ElementNameSelector>());
- expect(selector.toString(), 'comp-a');
- }
- }
- {
- final component = directives[1];
- expect(component, const isInstanceOf<Component>());
- {
- final selector = component.selector;
- expect(selector, const isInstanceOf<ElementNameSelector>());
- expect(selector.toString(), 'comp-b');
- }
- {
- expect(component.elementTags, hasLength(1));
- final selector = component.elementTags[0];
- expect(selector, const isInstanceOf<ElementNameSelector>());
- expect(selector.toString(), 'comp-b');
- }
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_Directive() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: 'dir-a')
-class DirectiveA {
-}
-
-@Directive(selector: 'dir-b')
-class DirectiveB {
-}
-''');
- await getDirectives(source);
- expect(directives, hasLength(2));
- {
- final directive = directives[0];
- expect(directive, const isInstanceOf<Directive>());
- {
- final selector = directive.selector;
- expect(selector, const isInstanceOf<ElementNameSelector>());
- expect(selector.toString(), 'dir-a');
- }
- {
- expect(directive.elementTags, hasLength(1));
- final selector = directive.elementTags[0];
- expect(selector, const isInstanceOf<ElementNameSelector>());
- expect(selector.toString(), 'dir-a');
- }
- }
- {
- final directive = directives[1];
- expect(directive, const isInstanceOf<Directive>());
- {
- final selector = directive.selector;
- expect(selector, const isInstanceOf<ElementNameSelector>());
- expect(selector.toString(), 'dir-b');
- }
- {
- expect(directive.elementTags, hasLength(1));
- final selector = directive.elementTags[0];
- expect(selector, const isInstanceOf<ElementNameSelector>());
- expect(selector.toString(), 'dir-b');
- }
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_Directive_elementTags_AndSelector() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: 'dir-a.myClass[myAttr]')
-class DirectiveA {
-}
-
-@Directive(selector: 'dir-b[myAttr]')
-class DirectiveB {
-}
-''');
- await getDirectives(source);
- expect(directives, hasLength(2));
- {
- final directive = directives[0];
- expect(directive, const isInstanceOf<Directive>());
- {
- final selector = directive.selector;
- expect(selector, const isInstanceOf<AndSelector>());
- expect((selector as AndSelector).selectors, hasLength(3));
- }
- {
- expect(directive.elementTags, hasLength(1));
- expect(directive.elementTags[0],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[0].toString(), 'dir-a');
- }
- }
- {
- final directive = directives[1];
- expect(directive, const isInstanceOf<Directive>());
- {
- final selector = directive.selector;
- expect(selector, const isInstanceOf<AndSelector>());
- expect((selector as AndSelector).selectors, hasLength(2));
- }
- {
- expect(directive.elementTags, hasLength(1));
- expect(directive.elementTags[0],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[0].toString(), 'dir-b');
- }
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_Directive_elementTags_CompoundSelector() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: 'dir-a1.myClass[myAttr], dir-a2.otherClass')
-class DirectiveA {
-}
-
-@Directive(selector: 'dir-b1[myAttr], dir-b2')
-class DirectiveB {
-}
-''');
- await getDirectives(source);
- expect(directives, hasLength(2));
- {
- final directive = directives[0];
- expect(directive, const isInstanceOf<Directive>());
- {
- final selector = directive.selector;
- expect(selector, const isInstanceOf<OrSelector>());
- expect((selector as OrSelector).selectors, hasLength(2));
- }
- {
- expect(directive.elementTags, hasLength(2));
- expect(directive.elementTags[0],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[0].toString(), 'dir-a1');
- expect(directive.elementTags[1],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[1].toString(), 'dir-a2');
- }
- }
- {
- final directive = directives[1];
- expect(directive, const isInstanceOf<Directive>());
- {
- final selector = directive.selector;
- expect(selector, const isInstanceOf<OrSelector>());
- expect((selector as OrSelector).selectors, hasLength(2));
- }
- {
- expect(directive.elementTags, hasLength(2));
- expect(directive.elementTags[0],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[0].toString(), 'dir-b1');
- expect(directive.elementTags[1],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[1].toString(), 'dir-b2');
- }
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_Directive_elementTags_OrSelector() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: 'dir-a1, dir-a2, dir-a3')
-class DirectiveA {
-}
-
-@Directive(selector: 'dir-b1, dir-b2')
-class DirectiveB {
-}
-''');
- await getDirectives(source);
- expect(directives, hasLength(2));
- {
- final directive = directives[0];
- expect(directive, const isInstanceOf<Directive>());
- {
- final selector = directive.selector;
- expect(selector, const isInstanceOf<OrSelector>());
- expect((selector as OrSelector).selectors, hasLength(3));
- }
- {
- expect(directive.elementTags, hasLength(3));
- expect(directive.elementTags[0],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[0].toString(), 'dir-a1');
- expect(directive.elementTags[1],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[1].toString(), 'dir-a2');
- expect(directive.elementTags[2],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[2].toString(), 'dir-a3');
- }
- }
- {
- final directive = directives[1];
- expect(directive, const isInstanceOf<Directive>());
- {
- final selector = directive.selector;
- expect(selector, const isInstanceOf<OrSelector>());
- expect((selector as OrSelector).selectors, hasLength(2));
- }
- {
- expect(directive.elementTags, hasLength(2));
- expect(directive.elementTags[0],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[0].toString(), 'dir-b1');
- expect(directive.elementTags[1],
- const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[1].toString(), 'dir-b2');
- }
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_exportAs_Component() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'aaa', exportAs: 'export-name', template:'')
-class ComponentA {
-}
-
-@Component(selector: 'bbb', template:'')
-class ComponentB {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- expect(directives, hasLength(2));
- {
- final component = getComponentByName(directives, 'ComponentA');
- {
- final exportAs = component.exportAs;
- expect(exportAs.name, 'export-name');
- expect(exportAs.nameOffset, code.indexOf('export-name'));
- }
- }
- {
- final component = getComponentByName(directives, 'ComponentB');
- {
- final exportAs = component.exportAs;
- expect(exportAs, isNull);
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_exportAs_constantStringExpressionOk() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'aaa', exportAs: 'a' + 'b', template:'')
-class ComponentA {
-}
-''');
- await getDirectives(source);
- expect(directives, hasLength(1));
- // has no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_exportAs_Directive() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: '[aaa]', exportAs: 'export-name')
-class DirectiveA {
-}
-
-@Directive(selector: '[bbb]')
-class DirectiveB {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- expect(directives, hasLength(2));
- {
- final directive = getDirectiveByName(directives, 'DirectiveA');
- {
- final exportAs = directive.exportAs;
- expect(exportAs.name, 'export-name');
- expect(exportAs.nameOffset, code.indexOf('export-name'));
- }
- }
- {
- final directive = getDirectiveByName(directives, 'DirectiveB');
- {
- final exportAs = directive.exportAs;
- expect(exportAs, isNull);
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_exportAs_hasError_notStringValue() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'aaa', exportAs: 42, template:'')
-class ComponentA {
-}
-''');
- await getDirectives(source);
- expect(directives, hasLength(1));
- // has an error
- errorListener.assertErrorsWithCodes(<ErrorCode>[
- AngularWarningCode.STRING_VALUE_EXPECTED,
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_finalPropertyInputError() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '<p></p>')
-class MyComponent {
- @Input() final int immutable = 1;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.INPUT_ANNOTATION_PLACEMENT_INVALID,
- code,
- "@Input()");
- }
-
- // ignore: non_constant_identifier_names
- Future test_finalPropertyInputErrorNonDirective() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-class MyNonDirective {
- @Input() final int immutable = 1;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.INPUT_ANNOTATION_PLACEMENT_INVALID,
- code,
- "@Input()");
- }
-
- // ignore: non_constant_identifier_names
- Future test_FunctionalDirective() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: 'dir-a.myClass[myAttr]')
-void directiveA() {
-}
-''');
- await getDirectives(source);
- expect(directives, hasLength(1));
- final directive = directives.single;
- expect(directive, const isInstanceOf<FunctionalDirective>());
- expect(directive.name, "directiveA");
- final selector = directive.selector;
- expect(selector, const isInstanceOf<AndSelector>());
- expect((selector as AndSelector).selectors, hasLength(3));
- expect(directive.elementTags, hasLength(1));
- expect(directive.elementTags[0], const isInstanceOf<ElementNameSelector>());
- expect(directive.elementTags[0].toString(), 'dir-a');
- }
-
- // ignore: non_constant_identifier_names
- Future test_FunctionalDirective_notAllowedValues() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Directive(selector: 'dir-a.myClass[myAttr]',
- exportAs: 'foo')
-void directiveA() {
-}
-''');
- await getDirectives(source);
- errorListener.assertErrorsWithCodes(
- [AngularWarningCode.FUNCTIONAL_DIRECTIVES_CANT_BE_EXPORTED]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildChildrenNoRangeNotRecorded() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren()
- List<ContentChildComp> contentChildren;
- @ContentChild()
- ContentChildComp contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.first;
- final childrenFields = component.contentChildrenFields;
- expect(childrenFields, hasLength(0));
- final childFields = component.contentChildFields;
- expect(childFields, hasLength(0));
- // validate
- errorListener.assertErrorsWithCodes([
- CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS,
- CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildChildrenSetter() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(ContentChildComp) // 1
- void set contentChild(ContentChildComp contentChild) => null;
- @ContentChildren(ContentChildComp) // 2
- void set contentChildren(List<ContentChildComp> contentChildren) => null;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.first;
-
- final childFields = component.contentChildFields;
- expect(childFields, hasLength(1));
- final child = childFields.first;
- expect(child.fieldName, equals("contentChild"));
- expect(
- child.nameRange.offset, equals(code.indexOf("ContentChildComp) // 1")));
- expect(child.nameRange.length, equals("ContentChildComp".length));
- expect(child.typeRange.offset, equals(code.indexOf("ContentChildComp ")));
- expect(child.typeRange.length, equals("ContentChildComp".length));
-
- final childrenFields = component.contentChildrenFields;
- expect(childrenFields, hasLength(1));
- final children = childrenFields.first;
- expect(children.fieldName, equals("contentChildren"));
- expect(children.nameRange.offset,
- equals(code.indexOf("ContentChildComp) // 2")));
- expect(children.nameRange.length, equals("ContentChildComp".length));
- expect(children.typeRange.offset,
- equals(code.indexOf("List<ContentChildComp>")));
- expect(children.typeRange.length, equals("List<ContentChildComp>".length));
-
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildDirective() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChild(ContentChildComp)
- ContentChildComp contentChild;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.first;
- final childFields = component.contentChildFields;
- expect(childFields, hasLength(1));
- final child = childFields.first;
- expect(child.fieldName, equals("contentChild"));
- expect(child.nameRange.offset, equals(code.indexOf("ContentChildComp)")));
- expect(child.nameRange.length, equals("ContentChildComp".length));
- expect(child.typeRange.offset, equals(code.indexOf("ContentChildComp ")));
- expect(child.typeRange.length, equals("ContentChildComp".length));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- List<ContentChildComp> contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.first;
- final childrenFields = component.contentChildrenFields;
- expect(childrenFields, hasLength(1));
- final children = childrenFields.first;
- expect(children.fieldName, equals("contentChildren"));
- expect(
- children.nameRange.offset, equals(code.indexOf("ContentChildComp)")));
- expect(children.nameRange.length, equals("ContentChildComp".length));
- expect(children.typeRange.offset,
- equals(code.indexOf("List<ContentChildComp>")));
- expect(children.typeRange.length, equals("List<ContentChildComp>".length));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasContentChildrenDirective_QueryList() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class ComponentA {
- @ContentChildren(ContentChildComp)
- QueryList<ContentChildComp> contentChildren;
-}
-
-@Component(selector: 'foo', template: '')
-class ContentChildComp {}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.first;
- final childrenFields = component.contentChildrenFields;
- expect(childrenFields, hasLength(1));
- final children = childrenFields.first;
- expect(children.fieldName, equals("contentChildren"));
- expect(
- children.nameRange.offset, equals(code.indexOf("ContentChildComp)")));
- expect(children.nameRange.length, equals("ContentChildComp".length));
- expect(children.typeRange.offset,
- equals(code.indexOf("QueryList<ContentChildComp>")));
- expect(children.typeRange.length,
- equals("QueryList<ContentChildComp>".length));
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_ArgumentSelectorMissing() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(template:'')
-class ComponentA {
-}
-''');
- await getDirectives(source);
- // validate
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[AngularWarningCode.ARGUMENT_SELECTOR_MISSING]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_CannotParseSelector() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-@Component(selector: 'a+bad selector', template: '')
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.CANNOT_PARSE_SELECTOR, code, "+");
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_selector_notStringValue() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 55, template: '')
-class ComponentA {
-}
-''');
- await getDirectives(source);
- // validate
- errorListener.assertErrorsWithCodes(<ErrorCode>[
- AngularWarningCode.STRING_VALUE_EXPECTED,
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasExports() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-const foo = null;
-void bar() {}
-class MyClass {}
-
-@Component(selector: 'my-component', template: '',
- exports: const [foo, bar, MyClass])
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.first as Component;
- expect(component.view, isNotNull);
- expect(component.view.exports, hasLength(3));
- {
- final export = component.view.exports[0];
- expect(export.identifier, equals('foo'));
- expect(export.prefix, equals(''));
- expect(export.span.offset, equals(code.indexOf('foo,')));
- expect(export.span.length, equals('foo'.length));
- expect(export.element, isNull); // not yet linked
- }
- {
- final export = component.view.exports[1];
- expect(export.identifier, equals('bar'));
- expect(export.prefix, equals(''));
- expect(export.span.offset, equals(code.indexOf('bar,')));
- expect(export.span.length, equals('bar'.length));
- expect(export.element, isNull); // not yet linked
- }
- {
- final export = component.view.exports[2];
- expect(export.identifier, equals('MyClass'));
- expect(export.prefix, equals(''));
- expect(export.span.offset, equals(code.indexOf('MyClass]')));
- expect(export.span.length, equals('MyClass'.length));
- expect(export.element, isNull); // not yet linked
- }
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasNonIdentifierExport() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '', exports: const [1])
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.EXPORTS_MUST_BE_PLAIN_IDENTIFIERS, code, '1');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasRepeatedExports() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-const foo = null;
-
-@Component(selector: 'my-component', template: '', exports: const [foo, foo])
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // validate. Can't validate position because foo occurs so many times
- errorListener.assertErrorsWithCodes([AngularWarningCode.DUPLICATE_EXPORT]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_inputOnGetterIsError() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class MyComponent {
- @Input()
- String get someGetter => null;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- assertErrorInCodeAtPosition(
- AngularWarningCode.INPUT_ANNOTATION_PLACEMENT_INVALID,
- code,
- "@Input()");
- }
-
- // ignore: non_constant_identifier_names
- Future test_inputs() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'my-component',
- template: '<p></p>')
-class MyComponent {
- @Input()
- bool firstField;
- @Input('secondInput')
- String secondField;
- @Input()
- set someSetter(String x) { }
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.single;
- final inputs = component.inputs;
- expect(inputs, hasLength(3));
- {
- final input = inputs[0];
- expect(input.name, 'firstField');
- expect(input.nameOffset, code.indexOf('firstField'));
- expect(input.nameLength, 'firstField'.length);
- expect(input.setterRange.offset, input.nameOffset);
- expect(input.setterRange.length, input.name.length);
- expect(input.setter, isNotNull);
- expect(input.setter.isSetter, isTrue);
- expect(input.setter.displayName, 'firstField');
- expect(input.setterType.toString(), equals("bool"));
- }
- {
- final input = inputs[1];
- expect(input.name, 'secondInput');
- expect(input.nameOffset, code.indexOf('secondInput'));
- expect(input.setterRange.offset, code.indexOf('secondField'));
- expect(input.setterRange.length, 'secondField'.length);
- expect(input.setter, isNotNull);
- expect(input.setter.isSetter, isTrue);
- expect(input.setter.displayName, 'secondField');
- expect(input.setterType.toString(), equals("String"));
- }
- {
- final input = inputs[2];
- expect(input.name, 'someSetter');
- expect(input.nameOffset, code.indexOf('someSetter'));
- expect(input.setterRange.offset, input.nameOffset);
- expect(input.setterRange.length, input.name.length);
- expect(input.setter, isNotNull);
- expect(input.setter.isSetter, isTrue);
- expect(input.setter.displayName, 'someSetter');
- expect(input.setterType.toString(), equals("String"));
- }
-
- // assert no syntax errors, etc
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_noDirectives() async {
- final source = newSource('/test.dart', r'''
-class A {}
-class B {}
-''');
- await getDirectives(source);
- expect(directives, isEmpty);
- }
-
- // ignore: non_constant_identifier_names
- Future test_outputOnSetterIsError() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class MyComponent {
- @Output()
- set someSetter(x) { }
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- assertErrorInCodeAtPosition(
- AngularWarningCode.OUTPUT_ANNOTATION_PLACEMENT_INVALID,
- code,
- "@Output()");
- }
-
- // ignore: non_constant_identifier_names
- Future test_outputs() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'my-component',
- template: '<p></p>')
-class MyComponent {
- @Output()
- EventEmitter<int> outputOne;
- @Output('outputTwo')
- EventEmitter secondOutput;
- @Output()
- EventEmitter get someGetter => null;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.single;
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(3));
- {
- final output = compOutputs[0];
- expect(output.name, 'outputOne');
- expect(output.nameOffset, code.indexOf('outputOne'));
- expect(output.nameLength, 'outputOne'.length);
- expect(output.getterRange.offset, output.nameOffset);
- expect(output.getterRange.length, output.nameLength);
- expect(output.getter, isNotNull);
- expect(output.getter.isGetter, isTrue);
- expect(output.getter.displayName, 'outputOne');
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("int"));
- }
- {
- final output = compOutputs[1];
- expect(output.name, 'outputTwo');
- expect(output.nameOffset, code.indexOf('outputTwo'));
- expect(output.getterRange.offset, code.indexOf('secondOutput'));
- expect(output.getterRange.length, 'secondOutput'.length);
- expect(output.getter, isNotNull);
- expect(output.getter.isGetter, isTrue);
- expect(output.getter.displayName, 'secondOutput');
- expect(output.eventType, isNotNull);
- expect(output.eventType.isDynamic, isTrue);
- }
- {
- final output = compOutputs[2];
- expect(output.name, 'someGetter');
- expect(output.nameOffset, code.indexOf('someGetter'));
- expect(output.getterRange.offset, output.nameOffset);
- expect(output.getterRange.length, output.name.length);
- expect(output.getter, isNotNull);
- expect(output.getter.isGetter, isTrue);
- expect(output.getter.displayName, 'someGetter');
- expect(output.eventType, isNotNull);
- expect(output.eventType.isDynamic, isTrue);
- }
-
- // assert no syntax errors, etc
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_outputs_extendStreamIsOk() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'dart:async';
-
-abstract class MyStream<T> implements Stream<T> { }
-
-@Component(
- selector: 'my-component',
- template: '<p></p>')
-class MyComponent {
- @Output()
- MyStream<int> myOutput;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.single;
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(1));
- {
- final output = compOutputs[0];
- expect(output.eventType, isNotNull);
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_outputs_extendStreamNotStreamHasDynamicEventType() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'my-component',
- template: '<p></p>')
-class MyComponent {
- @Output()
- int badOutput;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // validate
- final component = directives.single;
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(1));
- {
- final output = compOutputs[0];
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("dynamic"));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_outputs_extendStreamSpecializedIsOk() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'dart:async';
-
-class MyStream extends Stream<int> { }
-
-@Component(
- selector: 'my-component',
- template: '<p></p>')
-class MyComponent {
- @Output()
- MyStream myOutput;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.single;
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(1));
- {
- final output = compOutputs[0];
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("int"));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_outputs_extendStreamUntypedIsOk() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'dart:async';
-
-class MyStream extends Stream { }
-
-@Component(
- selector: 'my-component',
- template: '<p></p>')
-class MyComponent {
- @Output()
- MyStream myOutput;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.single;
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(1));
- {
- final output = compOutputs[0];
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("dynamic"));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_outputs_notEventEmitterTypeError() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'my-component',
- template: '<p></p>')
-class MyComponent {
- @Output()
- int badOutput;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- assertErrorInCodeAtPosition(
- AngularWarningCode.OUTPUT_MUST_BE_STREAM, code, "badOutput");
- }
-
- // ignore: non_constant_identifier_names
- Future test_outputs_streamIsOk() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'dart:async';
-
-@Component(
- selector: 'my-component',
- template: '<p></p>')
-class MyComponent {
- @Output()
- Stream<int> myOutput;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.single;
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(1));
- {
- final output = compOutputs[0];
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("int"));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_parameterizedInputsOutputs() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'my-component',
- template: '<p></p>')
-class MyComponent<T, A extends String, B extends A> {
- @Output() EventEmitter<T> dynamicOutput;
- @Input() T dynamicInput;
- @Output() EventEmitter<A> stringOutput;
- @Input() A stringInput;
- @Output() EventEmitter<B> stringOutput2;
- @Input() B stringInput2;
- @Output() EventEmitter<List<B>> listOutput;
- @Input() List<B> listInput;
-}
-
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // validate
- final component = directives.single;
- final compInputs = component.inputs;
- expect(compInputs, hasLength(4));
- {
- final input = compInputs[0];
- expect(input.name, 'dynamicInput');
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("dynamic"));
- }
- {
- final input = compInputs[1];
- expect(input.name, 'stringInput');
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("String"));
- }
- {
- final input = compInputs[2];
- expect(input.name, 'stringInput2');
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("String"));
- }
- {
- final input = compInputs[3];
- expect(input.name, 'listInput');
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("List<String>"));
- }
-
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(4));
- {
- final output = compOutputs[0];
- expect(output.name, 'dynamicOutput');
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("dynamic"));
- }
- {
- final output = compOutputs[1];
- expect(output.name, 'stringOutput');
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("String"));
- }
- {
- final output = compOutputs[2];
- expect(output.name, 'stringOutput2');
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("String"));
- }
- {
- final output = compOutputs[3];
- expect(output.name, 'listOutput');
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("List<String>"));
- }
-
- // assert no syntax errors, etc
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_Pipe() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Pipe('pipeA')
-class PipeA extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-@Pipe('pipeB', pure: false)
-class PipeB extends PipeTransform {
- String transform(int a1, String a2, bool a3) => 'someString';
-}
-''');
- await getDirectives(source);
- expect(pipes, hasLength(2));
- {
- final pipe = pipes[0];
- expect(pipe, const isInstanceOf<Pipe>());
- final pipeName = pipe.pipeName;
- final pure = pipe.isPure;
- expect(pipeName, const isInstanceOf<String>());
- expect(pipeName, 'pipeA');
- expect(pure, true);
-
- expect(pipe.requiredArgumentType.toString(), 'int');
- expect(pipe.transformReturnType.toString(), 'int');
- expect(pipe.optionalArgumentTypes, hasLength(0));
- }
- {
- final pipe = pipes[1];
- expect(pipe, const isInstanceOf<Pipe>());
- final pipeName = pipe.pipeName;
- final pure = pipe.isPure;
- expect(pipeName, const isInstanceOf<String>());
- expect(pipeName, 'pipeB');
- expect(pure, false);
-
- expect(pipe.requiredArgumentType.toString(), 'int');
- expect(pipe.transformReturnType.toString(), 'String');
-
- final opArgs = pipe.optionalArgumentTypes;
- expect(opArgs, hasLength(2));
- expect(opArgs[0].toString(), 'String');
- expect(opArgs[1].toString(), 'bool');
- }
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_Pipe_allowedOptionalArgs() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Pipe('pipeA')
-class PipeA extends PipeTransform{
- transform([named]) {}
-}
-''');
- await getDirectives(source);
- expect(pipes, hasLength(1));
- final pipe = pipes[0];
- expect(pipe, const isInstanceOf<Pipe>());
-
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_Pipe_dynamic() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Pipe('pipeA')
-class PipeA extends PipeTransform{
- dynamic transform(dynamic x, [dynamic more]) {}
-}
-''');
- await getDirectives(source);
- expect(pipes, hasLength(1));
- final pipe = pipes[0];
- expect(pipe, const isInstanceOf<Pipe>());
-
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_Pipe_error_bad_extends() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-class Trouble {}
-
-@Pipe('pipeA')
-class PipeA extends Trouble{
- int transform(int blah) => blah;
-}
-''');
- await getDirectives(source);
- expect(pipes, hasLength(1));
- final pipe = pipes[0];
- expect(pipe, const isInstanceOf<Pipe>());
- final pipeName = pipe.pipeName;
- final pure = pipe.isPure;
- expect(pipeName, const isInstanceOf<String>());
- expect(pipeName, 'pipeA');
- expect(pure, true);
-
- expect(pipe.transformReturnType.toString(), 'int');
- expect(pipe.requiredArgumentType.toString(), 'int');
- expect(pipe.optionalArgumentTypes, hasLength(0));
-
- errorListener.assertErrorsWithCodes(
- [AngularWarningCode.PIPE_REQUIRES_PIPETRANSFORM]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_Pipe_error_named_args() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Pipe('pipeA')
-class PipeA extends PipeTransform{
- transform({named}) {}
-}
-''');
- await getDirectives(source);
- expect(pipes, hasLength(1));
- final pipe = pipes[0];
- expect(pipe, const isInstanceOf<Pipe>());
-
- errorListener.assertErrorsWithCodes(
- [AngularWarningCode.PIPE_TRANSFORM_NO_NAMED_ARGS]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_Pipe_error_no_pipeTransform() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Pipe('pipeA')
-class PipeA {
- int transform(int blah) => blah;
-}
-''');
- await getDirectives(source);
- expect(pipes, hasLength(1));
- final pipe = pipes[0];
- expect(pipe, const isInstanceOf<Pipe>());
- final pipeName = pipe.pipeName;
- final pure = pipe.isPure;
- expect(pipeName, const isInstanceOf<String>());
- expect(pipeName, 'pipeA');
- expect(pure, true);
-
- expect(pipe.transformReturnType.toString(), 'int');
- expect(pipe.requiredArgumentType.toString(), 'int');
- expect(pipe.optionalArgumentTypes, hasLength(0));
-
- errorListener.assertErrorsWithCodes(
- [AngularWarningCode.PIPE_REQUIRES_PIPETRANSFORM]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_Pipe_error_no_transform() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-class Trouble {}
-
-@Pipe('pipeA')
-class PipeA extends PipeTransform{}
-''');
- await getDirectives(source);
- expect(pipes, hasLength(1));
- final pipe = pipes[0];
- expect(pipe, const isInstanceOf<Pipe>());
- final pipeName = pipe.pipeName;
- final pure = pipe.isPure;
- expect(pipeName, const isInstanceOf<String>());
- expect(pipeName, 'pipeA');
- expect(pure, true);
-
- expect(pipe.requiredArgumentType, null);
- expect(pipe.transformReturnType, null);
- expect(pipe.optionalArgumentTypes, hasLength(0));
-
- errorListener.assertErrorsWithCodes(
- [AngularWarningCode.PIPE_REQUIRES_TRANSFORM_METHOD]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_Pipe_is_abstract() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-class Trouble {}
-
-@Pipe('pipeA')
-abstract class PipeA extends PipeTransform{
- int transform(int blah) => blah;
-}
-''');
- await getDirectives(source);
- expect(pipes, hasLength(1));
- final pipe = pipes[0];
- expect(pipe, const isInstanceOf<Pipe>());
- final pipeName = pipe.pipeName;
- final pure = pipe.isPure;
- expect(pipeName, const isInstanceOf<String>());
- expect(pipeName, 'pipeA');
- expect(pure, true);
-
- expect(pipe.transformReturnType.toString(), 'int');
- expect(pipe.requiredArgumentType.toString(), 'int');
- expect(pipe.optionalArgumentTypes, hasLength(0));
-
- errorListener
- .assertErrorsWithCodes([AngularWarningCode.PIPE_CANNOT_BE_ABSTRACT]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_pipeInheritance() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-class BasePipe extends PipeTransform {
- int transform(int blah) => blah;
-}
-
-@Pipe('pipe', pure: false)
-class MyPipe extends BasePipe {
-}
-''');
- await getDirectives(source);
- expect(pipes, hasLength(1));
- {
- final pipe = pipes[0];
- expect(pipe, const isInstanceOf<Pipe>());
- final pipeName = pipe.pipeName;
- final pure = pipe.isPure;
- expect(pipeName, const isInstanceOf<String>());
- expect(pipeName, 'pipe');
- expect(pure, false);
-
- expect(pipe.requiredArgumentType.toString(), 'int');
- expect(pipe.transformReturnType.toString(), 'int');
- expect(pipe.optionalArgumentTypes, hasLength(0));
- }
-
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_prefixedExport() async {
- newSource('/prefixed.dart', 'const foo = null;');
- final code = r'''
-import 'package:angular2/angular2.dart';
-import '/prefixed.dart' as prefixed;
-
-const foo = null;
-
-@Component(selector: 'my-component', template: '',
- exports: const [prefixed.foo, foo])
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.first as Component;
- expect(component.view, isNotNull);
- expect(component.view.exports, hasLength(2));
- {
- final export = component.view.exports[0];
- expect(export.identifier, equals('foo'));
- expect(export.prefix, equals('prefixed'));
- expect(export.span.offset, equals(code.indexOf('prefixed.foo')));
- expect(export.span.length, equals('prefixed.foo'.length));
- expect(export.element, isNull); // not yet linked
- }
- {
- final export = component.view.exports[1];
- expect(export.identifier, equals('foo'));
- expect(export.prefix, equals(''));
- expect(export.span.offset, equals(code.indexOf('foo]')));
- expect(export.span.length, equals('foo'.length));
- expect(export.element, isNull); // not yet linked
- }
-
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_selector_constantExpressionOk() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'a' + '[b]', template: '')
-class ComponentA {
-}
-''');
- await getDirectives(source);
- // validate
- errorListener.assertNoErrors();
- }
-}
-
-abstract class GatherAnnotationsTestMixin implements AbstractAngularTest {
- List<AbstractDirective> directives;
- List<Pipe> pipes;
- List<AnalysisError> errors;
-
- Future getDirectives(final Source source) async {
- final dartResult = await dartDriver.getResult(source.fullName);
- fillErrorListener(dartResult.errors);
- final result = await angularDriver.getAngularTopLevels(source.fullName);
- directives = result.directives;
- pipes = result.pipes;
- errors = result.errors;
- fillErrorListener(errors);
- }
-}
-
-@reflectiveTest
-class LinkDirectivesTest extends AbstractAngularTest {
- List<AbstractDirective> directives;
- List<Template> templates;
- List<AnalysisError> errors;
-
- Future getDirectives(final Source source) async {
- final dartResult = await dartDriver.getResult(source.fullName);
- fillErrorListener(dartResult.errors);
- final ngResult = await angularDriver.requestDartResult(source.fullName);
- directives = ngResult.directives;
- errors = ngResult.errors;
- fillErrorListener(errors);
- templates = directives
- .map((d) => d is Component ? d.view?.template : null)
- .where((d) => d != null)
- .toList();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_DirectiveTypeLiteralExpected() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'aaa', template: 'AAA', directives: const [int])
-class ComponentA {
-}
-''');
- await getDirectives(source);
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[AngularWarningCode.TYPE_IS_NOT_A_DIRECTIVE]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_inheritMetadata() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'foo', template: '')
-class BaseComponent {
- @Input()
- String input;
- @Output()
- EventEmitter<String> output;
-
- @ViewChild(BaseComponent)
- BaseComponent queryView;
- @ViewChildren(BaseComponent)
- List<BaseComponent> queryListView;
- @ContentChild(BaseComponent)
- BaseComponent queryContent;
- @ContentChildren(BaseComponent)
- List<BaseComponent> queryListContent;
-
- // TODO host properties & listeners
-}
-
-@Component( selector: 'my-component', template: '<p></p>')
-class MyComponent extends BaseComponent {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.firstWhere((d) => d.name == 'MyComponent');
- final compInputs = component.inputs;
- expect(compInputs, hasLength(1));
- {
- final input = compInputs[0];
- expect(input.name, 'input');
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("String"));
- }
-
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(1));
- {
- final output = compOutputs[0];
- expect(output.name, 'output');
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("String"));
- }
-
- final compChildrenFields = component.contentChildrenFields;
- expect(compChildrenFields, hasLength(1));
- {
- final children = compChildrenFields[0];
- expect(children.fieldName, 'queryListContent');
- }
-
- final compChildFields = component.contentChildFields;
- expect(compChildFields, hasLength(1));
- {
- final child = compChildFields[0];
- expect(child.fieldName, 'queryContent');
- }
-
- // TODO asert viewchild is inherited once that's supported
- }
-
- // ignore: non_constant_identifier_names
- Future test_inheritMetadata_notReimplemented_stillSurfacesAPI() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'dart:async';
-
-abstract class BaseComponent {
- @Input()
- set someInput(int x);
-
- @Output()
- Stream<int> get someOutput;
-}
-
-@Component(selector: 'my-component', template: '<p></p>')
-class ImproperlyDefinedComponent extends BaseComponent {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component =
- directives.firstWhere((d) => d.name == 'ImproperlyDefinedComponent');
- final compInputs = component.inputs;
- final compOutputs = component.outputs;
- expect(compInputs, hasLength(1));
- {
- final input = compInputs[0];
- expect(input.name, 'someInput');
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("int"));
- }
- expect(compOutputs, hasLength(1));
- {
- final input = compOutputs[0];
- expect(input.name, 'someOutput');
- expect(input.eventType, isNotNull);
- expect(input.eventType.toString(), equals("int"));
- }
- errorListener.assertErrorsWithCodes(
- [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_inheritMetadata_overriddenWithVariance() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'dart:async';
-
-abstract class BaseComponent {
- @Input()
- set someInput(int x);
-
- @Output()
- Stream<Object> get someOutput;
-}
-
-@Component(selector: 'my-component', template: '<p></p>')
-class VarianceComponent extends BaseComponent {
- set someInput(Object x) => null; // contravariance -- allowed on params
-
- Stream<int> someOutput; // covariance -- allowed on returns
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component =
- directives.firstWhere((d) => d.name == 'VarianceComponent');
- final compInputs = component.inputs;
- final compOutputs = component.outputs;
- expect(compInputs, hasLength(1));
- {
- final input = compInputs[0];
- expect(input.name, 'someInput');
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("Object"));
- }
- expect(compOutputs, hasLength(1));
- {
- final input = compOutputs[0];
- expect(input.name, 'someOutput');
- expect(input.eventType, isNotNull);
- expect(input.eventType.toString(), equals("int"));
- }
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_inheritMetadataChildDirective() async {
- final childCode = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'foo', template: '')
-class BaseComponent {
- @Input()
- String input;
- @Output()
- EventEmitter<String> output;
-
- @ViewChild(BaseComponent)
- BaseComponent queryView;
- @ViewChildren(BaseComponent)
- List<BaseComponent> queryListView;
- @ContentChild(BaseComponent)
- BaseComponent queryContent;
- @ContentChildren(BaseComponent)
- List<BaseComponent> queryListContent;
-
- // TODO host properties & listeners
-}
-
-@Component( selector: 'child-component', template: '<p></p>')
-class ChildComponent extends BaseComponent {
-}
-''';
- newSource('/child.dart', childCode);
-
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'child.dart';
-
-@Component(selector: 'my-component', template: '<p></p>',
- directives: const [ChildComponent])
-class MyComponent {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component =
- (directives.firstWhere((d) => d.name == 'MyComponent') as Component)
- .view
- .directives
- .first;
- final compInputs = component.inputs;
- expect(compInputs, hasLength(1));
- {
- final input = compInputs[0];
- expect(input.name, 'input');
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("String"));
- }
-
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(1));
- {
- final output = compOutputs[0];
- expect(output.name, 'output');
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("String"));
- }
-
- final compChildren = component.contentChildren;
- expect(compChildren, hasLength(1));
- {
- final children = compChildren[0];
- expect(children.field.fieldName, 'queryListContent');
- }
-
- final compChilds = component.contentChilds;
- expect(compChilds, hasLength(1));
- {
- final child = compChilds[0];
- expect(child.field.fieldName, 'queryContent');
- }
-
- // TODO asert viewchild is inherited once that's supported
- }
-
- // ignore: non_constant_identifier_names
- Future test_inheritMetadataInheritanceDeep() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-class BaseBaseComponent {
- @Input()
- int someInput;
-}
-
-class BaseComponent extends BaseBaseComponent {
-}
-
-@Component(selector: 'my-component', template: '<p></p>')
-class FinalComponent
- extends BaseComponent {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.firstWhere((d) => d.name == 'FinalComponent');
- final compInputs = component.inputs;
- expect(compInputs, hasLength(1));
- {
- final input = compInputs[0];
- expect(input.name, 'someInput');
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("int"));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_inheritMetadataMixinsInterfaces() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-class MixinComponent1 {
- @Input()
- int mixin1Input;
-}
-
-class MixinComponent2 {
- @Input()
- int mixin2Input;
-}
-
-class ComponentInterface1 {
- @Input()
- int interface1Input;
-}
-
-class ComponentInterface2 {
- @Input()
- int interface2Input;
-}
-
-@Component( selector: 'my-component', template: '<p></p>')
-class FinalComponent
- extends Object
- with MixinComponent1, MixinComponent2
- implements ComponentInterface1, ComponentInterface2 {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.firstWhere((d) => d.name == 'FinalComponent');
- final inputNames = component.inputs.map((input) => input.name);
- expect(
- inputNames,
- unorderedEquals([
- 'mixin1Input',
- 'mixin2Input',
- 'interface1Input',
- 'interface2Input'
- ]));
- }
-
- // ignore: non_constant_identifier_names
- Future test_parameterizedInheritedInputsOutputs() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-class Generic<T> {
- @Input()
- T inputViaParentDecl;
- @Output()
- EventEmitter<T> outputViaParentDecl;
-}
-
-@Component(selector: 'my-component', template: '<p></p>')
-class MyComponent extends Generic {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.single;
- final compInputs = component.inputs;
- expect(compInputs, hasLength(1));
- {
- final input =
- compInputs.singleWhere((i) => i.name == 'inputViaParentDecl');
- expect(input, isNotNull);
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("dynamic"));
- }
-
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(1));
- {
- final output =
- compOutputs.singleWhere((o) => o.name == 'outputViaParentDecl');
- expect(output, isNotNull);
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("dynamic"));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_parameterizedInheritedInputsOutputsSpecified() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-class Generic<T> {
- @Input()
- T inputViaParentDecl;
- @Output()
- EventEmitter<T> outputViaParentDecl;
-}
-
-@Component(selector: 'my-component', template: '<p></p>')
-class MyComponent extends Generic<String> {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.single;
- final compInputs = component.inputs;
- expect(compInputs, hasLength(1));
- {
- final input =
- compInputs.singleWhere((i) => i.name == 'inputViaParentDecl');
- expect(input, isNotNull);
- expect(input.setterType, isNotNull);
- expect(input.setterType.toString(), equals("String"));
- }
-
- final compOutputs = component.outputs;
- expect(compOutputs, hasLength(1));
- {
- final output =
- compOutputs.singleWhere((o) => o.name == 'outputViaParentDecl');
- expect(output, isNotNull);
- expect(output.eventType, isNotNull);
- expect(output.eventType.toString(), equals("String"));
- }
- }
-}
-
-@reflectiveTest
-class ResolveDartTemplatesTest extends AbstractAngularTest {
- List<AbstractDirective> directives;
- List<Template> templates;
- List<AnalysisError> errors;
-
- Future getDirectives(final Source source) async {
- final dartResult = await dartDriver.getResult(source.fullName);
- fillErrorListener(dartResult.errors);
- final ngResult = await angularDriver.requestDartResult(source.fullName);
- directives = ngResult.directives;
- errors = ngResult.errors;
- fillErrorListener(errors);
- templates = directives
- .map((d) => d is Component ? d.view?.template : null)
- .where((d) => d != null)
- .toList();
- }
-
- // ignore: non_constant_identifier_names
- Future test_attributeNotString() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class MyComponent {
- MyComponent(@Attribute("my-attr") int foo);
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.single;
- final attributes = component.attributes;
- expect(attributes, hasLength(1));
- {
- final attribute = attributes[0];
- expect(attribute.name, 'my-attr');
- // TODO better offsets here. But its really not that critical
- expect(attribute.nameOffset, code.indexOf("foo"));
- expect(attribute.nameLength, "foo".length);
- }
- assertErrorInCodeAtPosition(
- AngularWarningCode.ATTRIBUTE_PARAMETER_MUST_BE_STRING, code, 'foo');
- }
-
- // ignore: non_constant_identifier_names
- Future test_attributes() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '')
-class MyComponent {
- MyComponent(@Attribute("my-attr") String foo);
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.single;
- final attributes = component.attributes;
- expect(attributes, hasLength(1));
- {
- final attribute = attributes[0];
- expect(attribute.name, 'my-attr');
- // TODO better offsets here. But its really not that critical
- expect(attribute.nameOffset, code.indexOf("foo"));
- expect(attribute.nameLength, "foo".length);
- }
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_cannotExportComponentClassItself() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '',
- exports: const [ComponentA])
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.COMPONENTS_CANT_EXPORT_THEMSELVES,
- code,
- 'ComponentA');
- }
-
- Future test_componentReference() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-aaa', template: '<div>AAA</div>')
-class ComponentA {
-}
-
-@Component(selector: 'my-bbb', template: '<div>BBB</div>')
-class ComponentB {
-}
-
-@Component(selector: 'my-ccc', template: r"""
-<div>
- <my-aaa></my-aaa>1
- <my-bbb></my-bbb>2
-</div>
-""", directives: const [ComponentA, ComponentB])
-class ComponentC {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final componentA = getComponentByName(directives, 'ComponentA');
- final componentB = getComponentByName(directives, 'ComponentB');
- // validate
- expect(templates, hasLength(3));
- {
- final template = _getDartTemplateByClassName(templates, 'ComponentA');
- expect(template.ranges, isEmpty);
- }
- {
- final template = _getDartTemplateByClassName(templates, 'ComponentB');
- expect(template.ranges, isEmpty);
- }
- {
- final template = _getDartTemplateByClassName(templates, 'ComponentC');
- final ranges = template.ranges;
- expect(ranges, hasLength(4));
- {
- final resolvedRange =
- getResolvedRangeAtString(code, ranges, 'my-aaa></');
- assertComponentReference(resolvedRange, componentA);
- }
- {
- final resolvedRange =
- getResolvedRangeAtString(code, ranges, 'my-aaa>1');
- assertComponentReference(resolvedRange, componentA);
- }
- {
- final resolvedRange =
- getResolvedRangeAtString(code, ranges, 'my-bbb></');
- assertComponentReference(resolvedRange, componentB);
- }
- {
- final resolvedRange =
- getResolvedRangeAtString(code, ranges, 'my-bbb>2');
- assertComponentReference(resolvedRange, componentB);
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_constantExpressionTemplateVarDoesntCrash() async {
- final source = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-const String tplText = "we don't analyze this";
-
-@Component(selector: 'aaa', template: tplText)
-class ComponentA {
-}
-''');
- await getDirectives(source);
- expect(templates, hasLength(0));
- errorListener.assertErrorsWithCodes(
- <ErrorCode>[AngularHintCode.OFFSETS_CANNOT_BE_CREATED]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_expression_ArgumentTypeNotAssignable() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel',
- template: r"<div> {{text.length + text}} </div>")
-class TextPanel {
- String text;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- errorListener.assertErrorsWithCodes(
- [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_expression_UndefinedIdentifier() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel', template: r"<div>some text</div>")
-class TextPanel {
- @Input()
- String text;
-}
-
-@Component(selector: 'UserPanel', template: r"""
-<div>
- <text-panel [text]='noSuchName'></text-panel>
-</div>
-""", directives: const [TextPanel])
-class UserPanel {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- errorListener
- .assertErrorsWithCodes([StaticWarningCode.UNDEFINED_IDENTIFIER]);
- }
-
- // ignore: non_constant_identifier_names
- Future
- // ignore: non_constant_identifier_names
- test_hasError_expression_UndefinedIdentifier_OutsideFirstHtmlTag() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '<h1></h1>{{noSuchName}}')
-class MyComponent {
-}
-''';
-
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- assertErrorInCodeAtPosition(
- StaticWarningCode.UNDEFINED_IDENTIFIER, code, 'noSuchName');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasError_UnresolvedTag() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-aaa',
- template: "<unresolved-tag attr='value'></unresolved-tag>")
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- assertErrorInCodeAtPosition(
- AngularWarningCode.UNRESOLVED_TAG, code, 'unresolved-tag');
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasExports() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-const String foo = 'foo';
-int bar() { return 2; }
-class MyClass {}
-
-@Component(selector: 'my-component', template: '',
- exports: const [foo, bar, MyClass])
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.first as Component;
- expect(component.view, isNotNull);
- expect(component.view.exports, hasLength(3));
- {
- final export = component.view.exports[0];
- expect(export.identifier, equals('foo'));
- expect(export.prefix, equals(''));
- expect(export.span.offset, equals(code.indexOf('foo,')));
- expect(export.span.length, equals('foo'.length));
- expect(export.element.toString(), equals('get foo → String'));
- }
- {
- final export = component.view.exports[1];
- expect(export.identifier, equals('bar'));
- expect(export.prefix, equals(''));
- expect(export.span.offset, equals(code.indexOf('bar,')));
- expect(export.span.length, equals('bar'.length));
- expect(export.element.toString(), equals('bar() → int'));
- }
- {
- final export = component.view.exports[2];
- expect(export.identifier, equals('MyClass'));
- expect(export.prefix, equals(''));
- expect(export.span.offset, equals(code.indexOf('MyClass]')));
- expect(export.span.length, equals('MyClass'.length));
- expect(export.element.toString(), equals('class MyClass'));
- }
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasWrongTypeOfPrefixedIdentifierExport() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '',
- exports: const [ComponentA.foo])
-class ComponentA {
- static void foo(){}
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // validate
- assertErrorInCodeAtPosition(
- AngularWarningCode.EXPORTS_MUST_BE_PLAIN_IDENTIFIERS,
- code,
- 'ComponentA.foo');
- }
-
- // ignore: non_constant_identifier_names
- Future test_htmlParsing_hasError() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel',
- template: r"<div> <h2> Expected closing H2 </h3> </div>")
-class TextPanel {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // has errors
- errorListener.assertErrorsWithCodes([
- NgParserWarningCode.DANGLING_CLOSE_ELEMENT,
- NgParserWarningCode.CANNOT_FIND_MATCHING_CLOSE,
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_input_OK_event() async {
- final code = r'''
-import 'dart:html';
- import 'package:angular2/angular2.dart';
-
-@Component(selector: 'UserPanel', template: r"""
-<div>
- <input (click)='gotClicked($event)'>
-</div>
-""")
-class TodoList {
- gotClicked(MouseEvent event) {}
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- expect(templates, hasLength(1));
- {
- final template = _getDartTemplateByClassName(templates, 'TodoList');
- final ranges = template.ranges;
- expect(ranges, hasLength(4));
- {
- final resolvedRange =
- getResolvedRangeAtString(code, ranges, r'gotClicked($');
- expect(resolvedRange.range.length, 'gotClicked'.length);
- final element = (resolvedRange.element as DartElement).element;
- expect(element, const isInstanceOf<MethodElement>());
- expect(element.name, 'gotClicked');
- expect(
- element.nameOffset, code.indexOf('gotClicked(MouseEvent event)'));
- }
- {
- final resolvedRange =
- getResolvedRangeAtString(code, ranges, r"$event)'>");
- expect(resolvedRange.range.length, r'$event'.length);
- final element = (resolvedRange.element as LocalVariable).dartVariable;
- expect(element, const isInstanceOf<LocalVariableElement>());
- expect(element.name, r'$event');
- expect(element.nameOffset, -1);
- }
- {
- final resolvedRange = getResolvedRangeAtString(code, ranges, 'click');
- expect(resolvedRange.range.length, 'click'.length);
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_input_OK_reference_expression() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel', template: r"<div>some text</div>")
-class TextPanel {
- @Input()
- String text;
-}
-
-@Component(selector: 'UserPanel', template: r"""
-<div>
- <text-panel [text]='user.name'></text-panel>
-</div>
-""", directives: const [TextPanel])
-class UserPanel {
- User user; // 1
-}
-
-class User {
- String name; // 2
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final textPanel = getComponentByName(directives, 'TextPanel');
- // validate
- expect(templates, hasLength(2));
- {
- final template = _getDartTemplateByClassName(templates, 'UserPanel');
- final ranges = template.ranges;
- expect(ranges, hasLength(5));
- {
- final resolvedRange = getResolvedRangeAtString(code, ranges, 'text]=');
- expect(resolvedRange.range.length, 'text'.length);
- assertPropertyReference(resolvedRange, textPanel, 'text');
- }
- {
- final resolvedRange = getResolvedRangeAtString(code, ranges, 'user.');
- expect(resolvedRange.range.length, 'user'.length);
- final element = (resolvedRange.element as DartElement).element;
- expect(element, const isInstanceOf<PropertyAccessorElement>());
- expect(element.name, 'user');
- expect(element.nameOffset, code.indexOf('user; // 1'));
- }
- {
- final resolvedRange = getResolvedRangeAtString(code, ranges, "name'>");
- expect(resolvedRange.range.length, 'name'.length);
- final element = (resolvedRange.element as DartElement).element;
- expect(element, const isInstanceOf<PropertyAccessorElement>());
- expect(element.name, 'name');
- expect(element.nameOffset, code.indexOf('name; // 2'));
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_input_OK_reference_text() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'comp-a',
- template: r"<div>AAA</div>")
-class ComponentA {
- @Input()
- int firstValue;
- @Input()
- int second;
-}
-
-@Component(selector: 'comp-b', template: r"""
-<div>
- <comp-a [firstValue]='1' [second]='2'></comp-a>
-</div>
-""", directives: const [ComponentA])
-class ComponentB {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final componentA = getComponentByName(directives, 'ComponentA');
- // validate
- expect(templates, hasLength(2));
- {
- final template = _getDartTemplateByClassName(templates, 'ComponentB');
- final ranges = template.ranges;
- expect(ranges, hasLength(4));
- {
- final resolvedRange =
- getResolvedRangeAtString(code, ranges, 'firstValue]=');
- expect(resolvedRange.range.length, 'firstValue'.length);
- assertPropertyReference(resolvedRange, componentA, 'firstValue');
- }
- {
- final resolvedRange =
- getResolvedRangeAtString(code, ranges, 'second]=');
- expect(resolvedRange.range.length, 'second'.length);
- assertPropertyReference(resolvedRange, componentA, 'second');
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_misspelledPrefixSuppressesWrongPrefixTypeError() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-component', template: '',
- exports: const [garbage.garbage])
-class ComponentA {
- static void foo(){}
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // validate
- errorListener.assertErrorsWithCodes(<ErrorCode>[
- StaticWarningCode.UNDEFINED_IDENTIFIER,
- CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT,
- CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_noRootElement() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel',
- template: r'Often used without an element in tests.')
-class TextPanel {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- expect(templates, hasLength(1));
- // has errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_noTemplateContents() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel',
- template: '')
-class TextPanel {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- expect(templates, hasLength(1));
- // has errors
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_prefixedExport() async {
- newSource('/prefixed.dart', 'const double foo = 2.0;');
- final code = r'''
-import 'package:angular2/angular2.dart';
-import '/prefixed.dart' as prefixed;
-
-const int foo = 2;
-
-@Component(selector: 'my-component', template: '',
- exports: const [prefixed.foo, foo])
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- final component = directives.first as Component;
- expect(component.view, isNotNull);
- expect(component.view.exports, hasLength(2));
- {
- final export = component.view.exports[0];
- expect(export.identifier, equals('foo'));
- expect(export.prefix, equals('prefixed'));
- expect(export.span.offset, equals(code.indexOf('prefixed.foo')));
- expect(export.span.length, equals('prefixed.foo'.length));
- expect(export.element.toString(), equals('get foo → double'));
- }
- {
- final export = component.view.exports[1];
- expect(export.identifier, equals('foo'));
- expect(export.prefix, equals(''));
- expect(export.span.offset, equals(code.indexOf('foo]')));
- expect(export.span.length, equals('foo'.length));
- expect(export.element.toString(), equals('get foo → int'));
- }
-
- // validate
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveGetChildDirectivesNgContentSelectors() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'child_file.dart';
-
-@Component(selector: 'my-component', template: 'My template',
- directives: const [ChildComponent])
-class MyComponent {}
-''';
- final childCode = r'''
-import 'package:angular2/angular2.dart';
-@Component(selector: 'child-component',
- template: 'My template <ng-content></ng-content>',
- directives: const [])
-class ChildComponent {}
-''';
- final source = newSource('/test.dart', code);
- newSource('/child_file.dart', childCode);
- await getDirectives(source);
- expect(templates, hasLength(1));
- // no errors
- errorListener.assertNoErrors();
-
- final childDirectives = templates.first.view.directives;
- expect(childDirectives, hasLength(1));
-
- final childViews = childDirectives
- .map((d) => d is Component ? d.view : null)
- .where((v) => v != null)
- .toList();
- expect(childViews, hasLength(1));
- final childView = childViews.first;
- expect(childView.component, isNotNull);
- expect(childView.component.ngContents, hasLength(1));
- }
-
- // ignore: non_constant_identifier_names
- Future test_suppressError_NotCaseSensitive() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-aaa',
- template: """
-<!-- @ngIgnoreErrors: UnReSoLvEd_tAg -->
-<unresolved-tag attr='value'></unresolved-tag>""")
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_suppressError_UnresolvedTag() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-aaa',
- template: """
-<!-- @ngIgnoreErrors: UNRESOLVED_TAG -->
-<unresolved-tag attr='value'></unresolved-tag>""")
-class ComponentA {
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_suppressError_UnresolvedTagAndInput() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-aaa',
- template: """
-<!-- @ngIgnoreErrors: UNRESOLVED_TAG, NONEXIST_INPUT_BOUND -->
-<unresolved-tag [attr]='value'></unresolved-tag>""")
-class ComponentA {
- Object value;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_textExpression_hasError_DoubleOpenedMustache() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel', template: r"<div> {{text {{ error}} </div>")
-class TextPanel {
- String text;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- errorListener.assertErrorsWithCodes([
- AngularWarningCode.UNTERMINATED_MUSTACHE,
- StaticWarningCode.UNDEFINED_IDENTIFIER
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_textExpression_hasError_MultipleUnclosedMustaches() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel', template: r"<div> {{open {{error {{text}} close}} close}} </div>")
-class TextPanel {
- String text, open, close;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- errorListener.assertErrorsWithCodes([
- AngularWarningCode.UNTERMINATED_MUSTACHE,
- AngularWarningCode.UNTERMINATED_MUSTACHE,
- StaticWarningCode.UNDEFINED_IDENTIFIER,
- AngularWarningCode.UNOPENED_MUSTACHE,
- AngularWarningCode.UNOPENED_MUSTACHE,
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_textExpression_hasError_UnopenedMustache() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel', template: r"<div> text}} </div>")
-class TextPanel {
- String text;
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // has errors
- errorListener.assertErrorsWithCodes([AngularWarningCode.UNOPENED_MUSTACHE]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_textExpression_hasError_UnterminatedMustache() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel', template: r"{{text")
-class TextPanel {
- String text = "text";
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- // has errors
- errorListener
- .assertErrorsWithCodes([AngularWarningCode.UNTERMINATED_MUSTACHE]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_textExpression_OK() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel',
- template: r"<div> <h2> {{text}} </h2> and {{text.length}} </div>")
-class TextPanel {
- String text; // 1
-}
-''';
- final source = newSource('/test.dart', code);
- await getDirectives(source);
- expect(templates, hasLength(1));
- {
- final template = _getDartTemplateByClassName(templates, 'TextPanel');
- final ranges = template.ranges;
- expect(ranges, hasLength(5));
- {
- final resolvedRange = getResolvedRangeAtString(code, ranges, 'text}}');
- expect(resolvedRange.range.length, 'text'.length);
- final element = assertGetter(resolvedRange);
- expect(element.name, 'text');
- expect(element.nameOffset, code.indexOf('text; // 1'));
- }
- {
- final resolvedRange =
- getResolvedRangeAtString(code, ranges, 'text.length');
- expect(resolvedRange.range.length, 'text'.length);
- final element = assertGetter(resolvedRange);
- expect(element.name, 'text');
- expect(element.nameOffset, code.indexOf('text; // 1'));
- }
- {
- final resolvedRange =
- getResolvedRangeAtString(code, ranges, 'length}}');
- expect(resolvedRange.range.length, 'length'.length);
- final element = assertGetter(resolvedRange);
- expect(element.name, 'length');
- expect(element.enclosingElement.name, 'String');
- }
- }
- // no errors
- errorListener.assertNoErrors();
- }
-
- static Template _getDartTemplateByClassName(
- List<Template> templates, String className) =>
- templates.firstWhere(
- (template) => template.view.classElement.name == className,
- orElse: () {
- fail('Template with the class "$className" was not found.');
- });
-}
-
-@reflectiveTest
-class ResolveHtmlTemplatesTest extends AbstractAngularTest {
- List<Template> templates;
- Future getDirectives(Source htmlSource, List<Source> dartSources) async {
- for (final dartSource in dartSources) {
- final result = await angularDriver.requestDartResult(dartSource.fullName);
- fillErrorListener(result.errors);
- }
- final result2 = await angularDriver.requestHtmlResult(htmlSource.fullName);
- fillErrorListener(result2.errors);
- templates = result2.directives
- .map((d) => d is Component ? d.view?.template : null)
- .where((d) => d != null)
- .toList();
- }
-
- // ignore: non_constant_identifier_names
- Future test_multipleViewsWithTemplate() async {
- final dartCodeOne = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panelA', templateUrl: 'text_panel.html')
-class TextPanelA {
- String text; // A
-}
-''';
-
- final dartCodeTwo = r'''
-import '/angular2/angular2.dart';
-
-@Component(selector: 'text-panelB', templateUrl: 'text_panel.html')
-class TextPanelB {
- String text; // B
-}
-''';
- final htmlCode = r"""
-<div>
- {{text}}
-</div>
-""";
- final dartSourceOne = newSource('/test1.dart', dartCodeOne);
- final dartSourceTwo = newSource('/test2.dart', dartCodeTwo);
- final htmlSource = newSource('/text_panel.html', htmlCode);
- await getDirectives(htmlSource, [dartSourceOne, dartSourceTwo]);
- expect(templates, hasLength(2));
- // validate templates
- var hasTextPanelA = false;
- var hasTextPanelB = false;
- for (final template in templates) {
- final viewClassName = template.view.classElement.name;
- int textLocation;
- if (viewClassName == 'TextPanelA') {
- hasTextPanelA = true;
- textLocation = dartCodeOne.indexOf('text; // A');
- }
- if (viewClassName == 'TextPanelB') {
- hasTextPanelB = true;
- textLocation = dartCodeTwo.indexOf('text; // B');
- }
- expect(template.ranges, hasLength(1));
- {
- final resolvedRange =
- getResolvedRangeAtString(htmlCode, template.ranges, 'text}}');
- final element = assertGetter(resolvedRange);
- expect(element.name, 'text');
- expect(element.nameOffset, textLocation);
- }
- }
- expect(hasTextPanelA, isTrue);
- expect(hasTextPanelB, isTrue);
- }
-}
-
-@reflectiveTest
-class ResolveHtmlTemplateTest extends AbstractAngularTest {
- List<View> views;
- Future getDirectives(Source htmlSource, Source dartSource) async {
- final result = await angularDriver.requestDartResult(dartSource.fullName);
- fillErrorListener(result.errors);
- final result2 = await angularDriver.requestHtmlResult(htmlSource.fullName);
- fillErrorListener(result2.errors);
- views = result2.directives
- .map((d) => d is Component ? d.view : null)
- .where((v) => v != null)
- .toList();
- }
-
- // ignore: non_constant_identifier_names
- Future test_contentChildAnnotatedConstructor() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'a', templateUrl: 'test.html')
-class A {
- @ContentChild(X)
- A(){}
-}
-''';
- final dartSource = newSource('/test.dart', code);
- final htmlSource = newSource('/test.html', '');
- await getDirectives(htmlSource, dartSource);
-
- final component = views.first.component;
-
- expect(component.contentChilds, hasLength(0));
- }
-
- // ignore: non_constant_identifier_names
- Future test_errorFromWeirdInclude_includesFromPath() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-aaa', templateUrl: "test.html")
-class WeirdComponent {
-}
-''';
- final dartSource = newSource('/weird.dart', code);
- final htmlSource =
- newSource('/test.html', "<unresolved-tag></unresolved-tag>");
- await getDirectives(htmlSource, dartSource);
- final errors = errorListener.errors;
- expect(errors, hasLength(1));
- expect(errors.first, const isInstanceOf<FromFilePrefixedError>());
- expect(
- errors.first.message,
- equals('In WeirdComponent:'
- ' Unresolved tag "unresolved-tag" (from /weird.dart)'));
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasView_withTemplate_relativeToLibForParts() async {
- final libCode = r'''
-import 'package:angular2/angular2.dart';
-part 'parts/part.dart';
- ''';
- final partCode = r'''
-part of '../lib.dart';
-@Component(selector: 'my-component', templateUrl: 'parts/my-template.html')
-class MyComponent {
- String text; // 1
-}
-''';
- final htmlCode = r'''
-<div>
- {{text}}
-</div>
-''';
- final dartLibSource = newSource('/lib.dart', libCode);
- final dartPartSource = newSource('/parts/part.dart', partCode);
- final htmlSource = newSource('/parts/my-template.html', htmlCode);
- await getDirectives(htmlSource, dartPartSource);
- errorListener.assertNoErrors();
- expect(views, hasLength(1));
- {
- final view = getViewByClassName(views, 'MyComponent');
- expect(view.templateUriSource, isNotNull);
- // resolve this View
- final template = view.template;
- expect(template, isNotNull);
- expect(template.view, view);
- expect(template.ranges, hasLength(1));
- {
- final resolvedRange =
- getResolvedRangeAtString(htmlCode, template.ranges, 'text}}');
- final element = assertGetter(resolvedRange);
- expect(element.name, 'text');
- expect(element.nameOffset, partCode.indexOf('text; // 1'));
- }
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_hasViewWithTemplate() async {
- final dartCode = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'text-panel', templateUrl: 'text_panel.html')
-class TextPanel {
- String text; // 1
-}
-''';
- final htmlCode = r"""
-<div>
- {{text}}
-</div>
-""";
- final dartSource = newSource('/test.dart', dartCode);
- final htmlSource = newSource('/text_panel.html', htmlCode);
- // compute
- await getDirectives(htmlSource, dartSource);
- expect(views, hasLength(1));
- {
- final view = getViewByClassName(views, 'TextPanel');
- expect(view.templateUriSource, isNotNull);
- // resolve this View
- final template = view.template;
- expect(template, isNotNull);
- expect(template.view, view);
- expect(template.ranges, hasLength(1));
- {
- final resolvedRange =
- getResolvedRangeAtString(htmlCode, template.ranges, 'text}}');
- final element = assertGetter(resolvedRange);
- expect(element.name, 'text');
- expect(element.nameOffset, dartCode.indexOf('text; // 1'));
- }
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveGetChildDirectivesNgContentSelectors() async {
- final code = r'''
-import 'package:angular2/angular2.dart';
-import 'child_file.dart';
-
-import 'package:angular2/angular2.dart';
-@Component(selector: 'my-component', templateUrl: 'test.html',
- directives: const [ChildComponent])
-class MyComponent {}
-''';
- final childCode = r'''
-import 'package:angular2/angular2.dart';
-@Component(selector: 'child-component',
- template: 'My template <ng-content></ng-content>',
- directives: const [])
-class ChildComponent {}
-''';
- final dartSource = newSource('/test.dart', code);
- newSource('/child_file.dart', childCode);
- final htmlSource = newSource('/test.html', '');
- await getDirectives(htmlSource, dartSource);
-
- final childDirectives = views.first.directives;
- expect(childDirectives, hasLength(1));
-
- final childView = (views.first.directives.first as Component).view;
- expect(childView.component, isNotNull);
- expect(childView.component.ngContents, hasLength(1));
- }
-
- // ignore: non_constant_identifier_names
- Future test_suppressError_UnresolvedTagHtmlTemplate() async {
- final dartSource = newSource('/test.dart', r'''
-import 'package:angular2/angular2.dart';
-
-@Component(selector: 'my-aaa', templateUrl: 'test.html')
-class ComponentA {
-}
-''');
- final htmlSource = newSource('/test.html', '''
-<!-- @ngIgnoreErrors: UNRESOLVED_TAG -->
-<unresolved-tag attr='value'></unresolved-tag>""")
-''');
- await getDirectives(htmlSource, dartSource);
- errorListener.assertNoErrors();
- }
-}
diff --git a/angular_analyzer_plugin/test/ast_test.dart b/angular_analyzer_plugin/test/ast_test.dart
deleted file mode 100644
index d683a39..0000000
--- a/angular_analyzer_plugin/test/ast_test.dart
+++ /dev/null
@@ -1,60 +0,0 @@
-import 'package:angular_analyzer_plugin/ast.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(StatementsBoundAttrTest);
- });
-}
-
-@reflectiveTest
-class StatementsBoundAttrTest {
- // ignore: non_constant_identifier_names
- void test_reductionOffsetMultipleReductions() {
- final attr = new StatementsBoundAttribute(
- 'name',
- '('.length, // nameOffset
- 'value',
- '(name.reductions.here)="'.length, //valueOffset
- '(name)',
- 0, // originalNameOffset
- ['reductions', 'here'], // reductions
- [] // statements
- );
- expect(attr.reductionsOffset, '(name'.length);
- expect(attr.reductionsLength, '.reductions.here'.length);
- }
-
- // ignore: non_constant_identifier_names
- void test_reductionOffsetNoReductions() {
- final attr = new StatementsBoundAttribute(
- 'name',
- '('.length, // nameOffset
- 'value',
- '(name)="'.length, //valueOffset
- '(name)',
- 0, // originalNameOffset
- [], // reductions
- [] // statements
- );
- expect(attr.reductionsOffset, null);
- expect(attr.reductionsLength, null);
- }
-
- // ignore: non_constant_identifier_names
- void test_reductionOffsetOneReduction() {
- final attr = new StatementsBoundAttribute(
- 'name',
- '('.length, // nameOffset
- 'value',
- '(name.reduction)="'.length, //valueOffset
- '(name)',
- 0, // originalNameOffset
- ['reduction'], // reductions
- [] // statements
- );
- expect(attr.reductionsOffset, '(name'.length);
- expect(attr.reductionsLength, '.reduction'.length);
- }
-}
diff --git a/angular_analyzer_plugin/test/completion_contributor_test.dart b/angular_analyzer_plugin/test/completion_contributor_test.dart
deleted file mode 100644
index d3f1bf3..0000000
--- a/angular_analyzer_plugin/test/completion_contributor_test.dart
+++ /dev/null
@@ -1,3355 +0,0 @@
-import 'dart:async';
-
-import 'package:analyzer_plugin/utilities/completion/relevance.dart';
-import 'package:angular_analyzer_plugin/src/completion.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'completion_contributor_test_util.dart';
-
-void main() {
- defineReflectiveTests(DartCompletionContributorTest);
- defineReflectiveTests(HtmlCompletionContributorTest);
-}
-
-@reflectiveTest
-class DartCompletionContributorTest extends AbstractCompletionContributorTest {
- @override
- void setUp() {
- testFile = '/completionTest.dart';
- super.setUp();
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInlineHtmlSelectorTag_at_beginning() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<^<div></div>', selector: 'my-parent', directives: const[MyChildComponent1, MyChildComponent2])
-class MyParentComponent{}
-@Component(template: '', selector: 'my-child1, my-child2')
-class MyChildComponent1{}
-@Component(template: '', selector: 'my-child3.someClass[someAttr]')
-class MyChildComponent2{}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInlineHtmlSelectorTag_at_beginning_with_partial() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<my^<div></div>', selector: 'my-parent', directives: const[MyChildComponent1, MyChildComponent2])
-class MyParentComponent{}
-@Component(template: '', selector: 'my-child1, my-child2')
-class MyChildComponent1{}
-@Component(template: '', selector: 'my-child3.someClass[someAttr]')
-class MyChildComponent2{}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '<my'.length);
- expect(replacementLength, '<my'.length);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInlineHtmlSelectorTag_at_end() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<div><div></div></div><^', selector: 'my-parent', directives: const[MyChildComponent1,MyChildComponent2])
-class MyParentComponent{}
-@Component(template: '', selector: 'my-child1, my-child2')
-class MyChildComponent1{}
-@Component(template: '', selector: 'my-child3.someClass[someAttr]')
-class MyChildComponent2{}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInlineHtmlSelectorTag_at_end_after_close() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<div><div></div></div>^', selector: 'my-parent', directives: const[MyChildComponent1,MyChildComponent2])
-class MyParentComponent{}
-@Component(template: '', selector: 'my-child1, my-child2')
-class MyChildComponent1{}
-@Component(template: '', selector: 'my-child3.someClass[someAttr]')
-class MyChildComponent2{}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInlineHtmlSelectorTag_at_end_with_partial() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<div><div></div></div><m^', selector: 'my-parent', directives: const[MyChildComponent1,MyChildComponent2])
-class MyParentComponent{}
-@Component(template: '', selector: 'my-child1, my-child2')
-class MyChildComponent1{}
-@Component(template: '', selector: 'my-child3.someClass[someAttr]')
-class MyChildComponent2{}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '<m'.length);
- expect(replacementLength, '<m'.length);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInlineHtmlSelectorTag_at_middle() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<div><div><^</div></div>', selector: 'my-parent', directives: const[MyChildComponent1,MyChildComponent2])
-class MyParentComponent{}
-@Component(template: '', selector: 'my-child1, my-child2')
-class MyChildComponent1{}
-@Component(template: '', selector: 'my-child3.someClass[someAttr]')
-class MyChildComponent2{}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInlineHtmlSelectorTag_at_middle_of_text() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<div><div> some text<^</div></div>', selector: 'my-parent', directives: const[MyChildComponent1,MyChildComponent2])
-class MyParentComponent{}
-@Component(template: '', selector: 'my-child1, my-child2')
-class MyChildComponent1{}
-@Component(template: '', selector: 'my-child3.someClass[someAttr]')
-class MyChildComponent2{}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInlineHtmlSelectorTag_at_middle_with_partial() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<div><div><my^</div></div>', selector: 'my-parent', directives: const[MyChildComponent1, MyChildComponent2])
-class MyParentComponent{}
-@Component(template: '', selector: 'my-child1, my-child2')
-class MyChildComponent1{}
-@Component(template: '', selector: 'my-child3.someClass[someAttr]')
-class MyChildComponent2{}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '<my'.length);
- expect(replacementLength, '<my'.length);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInlineHtmlSelectorTag_in_middle_of_unclosed_tag() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<div>some text<^', selector: 'my-parent', directives: const[MyChildComponent1,MyChildComponent2])
-class MyParentComponent{}
-@Component(template: '', selector: 'my-child1, my-child2')
-class MyChildComponent1{}
-@Component(template: '', selector: 'my-child3.someClass[someAttr]')
-class MyChildComponent2{}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInlineHtmlSelectorTag_on_empty_document() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '^', selector: 'my-parent', directives: const[MyChildComponent1,MyChildComponent2])
-class MyParentComponent{}
-@Component(template: '', selector: 'my-child1, my-child2')
-class MyChildComponent1{}
-@Component(template: '', selector: 'my-child3.someClass[someAttr]')
-class MyChildComponent2{}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInput_as_plainAttribute() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<child-tag ^<div></div>', selector: 'my-tag',
-directives: const [MyChildComponent])
-class MyComponent {}
-@Component(template: '', selector: 'child-tag')
-class MyChildComponent {
- @Input() String stringInput;
- @Input() int intInput;
- @Output() EventEmitter<String> myEvent;
-
- bool _myDynamicInput = false;
- bool get myDynamicInput => _myDynamicInput;
- @Input()
- void set myDynamicInput(value) {}
-}
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('stringInput');
- assertNotSuggested('intInput');
- assertSuggestSetter('myDynamicInput',
- relevance: DART_RELEVANCE_DEFAULT - 1);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputNotStarted_at_incompleteTag_with_newTag() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<child-tag ^<div></div>', selector: 'my-tag',
-directives: const [MyChildComponent])
-class MyComponent {}
-@Component(template: '', selector: 'child-tag')
-class MyChildComponent {
- @Input() String stringInput;
- @Output() EventEmitter<String> myEvent;
-}
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('[stringInput]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputStarted_at_incompleteTag_with_EOF() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<child-tag [^', selector: 'my-tag',
-directives: const [MyChildComponent])
-class MyComponent {}
-@Component(template: '', selector: 'child-tag')
-class MyChildComponent {
- @Input() String stringInput;
- @Output() EventEmitter<String> myEvent;
-}
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestSetter("[stringInput]");
- assertNotSuggested("(myEvent)");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputStarted_at_incompleteTag_with_newTag() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<child-tag [^<div></div>', selector: 'my-tag',
-directives: const [MyChildComponent])
-class MyComponent {}
-@Component(template: '', selector: 'child-tag')
-class MyChildComponent {
- @Input() String stringInput;
- @Output() EventEmitter<String> myEvent;
-}
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestSetter("[stringInput]");
- assertNotSuggested("(myEvent)");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInAttrBinding() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<h1 [attr.on-click]="^"></h1>', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInClassBinding() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<h1 [class.my-class]="^"></h1>', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInInputBinding() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<h1 [hidden]="^"></h1>', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInInputOutput_at_incompleteTag_with_EOF() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<child-tag ^', selector: 'my-tag',
-directives: const [MyChildComponent])
-class MyComponent {}
-@Component(template: '', selector: 'child-tag')
-class MyChildComponent {
- @Input() String stringInput;
- @Output() EventEmitter<String> myEvent;
-}
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter("[stringInput]");
- assertSuggestGetter("(myEvent)", "String");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInInputOutput_at_incompleteTag_with_newTag() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<child-tag ^<div></div>', selector: 'my-tag',
-directives: const [MyChildComponent])
-class MyComponent {}
-@Component(template: '', selector: 'child-tag')
-class MyChildComponent {
- @Input() String stringInput;
- @Output() EventEmitter<String> myEvent;
-}
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter("[stringInput]");
- assertSuggestGetter("(myEvent)", "String");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInMustache() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '{{^}}', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInStyleBinding() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<h1 [style.background-color]="^"></h1>', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberMustacheAttrBinding() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<h1 title="{{^}}"></h1>', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMultipleMembers() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '{{d^}}', selector: 'a')
-class MyComp {
- String text;
- String description;
-}
- ''');
-
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestGetter('text', 'String');
- assertSuggestGetter('description', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeOutputStarted_at_incompleteTag_with_EOF() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<child-tag (^', selector: 'my-tag',
-directives: const [MyChildComponent])
-class MyComponent {}
-@Component(template: '', selector: 'child-tag')
-class MyChildComponent {
- @Input() String stringInput;
- @Output() EventEmitter<String> myEvent;
-}
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertNotSuggested("[stringInput]");
- assertSuggestGetter("(myEvent)", "String");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeOutputStarted_at_incompleteTag_with_newTag() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<child-tag (^<div></div>', selector: 'my-tag',
-directives: const [MyChildComponent])
-class MyComponent {}
-@Component(template: '', selector: 'child-tag')
-class MyChildComponent {
- @Input() String stringInput;
- @Output() EventEmitter<String> myEvent;
-}
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertNotSuggested("[stringInput]");
- assertSuggestGetter("(myEvent)", "String");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeOutsideTemplateOK() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-class MyComp {
- String text = ^;
-}
- ''');
-
- await computeSuggestions();
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeStandardInput_as_plainAttribute() async {
- addTestSource('''
-import 'package:angular2/angular2.dart';
-@Component(template: '<child-tag ^<div></div>', selector: 'my-tag',
-directives: const [MyChildComponent])
-class MyComponent {}
-@Component(template: '', selector: 'child-tag')
-class MyChildComponent {
-}
- }
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('[id]', relevance: DART_RELEVANCE_DEFAULT - 2);
- assertSuggestSetter('id', relevance: DART_RELEVANCE_DEFAULT - 2);
- }
-}
-
-@reflectiveTest
-class HtmlCompletionContributorTest extends AbstractCompletionContributorTest {
- void assertSuggestTransclusion(String name) {
- assertSuggestClassTypeAlias(name,
- relevance: TemplateCompleter.RELEVANCE_TRANSCLUSION);
- }
-
- // ignore: non_constant_identifier_names
- @override
- void setUp() {
- testFile = '/completionTest.html';
- super.setUp();
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_banana_noInput() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]')
-class MyDirective {
- @Input()
- String foo;
- @Output()
- EventEmitter<String> myDirectiveChange;
-}
- ''');
-
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('myDirective');
- assertNotSuggested('[foo]');
- assertNotSuggested('(myDirectiveChange)');
- assertNotSuggested('[(myDirective)]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_begin() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]')
-class MyDirective {}
- ''');
-
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('myDirective');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_complete() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective, MyDirectiveTwo])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]')
-class MyDirective {}
-@Directive(selector: '[myDirectiveTwo]')
-class MyDirectiveTwo {}
- ''');
-
- addTestSource('<my-tag ^myDirective></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 'myDirective'.length);
- assertSuggestSetter('myDirectiveTwo');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_middle() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]')
-class MyDirective {}
- ''');
-
- addTestSource('<my-tag myDi^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 'myDi'.length);
- expect(replacementLength, 'myDi'.length);
- assertSuggestSetter('myDirective');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_multipleAttribute_and() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective][foo][bar]')
-class MyDirective {}
- ''');
-
- addTestSource('<my-tag foo ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('myDirective');
- assertNotSuggested('foo');
- assertSuggestSetter('bar');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_multipleAttribute_attrValue1() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[foo=bar][baz]')
-class MyDirective {}
- ''');
-
- addTestSource('<my-tag foo="blah" ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('foo');
- assertNotSuggested('baz');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_multipleAttribute_attrValue2() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[foo=bar][baz]')
-class MyDirective {}
- ''');
-
- addTestSource('<my-tag foo="bar" ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('foo');
- assertSuggestSetter('baz');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_multipleAttribute_matchBanana() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective],[foo],[bar]')
-class MyDirective {
- @Input()
- String myDirective;
- @Output()
- EventEmitter<String> myDirectiveChange;
-}
- ''');
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('myDirective');
- assertSuggestSetter('[myDirective]');
- assertNotSuggested('(myDirective)');
- assertSuggestSetter('[(myDirective)]', returnType: 'String');
- assertSuggestSetter('foo');
- assertSuggestSetter('bar');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_multipleAttribute_matchInput() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective],[foo],[bar]')
-class MyDirective {
- @Input()
- String myDirective;
-}
- ''');
-
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('myDirective');
- assertSuggestSetter('[myDirective]');
- assertSuggestSetter('foo');
- assertSuggestSetter('bar');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_multipleAttribute_or() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective],[foo],[bar]')
-class MyDirective {}
- ''');
-
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('myDirective');
- assertSuggestSetter('foo');
- assertSuggestSetter('bar');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_multipleAttribute_or_matchOne() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective],[foo],[bar]')
-class MyDirective {}
- ''');
-
- addTestSource('<my-tag foo ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('myDirective');
- assertNotSuggested('bar');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_sharedBanana() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]')
-class MyDirective {
- @Input()
- String myDirective;
- @Output()
- EventEmitter<String> myDirectiveChange;
-}
- ''');
-
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('myDirective');
- assertSuggestSetter('[myDirective]');
- assertNotSuggested('(myDirective)');
- assertSuggestSetter('[(myDirective)]', returnType: 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_sharedInput() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]')
-class MyDirective {
- @Input()
- String myDirective;
-}
- ''');
-
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('myDirective');
- assertSuggestSetter('[myDirective]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availDirective_attribute_unsharedInput() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]')
-class MyDirective {
- @Input()
- String foo;
-}
- ''');
-
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('[foo]');
- assertSuggestSetter('myDirective');
- }
-
- // ignore: non_constant_identifier_names
- Future test_availFunctionalDirective_attribute_begin() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, myDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]')
-void myDirective() {}
- ''');
-
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('myDirective');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeAfterExportedPrefixes() async {
- newSource('/prefixed.dart', '''
-const int foo = 1;
-const int bar = 1;
-''');
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-import 'prefixed.dart' as prefixed;
-const int baz = 2;
-@Component(templateUrl: 'completionTest.html', selector: 'a', exports: const [
- prefixed.foo,
-])
-class MyComp {
-}
- ''');
-
- addTestSource('{{prefixed.^}}');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('foo', 'int');
- assertNotSuggested('bar');
- assertNotSuggested('baz');
- assertNotSuggested('MyComp');
- assertNotSuggested('hashCode');
- assertNotSuggested('toString()');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaNotStarted() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('[name]');
- assertSuggestSetter('[(name)]', returnType: 'String');
- assertSuggestGetter('(nameChange)', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaNotSuggested_after_inputUsed() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag [name]="\'bob\'" ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('[name]');
- assertSuggestGetter('(nameChange)', 'String');
- assertNotSuggested('[(name)]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaNotSuggested_after_outputUsed() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag (nameChange)="" ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('[name]');
- assertNotSuggested('(nameChange)');
- assertNotSuggested('[(name)]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaNotSuggestedTwice() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag [(name)]="\'bob\'" ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('[name]');
- assertNotSuggested('(nameChange)');
- assertNotSuggested('[(name)]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaReplacing() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-
- @Input() String codename;
- @Output() EventEmitter<String> codenameChange;
-}
- ''');
-
- addTestSource('<my-tag [(^name)]></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 2);
- expect(replacementLength, '[(name)]'.length);
- assertNotSuggested('[name]');
- assertNotSuggested('(nameChange)');
- assertNotSuggested('[codename]');
- assertNotSuggested('(codenameChange)');
- assertSuggestSetter('[(name)]', returnType: 'String');
- assertSuggestSetter('[(codename)]', returnType: 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaStarted1() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag [^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestSetter('[name]');
- assertSuggestSetter('[(name)]', returnType: 'String');
- assertNotSuggested('(nameChange)');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaStarted1_at_incompleteTag_with_EOF() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag [^');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertNotSuggested('(nameChange)');
- assertSuggestSetter('[name]');
- assertSuggestSetter('[(name)]', returnType: 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaStarted2() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag [(^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 2);
- expect(replacementLength, 2);
- assertNotSuggested('[name]');
- assertSuggestSetter('[(name)]', returnType: 'String');
- assertNotSuggested('(nameChange)');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaStarted2_at_incompleteTag_with_EOF() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag [(^');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 2);
- expect(replacementLength, 2);
- assertNotSuggested('(nameChange)');
- assertNotSuggested('[name]');
- assertSuggestSetter('[(name)]', returnType: 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaStarted_at_incompleteTag_bananaStart() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag [(^<div></div>');
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 2);
- expect(replacementLength, 2);
-
- assertNotSuggested('(nameChange)');
- assertNotSuggested('[name]');
- assertSuggestSetter('[(name)]', returnType: 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaStarted_at_incompleteTag_bracketStart() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag [^<div></div>');
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
-
- assertNotSuggested('(nameChange)');
- assertSuggestSetter('[name]');
- assertSuggestSetter('[(name)]', returnType: 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBananaSuggestsItself() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag [(name^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 6);
- expect(replacementLength, 6);
- assertNotSuggested('[name]');
- assertNotSuggested('(nameChange)');
- assertSuggestSetter('[(name)]', returnType: 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeBeforeComment() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-class MyClass{}
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {}
- ''');
-
- addTestSource('^<!-- comment! -->');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeCurrentClass() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
-}
- ''');
-
- addTestSource('{{^}}');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestClass('MyComp');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeDotMemberAlreadyStartedInMustache() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('html file {{text.le^}} with mustache');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 'le'.length);
- expect(replacementLength, 'le'.length);
- assertSuggestGetter('length', 'int');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeDotMemberInMustache() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('html file {{text.^}} with mustache');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('length', 'int');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeDotMemberInNgFor() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<div *ngFor="let item of text.^"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('length', 'int');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeDotMemberInNgIf() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgIf])
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<div *ngIf="text.^"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('length', 'int');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeEmptyExpressionDoesntIncludeVoid() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
- void dontCompleteMe() {}
-}
- ''');
-
- addTestSource('{{^}}');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested("dontCompleteMe");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeExportedPrefixes() async {
- newSource('/prefix_one.dart', '''
-const int foo = 1;
-''');
- newSource('/prefix_two.dart', '''
-const int foo = 1;
-const int bar = 1;
-''');
- newSource('/prefix_three.dart', '''
-const int foo = 1;
-const int bar = 1;
-const int baz = 1;
-''');
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-import 'prefix_one.dart' as prefix_one;
-import 'prefix_two.dart' as prefix_two;
-import 'prefix_three.dart' as prefix_three;
-@Component(templateUrl: 'completionTest.html', selector: 'a', exports: const [
- prefix_one.foo,
- prefix_two.foo,
- prefix_two.bar,
-])
-class MyComp {
-}
- ''');
-
- addTestSource('{{^}}');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestLibrary('prefix_one');
- assertSuggestLibrary('prefix_two');
- assertNotSuggested('prefix_three');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeExports() async {
- newSource('/prefixed.dart', '''
-const int otherAccessor = 1;
-int otherFunction(){}
-class OtherClass {}
-enum OtherEnum {}
-''');
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-import 'prefixed.dart' as prefixed;
-const int myAccessor = 1;
-int myFunction(){}
-class MyClass {}
-enum MyEnum {}
-@Component(templateUrl: 'completionTest.html', selector: 'a', exports: const [
- myAccessor,
- myFunction,
- MyClass,
- MyEnum,
- prefixed.otherAccessor,
- prefixed.otherFunction,
- prefixed.OtherClass,
- prefixed.OtherEnum,
-])
-class MyComp {
-}
- ''');
-
- addTestSource('{{^}}');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('myAccessor', 'int');
- assertSuggestFunction('myFunction', 'int');
- assertSuggestClass('MyClass');
- assertSuggestEnum('MyEnum');
- assertSuggestGetter('prefixed.otherAccessor', 'int',
- elementName: 'otherAccessor');
- assertSuggestFunction('prefixed.otherFunction', 'int',
- elementName: 'otherFunction');
- assertSuggestClass('prefixed.OtherClass', elemName: 'OtherClass');
- assertSuggestEnum('prefixed.OtherEnum');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeExportsAfterNew() async {
- newSource('/prefixed.dart', '''
-const int foo = 1;
-class OtherClass {};
-''');
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-import 'prefixed.dart' as prefixed;
-class MyClass{}
-@Component(templateUrl: 'completionTest.html', selector: 'a', exports: const [
- MyClass,
- prefixed.foo,
- prefixed.OtherClass,
-])
-class MyComp {
-}
- ''');
-
- // NOTE: This actually isn't valid angular yet (we flag it) but one day will
- // be: once we move to angular_ast in both repos.
- addTestSource('{{new ^}}');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestClass('MyComp');
- assertSuggestClass('MyClass');
- assertSuggestClass('prefixed.OtherClass', elemName: 'OtherClass');
- assertSuggestLibrary('prefixed');
- assertNotSuggested('foo');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHashVar() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
-}
- ''');
-
- addTestSource('<button #buttonEl>button</button> {{^}}');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestLocalVar('buttonEl', 'ButtonElement');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHtmlSelectorTag__in_middle_of_unclosed_tag() async {
- final dartSource = newSource('/completionTest.dart', '''
- import 'package:angular2/angular2.dart';
- @Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyChildComponent1, MyChildComponent2])
- class MyComp{}
- @Component(template: '', selector: 'my-child1, my-child2')
- class MyChildComponent1{}
- @Component(template: '', selector: 'my-child3.someClass[someAttr]')
- class MyChildComponent2{}
- ''');
- addTestSource('<div>some text<^');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHtmlSelectorTag_at_beginning() async {
- final dartSource = newSource('/completionTest.dart', '''
- import 'package:angular2/angular2.dart';
- @Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyChildComponent1, MyChildComponent2])
- class MyComp{}
- @Component(template: '', selector: 'my-child1, my-child2')
- class MyChildComponent1{}
- @Component(template: '', selector: 'my-child3.someClass[someAttr]')
- class MyChildComponent2
- ''');
- addTestSource('<^<div></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHtmlSelectorTag_at_beginning_with_partial() async {
- final dartSource = newSource('/completionTest.dart', '''
- import 'package:angular2/angular2.dart';
- @Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyChildComponent1, MyChildComponent2])
- class MyComp{}
- @Component(template: '', selector: 'my-child1, my-child2')
- class MyChildComponent1{}
- @Component(template: '', selector: 'my-child3.someClass[someAttr]')
- class MyChildComponent2{}
- ''');
- addTestSource('<my^<div></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '<my'.length);
- expect(replacementLength, '<my'.length);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHtmlSelectorTag_at_end() async {
- final dartSource = newSource('/completionTest.dart', '''
- import 'package:angular2/angular2.dart';
- @Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyChildComponent1, MyChildComponent2])
- class MyComp{}
- @Component(template: '', selector: 'my-child1, my-child2')
- class MyChildComponent1{}
- @Component(template: '', selector: 'my-child3.someClass[someAttr]')
- class MyChildComponent2{}
- ''');
- addTestSource('''<div><div></div></div><^''');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHtmlSelectorTag_at_end_after_close() async {
- final dartSource = newSource('/completionTest.dart', '''
- import 'package:angular2/angular2.dart';
- @Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyChildComponent1, MyChildComponent2])
- class MyComp{}
- @Component(template: '', selector: 'my-child1, my-child2')
- class MyChildComponent1{}
- @Component(template: '', selector: 'my-child3.someClass[someAttr]')
- class MyChildComponent2{}
- ''');
- addTestSource('<div><div></div></div>^');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHtmlSelectorTag_at_end_with_partial() async {
- final dartSource = newSource('/completionTest.dart', '''
- import 'package:angular2/angular2.dart';
- @Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyChildComponent1, MyChildComponent2])
- class MyComp{}
- @Component(template: '', selector: 'my-child1, my-child2')
- class MyChildComponent1{}
- @Component(template: '', selector: 'my-child3.someClass[someAttr]')
- class MyChildComponent2{}
- ''');
- addTestSource('''<div><div></div></div>
- <my^''');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '<my'.length);
- expect(replacementLength, '<my'.length);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHtmlSelectorTag_at_middle() async {
- final dartSource = newSource('/completionTest.dart', '''
- import 'package:angular2/angular2.dart';
- @Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyChildComponent1, MyChildComponent2])
- class MyComp{}
- @Component(template: '', selector: 'my-child1, my-child2')
- class MyChildComponent1{}
- @Component(template: '', selector: 'my-child3.someClass[someAttr]')
- class MyChildComponent2{}
- ''');
- addTestSource('''<div><div><^</div></div>''');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHtmlSelectorTag_at_middle_of_text() async {
- final dartSource = newSource('/completionTest.dart', '''
- import 'package:angular2/angular2.dart';
- @Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyChildComponent1, MyChildComponent2])
- class MyComp{}
- @Component(template: '', selector: 'my-child1, my-child2')
- class MyChildComponent1{}
- @Component(template: '', selector: 'my-child3.someClass[someAttr]')
- class MyChildComponent2{}
- ''');
- addTestSource('''<div><div> some text<^</div></div>''');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHtmlSelectorTag_at_middle_with_partial() async {
- final dartSource = newSource('/completionTest.dart', '''
- import 'package:angular2/angular2.dart';
- @Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyChildComponent1, MyChildComponent2])
- class MyComp{}
- @Component(template: '', selector: 'my-child1, my-child2')
- class MyChildComponent1{}
- @Component(template: '', selector: 'my-child3.someClass[someAttr]')
- class MyChildComponent2{}
- ''');
- addTestSource('''<div><div><my^</div></div>''');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '<my'.length);
- expect(replacementLength, '<my'.length);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeHtmlSelectorTag_on_empty_document() async {
- final dartSource = newSource('/completionTest.dart', '''
- import 'package:angular2/angular2.dart';
- @Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyChildComponent1, MyChildComponent2])
- class MyComp{}
- @Component(template: '', selector: 'my-child1, my-child2')
- class MyChildComponent1{}
- @Component(template: '', selector: 'my-child3.someClass[someAttr]')
- class MyChildComponent2{}
- ''');
- addTestSource('^');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestClassTypeAlias("<my-child1");
- assertSuggestClassTypeAlias("<my-child2");
- assertSuggestClassTypeAlias("<my-child3");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInMiddleOfExpressionDoesntIncludeVoid() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
- bool takesArg(dynamic arg) {};
- void dontCompleteMe() {}
-}
- ''');
-
- addTestSource('{{takesArg(^)}}');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested("dontCompleteMe");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputAsPlainAttribute() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Input() int intInput;
-
- bool _myDynamicInput = false;
- bool get myDynamicInput => _myDynamicInput;
- @Input()
- void set myDynamicInput(value) {}
-}
- ''');
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('name');
- assertNotSuggested('intInput');
- assertSuggestSetter('id', relevance: DART_RELEVANCE_DEFAULT - 2);
- assertSuggestSetter('[myDynamicInput]');
- assertSuggestSetter('myDynamicInput',
- relevance: DART_RELEVANCE_DEFAULT - 1);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputAsPlainAttributeStarted() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Input() int intInput;
-
- bool _myDynamicInput = false;
- bool get myDynamicInput => _myDynamicInput;
- @Input()
- void set myDynamicInput(value) {}
-}
- ''');
- addTestSource('<my-tag myDyna^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 6);
- expect(replacementLength, 6);
- assertSuggestSetter('name');
- assertNotSuggested('intInput');
- assertSuggestSetter('id', relevance: DART_RELEVANCE_DEFAULT - 2);
- assertSuggestSetter('[myDynamicInput]');
- assertSuggestSetter('myDynamicInput',
- relevance: DART_RELEVANCE_DEFAULT - 1);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputInStar() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- List<String> items;
-}
- ''');
-
- addTestSource('<div *ngFor="let x of items; ^"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestTemplateInput("trackBy:", elementName: '[ngForTrackBy]');
- assertNotSuggested("of");
- assertNotSuggested("of:");
- assertNotSuggested("trackBy"); // without the colon
- assertNotSuggested("items");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputInStarReplacing() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- List<String> items;
-}
- ''');
-
- addTestSource('<div *ngFor="let x of items; trackBy^: foo"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 'trackBy'.length);
- expect(replacementLength, 'trackBy'.length);
- assertSuggestTemplateInput("trackBy:", elementName: '[ngForTrackBy]');
- assertNotSuggested("of");
- assertNotSuggested("of:");
- assertNotSuggested("trackBy"); // without the colon
- assertNotSuggested("items");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputInStarReplacingBeforeValue() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- List<String> items;
-}
- ''');
-
- addTestSource('<div *ngFor="let x of items; trackBy^"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 'trackBy'.length);
- expect(replacementLength, 'trackBy'.length);
- assertSuggestTemplateInput("trackBy:", elementName: '[ngForTrackBy]');
- assertNotSuggested("of");
- assertNotSuggested("of:");
- assertNotSuggested("trackBy"); // without the colon
- assertNotSuggested("items");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputInStarValueAlready() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- List<String> items;
-}
- ''');
-
- addTestSource('<div *ngFor="let x of items; ^ : foo"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestTemplateInput("trackBy:", elementName: '[ngForTrackBy]');
- assertNotSuggested("of");
- assertNotSuggested("of:");
- assertNotSuggested("trackBy"); // without the colon
- assertNotSuggested("items");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputNotStarted() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('[name]');
- assertSuggestSetter('[hidden]', relevance: DART_RELEVANCE_DEFAULT - 2);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputNotStarted_plain_standardHtmlInput() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
-}
- ''');
-
- addTestSource('<div ^></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('class', relevance: DART_RELEVANCE_DEFAULT - 2);
- assertNotSuggested('className');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputNotStarted_standardHtmlInput() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
-}
- ''');
-
- addTestSource('<div ^></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('[class]', relevance: DART_RELEVANCE_DEFAULT - 2);
- assertNotSuggested('[className]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputNotSuggestedTwice() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag [name]="\'bob\'" ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested("[name]");
- assertSuggestGetter("(nameEvent)", "String");
- assertSuggestGetter("(click)", "MouseEvent",
- relevance: DART_RELEVANCE_DEFAULT - 1);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputOutputBanana() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-
- @Input() String twoWay;
- @Output() EventEmitter<String> twoWayChange;
-}
- ''');
-
- addTestSource('<my-tag ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('[name]');
- assertSuggestSetter('[hidden]', relevance: DART_RELEVANCE_DEFAULT - 2);
- assertSuggestGetter('(nameEvent)', 'String');
- assertSuggestGetter('(click)', 'MouseEvent',
- relevance: DART_RELEVANCE_DEFAULT - 1);
- assertSuggestSetter('[twoWay]');
- assertSuggestGetter('(twoWayChange)', 'String');
- assertSuggestSetter('[(twoWay)]', returnType: 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputOutputBanana_at_incompleteTag_with_EOF() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-
- @Input() String twoWay;
- @Output() EventEmitter<String> twoWayChange;
-}
- ''');
-
- addTestSource('<my-tag ^');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('[name]');
- assertSuggestSetter('[hidden]', relevance: DART_RELEVANCE_DEFAULT - 2);
- assertSuggestGetter('(nameEvent)', 'String');
- assertSuggestGetter('(click)', 'MouseEvent',
- relevance: DART_RELEVANCE_DEFAULT - 1);
- assertSuggestSetter('[twoWay]');
- assertSuggestGetter('(twoWayChange)', 'String');
- assertSuggestSetter('[(twoWay)]', returnType: 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputOutputBanana_at_incompleteTag_with_newTag() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-
- @Input() String twoWay;
- @Output() EventEmitter<String> twoWayChange;
-}
- ''');
-
- addTestSource('<my-tag ^<div></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter('[name]');
- assertSuggestSetter('[hidden]', relevance: DART_RELEVANCE_DEFAULT - 2);
- assertSuggestGetter('(nameEvent)', 'String');
- assertSuggestGetter('(click)', 'MouseEvent',
- relevance: DART_RELEVANCE_DEFAULT - 1);
- assertSuggestSetter('[twoWay]');
- assertSuggestGetter('(twoWayChange)', 'String');
- assertSuggestSetter('[(twoWay)]', returnType: 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputOutputNotSuggestedAfterTwoWay() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
- String name;
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameChange;
-}
- ''');
-
- addTestSource('<my-tag [(name)]="name" ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested("[name]");
- assertNotSuggested("(nameEvent)");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputReplacing() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag [^input]="4"></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, '[input]'.length);
- assertSuggestSetter("[name]");
- assertSuggestSetter("[hidden]", relevance: DART_RELEVANCE_DEFAULT - 2);
- assertNotSuggested("(nameEvent)");
- assertNotSuggested("(click)");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputStarted() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag [^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestSetter("[name]");
- assertSuggestSetter("[hidden]", relevance: DART_RELEVANCE_DEFAULT - 2);
- assertNotSuggested("(nameEvent)");
- assertNotSuggested("(click)");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputStarted_at_incompleteTag_with_EOF() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag [^');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestSetter("[name]");
- assertSuggestSetter("[hidden]", relevance: DART_RELEVANCE_DEFAULT - 2);
- assertNotSuggested("(nameEvent)");
- assertNotSuggested("(click)");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputStarted_at_incompleteTag_with_newTag() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag [^<div></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestSetter("[name]");
- assertSuggestSetter("[hidden]", relevance: DART_RELEVANCE_DEFAULT - 2);
- assertNotSuggested("(nameEvent)");
- assertNotSuggested("(click)");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputStarted_plain_standardHtmlInput() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
-}
- ''');
-
- addTestSource('<div cla^></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 3);
- expect(replacementLength, 3);
- assertSuggestSetter('class', relevance: DART_RELEVANCE_DEFAULT - 2);
- assertNotSuggested('className');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputStarted_standardHtmlInput() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
-}
- ''');
-
- addTestSource('<div [^></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestSetter('[class]', relevance: DART_RELEVANCE_DEFAULT - 2);
- assertNotSuggested('[className]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeInputSuggestsItself() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag [name^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '[name'.length);
- expect(replacementLength, '[name'.length);
- assertSuggestSetter("[name]");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInMustache() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('html file {{^}} with mustache');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- assertSuggestMethod('toString', 'Object', 'String');
- assertSuggestGetter('hashCode', 'int');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInNgFor() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<div *ngFor="let item of ^"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- assertSuggestMethod('toString', 'Object', 'String');
- assertSuggestGetter('hashCode', 'int');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInNgIf() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgIf])
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<div *ngIf="^"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- assertSuggestMethod('toString', 'Object', 'String');
- assertSuggestGetter('hashCode', 'int');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeMemberInNgIfPartial() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgIf])
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<div *ngIf="let ^" ></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('text');
- assertNotSuggested('ngIf');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeNgForItem() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- List<String> items;
-}
- ''');
-
- addTestSource('<div *ngFor="let item of items">{{^}}</div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestLocalVar('item', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeNgForStarted() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- List<String> items;
-}
- ''');
-
- addTestSource('<div *ngFor^');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '*ngFor'.length);
- expect(replacementLength, '*ngFor'.length);
- assertSuggestStar("*ngFor");
- assertNotSuggested("*ngForOf");
- assertNotSuggested("[id]");
- assertNotSuggested("id");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeNgForStartedWithValue() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- List<String> items;
-}
- ''');
-
- addTestSource('<div *ngFor^="let x of items"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '*ngFor'.length);
- expect(replacementLength, '*ngFor'.length);
- assertSuggestStar("*ngFor");
- assertNotSuggested("*ngForOf");
- assertNotSuggested("[id]");
- assertNotSuggested("id");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeNgVars_notAfterDot() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
- List<String> items;
-}
- ''');
-
- addTestSource(
- '<button #buttonEl>button</button><div *ngFor="item of items">{{hashCode.^}}</div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('buttonEl');
- assertNotSuggested('item');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeOutputNotSuggestedTwice() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag (nameEvent)="" ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter("[name]");
- assertSuggestSetter("[hidden]", relevance: DART_RELEVANCE_DEFAULT - 2);
- assertNotSuggested("(nameEvent)");
- assertSuggestGetter("(click)", "MouseEvent",
- relevance: DART_RELEVANCE_DEFAULT - 1);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeOutputReplacing() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag (^output)="4"></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, '(output)'.length);
- assertSuggestGetter("(nameEvent)", "String");
- assertSuggestGetter("(click)", "MouseEvent",
- relevance: DART_RELEVANCE_DEFAULT - 1);
- assertNotSuggested("[name]");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeOutputStarted() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag (^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestGetter("(nameEvent)", "String");
- assertSuggestGetter("(click)", "MouseEvent",
- relevance: DART_RELEVANCE_DEFAULT - 1);
- assertNotSuggested("[name]");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeOutputStarted_at_incompleteTag_with_EOF() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag (^');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertNotSuggested("[name]");
- assertNotSuggested("[hidden]");
- assertSuggestGetter("(nameEvent)", "String");
- assertSuggestGetter("(click)", "MouseEvent",
- relevance: DART_RELEVANCE_DEFAULT - 1);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeOutputStarted_at_incompleteTag_with_newTag() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag (^<div></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertNotSuggested("[name]");
- assertNotSuggested("[hidden]");
- assertSuggestGetter("(nameEvent)", "String");
- assertSuggestGetter("(click)", "MouseEvent",
- relevance: DART_RELEVANCE_DEFAULT - 1);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeOutputSuggestsItself() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag (nameEvent^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '(nameEvent'.length);
- expect(replacementLength, '(nameEvent'.length);
- assertSuggestGetter("(nameEvent)", "String");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeStandardInputNotSuggestedTwice() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag [hidden]="true" ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested("[hidden]");
- assertSuggestSetter("[name]");
- assertSuggestGetter("(nameEvent)", "String");
- assertSuggestGetter("(click)", "MouseEvent",
- relevance: DART_RELEVANCE_DEFAULT - 1);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeStandardInputSuggestsItself() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag [hidden^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '[hidden'.length);
- expect(replacementLength, '[hidden'.length);
- assertSuggestSetter("[hidden]", relevance: DART_RELEVANCE_DEFAULT - 2);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeStarAttrsNotStarted() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [NgFor, NgIf, CustomTemplateDirective, NotTemplateDirective])
-class MyComp {
- List<String> items;
-}
-
-@Directive(selector: '[customTemplateDirective]')
-class CustomTemplateDirective {
- CustomTemplateDirective(TemplateRef tpl);
-}
-
-@Directive(selector: '[notTemplateDirective]')
-class NotTemplateDirective {
-}
- ''');
-
- addTestSource('<div ^></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestStar("*ngFor");
- assertSuggestStar("*ngIf");
- assertSuggestStar("*customTemplateDirective");
- assertNotSuggested("*notTemplateDirective");
- assertNotSuggested("*ngForOf");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeStarAttrsOnlyStar() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives:
- const [NgFor, NgIf, CustomTemplateDirective, functionalTemplateDirective])
-class MyComp {
- List<String> items;
-}
-
-@Directive(selector: '[customTemplateDirective]')
-class CustomTemplateDirective {
- CustomTemplateDirective(TemplateRef tpl);
-}
-
-@Directive(selector: '[functionalTemplateDirective]')
-void functionalTemplateDirective(TemplateRef tpl);
- ''');
-
- addTestSource('<div *^></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestStar("*ngFor");
- assertSuggestStar("*ngIf");
- assertSuggestStar("*customTemplateDirective");
- assertSuggestStar("*functionalTemplateDirective");
- assertNotSuggested("*ngForOf");
- assertNotSuggested("[id]");
- assertNotSuggested("id");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeStatements() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<button (click)="^"></button>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestLocalVar(r'$event', 'MouseEvent');
- assertSuggestField('text', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeStdOutputNotSuggestedTwice() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag (click)="" ^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestSetter("[name]");
- assertSuggestSetter("[hidden]", relevance: DART_RELEVANCE_DEFAULT - 2);
- assertSuggestGetter("(nameEvent)", "String");
- assertNotSuggested("(click)");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeStdOutputSuggestsItself() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter<String> nameEvent;
-}
- ''');
-
- addTestSource('<my-tag (click^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - '(click'.length);
- expect(replacementLength, '(click'.length);
- assertSuggestGetter("(click)", "MouseEvent",
- relevance: DART_RELEVANCE_DEFAULT - 1);
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeTransclusionSuggestion() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [ContainerComponent])
-class MyComp{}
-
-@Component(template:
- '<ng-content select="tag1,tag2[withattr],tag3.withclass"></ng-content>',
- selector: 'container')
-class ContainerComponent{}
- ''');
- addTestSource('<container>^</container>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestTransclusion("<tag1");
- assertSuggestTransclusion("<tag2 withattr");
- assertSuggestTransclusion("<tag3 class=\"withclass\"");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeTransclusionSuggestionAfterTag() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [ContainerComponent])
-class MyComp{}
-
-@Component(template:
- '<ng-content select="tag1,tag2[withattr],tag3.withclass"></ng-content>',
- selector: 'container')
-class ContainerComponent{}
- ''');
- addTestSource('''
-<container>
- <blah></blah>
- ^
-</container>''');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestTransclusion("<tag1");
- assertSuggestTransclusion("<tag2 withattr");
- assertSuggestTransclusion("<tag3 class=\"withclass\"");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeTransclusionSuggestionBeforeTag() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [ContainerComponent])
-class MyComp{}
-
-@Component(template:
- '<ng-content select="tag1,tag2[withattr],tag3.withclass"></ng-content>',
- selector: 'container')
-class ContainerComponent{}
- ''');
- addTestSource('''
-<container>
- ^
- <blah></blah>
-</container>''');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestTransclusion("<tag1");
- assertSuggestTransclusion("<tag2 withattr");
- assertSuggestTransclusion("<tag3 class=\"withclass\"");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeTransclusionSuggestionInWhitespace() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [ContainerComponent])
-class MyComp{}
-
-@Component(template:
- '<ng-content select="tag1,tag2[withattr],tag3.withclass"></ng-content>',
- selector: 'container')
-class ContainerComponent{}
- ''');
- addTestSource('''
-<container>
- ^
-</container>''');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestTransclusion("<tag1");
- assertSuggestTransclusion("<tag2 withattr");
- assertSuggestTransclusion("<tag3 class=\"withclass\"");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeTransclusionSuggestionStarted() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [ContainerComponent])
-class MyComp{}
-
-@Component(template:
- '<ng-content select="tag1,tag2[withattr],tag3.withclass"></ng-content>',
- selector: 'container')
-class ContainerComponent{}
- ''');
- addTestSource('''
-<container>
- <^
-</container>''');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- //expect(replacementOffset, completionOffset - 1);
- //expect(replacementLength, 1);
- assertSuggestTransclusion("<tag1");
- assertSuggestTransclusion("<tag2 withattr");
- assertSuggestTransclusion("<tag3 class=\"withclass\"");
- }
-
- Future test_completeTransclusionSuggestionStartedTagName() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [ContainerComponent])
-class MyComp{}
-
-@Component(template:
- '<ng-content select="tag1,tag2[withattr],tag3.withclass"></ng-content>',
- selector: 'container')
-class ContainerComponent{}
- ''');
- addTestSource('''
-<container>
- <tag^
-</container>''');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- //expect(replacementOffset, completionOffset - 4);
- //expect(replacementLength, 4);
- assertSuggestTransclusion("<tag1");
- assertSuggestTransclusion("<tag2 withattr");
- assertSuggestTransclusion("<tag3 class=\"withclass\"");
- }
-
- // ignore: non_constant_identifier_names
- Future test_completeUnclosedMustache() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('some text and {{^ <div>some html</div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_findCompletionTarget_afterUnclosedDom() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a')
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<input /> {{^}}');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestGetter('text', 'String');
- }
-
- // ignore: non_constant_identifier_names
- Future test_noCompleteEmptyTagContents() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter event;
-}
- ''');
-
- addTestSource('<my-tag>^</my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested("[name]");
- assertNotSuggested("[hidden]");
- assertNotSuggested("(event)");
- assertNotSuggested("(click)");
- }
-
- // ignore: non_constant_identifier_names
- Future test_noCompleteInOutputInCloseTag() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter event;
-
- @Input() String twoWay;
- @Output() EventEmitter<String> twoWayChange;
-}
- ''');
-
- addTestSource('<my-tag></my-tag ^>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('[name]');
- assertNotSuggested('[hidden]');
- assertNotSuggested('(event)');
- assertNotSuggested('(click)');
- assertNotSuggested('[twoWay]');
- assertNotSuggested('(twoWayChange)');
- assertNotSuggested('[(twoWay)]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_noCompleteInOutputsOnTagNameCompletion() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [OtherComp])
-class MyComp {
-}
-@Component(template: '', selector: 'my-tag')
-class OtherComp {
- @Input() String name;
- @Output() EventEmitter event;
-
- @Input() String twoWay;
- @Output() EventEmitter<String> twoWayChange;
-}
- ''');
-
- addTestSource('<my-tag^></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, 0);
- expect(replacementLength, '<my-tag'.length);
- assertNotSuggested('[name]');
- assertNotSuggested('[hidden]');
- assertNotSuggested('(event)');
- assertNotSuggested('(click)');
- assertNotSuggested('[twoWay]');
- assertNotSuggested('(twoWayChange)');
- assertNotSuggested('[(twoWay)]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_noCompleteMemberInNgFor_forLettedName() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<div *ngFor="let ^"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('text');
- }
-
- // ignore: non_constant_identifier_names
- Future test_noCompleteMemberInNgForAfterLettedName() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<div *ngFor="let item^ of [text]"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('text');
- }
-
- // ignore: non_constant_identifier_names
- Future test_noCompleteMemberInNgForInLet() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<div *ngFor="l^et item of [text]"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('text');
- }
-
- // ignore: non_constant_identifier_names
- Future test_noCompleteMemberInNgForInLettedName() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<div *ngFor="let i^tem of [text]"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('text');
- }
-
- // ignore: non_constant_identifier_names
- Future test_noCompleteMemberInNgForRightAfterLet() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a', directives: const [NgFor])
-class MyComp {
- String text;
-}
- ''');
-
- addTestSource('<div *ngFor="let^ item of [text]"></div>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('text');
- }
-
- // ignore: non_constant_identifier_names
- Future test_refValue_begin() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]', exportAs: 'foo')
-class MyDirective {}
- ''');
-
- addTestSource('<my-tag myDirective #ref="^"></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestLabel('foo');
- }
-
- // ignore: non_constant_identifier_names
- Future test_refValue_complete() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]', exportAs: 'foobar')
-class MyDirective {}
- ''');
-
- addTestSource('<my-tag myDirective #ref="^foobar"></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 'foobar'.length);
- assertSuggestLabel('foobar');
- }
-
- // ignore: non_constant_identifier_names
- Future test_refValue_middle() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirective])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirective]', exportAs: 'foobar')
-class MyDirective {}
- ''');
-
- addTestSource('<my-tag myDirective #ref="foo^"></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 'foo'.length);
- expect(replacementLength, 'foo'.length);
- assertSuggestLabel('foobar');
- }
-
- // ignore: non_constant_identifier_names
- Future test_refValue_should_dedupe() async {
- final dartSource = newSource('/completionTest.dart', '''
-import 'package:angular2/angular2.dart';
-@Component(templateUrl: 'completionTest.html', selector: 'a',
- directives: const [MyTagComponent, MyDirectiveOne, MyDirectiveTwo])
-class MyComp {
-}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent{}
-@Directive(selector: '[myDirectiveOne]', exportAs: 'foobar')
-class MyDirectiveOne {}
-@Directive(selector: '[myDirectiveTwo]', exportAs: 'foobar')
-class MyDirectiveTwo {}
- ''');
-
- addTestSource('<my-tag myDirectiveOne myDirectiveTwo #ref="^"></my-tag>');
-
- await resolveSingleTemplate(dartSource);
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestLabel('foobar');
- }
-}
diff --git a/angular_analyzer_plugin/test/completion_contributor_test_util.dart b/angular_analyzer_plugin/test/completion_contributor_test_util.dart
deleted file mode 100644
index 6b79273..0000000
--- a/angular_analyzer_plugin/test/completion_contributor_test_util.dart
+++ /dev/null
@@ -1,616 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol
- show ElementKind;
-import 'package:analyzer_plugin/protocol/protocol_common.dart'
- hide Element, ElementKind;
-import 'package:analyzer_plugin/src/utilities/completion/completion_core.dart';
-import 'package:analyzer_plugin/utilities/completion/completion_core.dart';
-import 'package:analyzer_plugin/utilities/completion/relevance.dart';
-import 'package:angular_analyzer_plugin/src/completion.dart';
-import 'package:angular_analyzer_plugin/src/completion_request.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:test/test.dart';
-
-import 'abstract_angular.dart';
-
-int suggestionComparator(CompletionSuggestion s1, CompletionSuggestion s2) {
- final c1 = s1.completion.toLowerCase();
- final c2 = s2.completion.toLowerCase();
- return c1.compareTo(c2);
-}
-
-abstract class AbstractCompletionContributorTest
- extends BaseCompletionContributorTest {
- List<CompletionContributor> contributors;
- CompletionCollectorImpl collector;
-
- @override
- Future computeSuggestions([int times = 200]) async {
- final templates = await angularDriver.getTemplatesForFile(testFile);
- final standardHtml = await angularDriver.getStandardHtml();
- final angularCompletionRequest = new AngularCompletionRequest(
- completionOffset, testFile, resourceProvider, templates, standardHtml);
- final collector = new CompletionCollectorImpl();
-
- // Request completions
- for (final contributor in contributors) {
- await contributor.computeSuggestions(angularCompletionRequest, collector);
- }
- if (!collector.offsetIsSet) {
- collector
- ..offset = angularCompletionRequest.offset
- ..length = 0;
- }
- suggestions = collector.suggestions;
- replacementOffset = collector.offset;
- replacementLength = collector.length;
- expect(suggestions, isNotNull, reason: 'expected suggestions');
- }
-
- List<CompletionContributor> createContributors() => <CompletionContributor>[
- new AngularCompletionContributor(),
- new NgInheritedReferenceContributor(),
- new NgTypeMemberContributor(),
- new NgOffsetLengthContributor(),
- ];
-
- /// Compute all the views declared in the given [dartSource], and resolve the
- /// external template of all the views.
- Future resolveSingleTemplate(Source dartSource) async {
- final result = await angularDriver.requestDartResult(dartSource.fullName);
- for (var d in result.directives) {
- if (d is Component && d.view.templateUriSource != null) {
- final htmlPath = d.view.templateUriSource.fullName;
- await angularDriver.requestHtmlResult(htmlPath);
- }
- }
- }
-
- @override
- void setUp() {
- super.setUp();
- contributors = createContributors();
- }
-}
-
-abstract class BaseCompletionContributorTest extends AbstractAngularTest {
- String testFile;
- Source testSource;
- int completionOffset;
- int replacementOffset;
- int replacementLength;
- List<CompletionSuggestion> suggestions;
-
- /// If `true` and `null` is specified as the suggestion's expected returnType
- /// then the actual suggestion is expected to have a `dynamic` returnType.
- /// Newer tests return `false` so that they can distinguish between
- /// `dynamic` and `null`.
- /// Eventually all tests should be converted and this getter removed.
- bool get isNullExpectedReturnTypeConsideredDynamic => true;
-
- void addTestSource(String content) {
- expect(completionOffset, isNull, reason: 'Call addTestUnit exactly once');
- completionOffset = content.indexOf('^');
- expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
- final nextOffset = content.indexOf('^', completionOffset + 1);
- expect(nextOffset, equals(-1), reason: 'too many ^');
- // ignore: parameter_assignments, prefer_interpolation_to_compose_strings
- content = content.substring(0, completionOffset) +
- content.substring(completionOffset + 1);
- testSource = newSource(testFile, content);
- }
-
- void assertHasNoParameterInfo(final suggestion) {
- expect(suggestion.parameterNames, isNull);
- expect(suggestion.parameterTypes, isNull);
- expect(suggestion.requiredParameterCount, isNull);
- expect(suggestion.hasNamedParameters, isNull);
- }
-
- void assertHasParameterInfo(final suggestion) {
- expect(suggestion.parameterNames, isNotNull);
- expect(suggestion.parameterTypes, isNotNull);
- expect(suggestion.parameterNames.length, suggestion.parameterTypes.length);
- expect(suggestion.requiredParameterCount,
- lessThanOrEqualTo(suggestion.parameterNames.length));
- expect(suggestion.hasNamedParameters, isNotNull);
- }
-
- void assertNoSuggestions({CompletionSuggestionKind kind}) {
- if (kind == null) {
- if (suggestions.isNotEmpty) {
- failedCompletion('Expected no suggestions', suggestions);
- }
- return;
- }
- final suggestion = suggestions.firstWhere((final cs) => cs.kind == kind,
- orElse: () => null);
- if (suggestion != null) {
- failedCompletion('did not expect completion: $completion\n $suggestion');
- }
- }
-
- void assertNotSuggested(String completion) {
- final suggestion = suggestions.firstWhere(
- (final cs) => cs.completion == completion,
- orElse: () => null);
- if (suggestion != null) {
- failedCompletion('did not expect completion: $completion\n $suggestion');
- }
- }
-
- CompletionSuggestion assertSuggest(String completion,
- {CompletionSuggestionKind csKind: CompletionSuggestionKind.INVOCATION,
- int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- protocol.ElementKind elemKind,
- bool isDeprecated: false,
- bool isPotential: false,
- String elemFile,
- int elemOffset,
- final paramName,
- final paramType}) {
- final cs =
- getSuggest(completion: completion, csKind: csKind, elemKind: elemKind);
- if (cs == null) {
- failedCompletion('expected $completion $csKind $elemKind', suggestions);
- }
- expect(cs.kind, equals(csKind));
- if (isDeprecated) {
- expect(cs.relevance, equals(DART_RELEVANCE_LOW));
- } else {
- expect(cs.relevance, equals(relevance), reason: completion);
- }
- expect(cs.importUri, importUri);
- expect(cs.selectionOffset, equals(completion.length));
- expect(cs.selectionLength, equals(0));
- expect(cs.isDeprecated, equals(isDeprecated));
- expect(cs.isPotential, equals(isPotential));
- if (cs.element != null) {
- expect(cs.element.location, isNotNull);
- expect(cs.element.location.file, isNotNull);
- expect(cs.element.location.offset, isNotNull);
- expect(cs.element.location.length, isNotNull);
- expect(cs.element.location.startColumn, isNotNull);
- expect(cs.element.location.startLine, isNotNull);
- }
- if (elemFile != null) {
- expect(cs.element.location.file, elemFile);
- }
- if (elemOffset != null) {
- expect(cs.element.location.offset, elemOffset);
- }
- if (paramName != null) {
- expect(cs.parameterName, paramName);
- }
- if (paramType != null) {
- expect(cs.parameterType, paramType);
- }
- return cs;
- }
-
- CompletionSuggestion assertSuggestClass(String name,
- {int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- bool isDeprecated: false,
- String elemFile,
- String elemName,
- int elemOffset}) {
- final cs = assertSuggest(name,
- csKind: kind,
- relevance: relevance,
- importUri: importUri,
- isDeprecated: isDeprecated,
- elemFile: elemFile,
- elemOffset: elemOffset);
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.CLASS));
- expect(element.name, equals(elemName ?? name));
- expect(element.parameters, isNull);
- expect(element.returnType, isNull);
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestClassTypeAlias(String name,
- {int relevance: DART_RELEVANCE_DEFAULT,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION}) {
- final cs = assertSuggest(name, csKind: kind, relevance: relevance);
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.CLASS_TYPE_ALIAS));
- expect(element.name, equals(name));
- expect(element.parameters, isNull);
- expect(element.returnType, isNull);
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestConstructor(String name,
- {int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- int elemOffset}) {
- final cs = assertSuggest(name,
- relevance: relevance, importUri: importUri, elemOffset: elemOffset);
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.CONSTRUCTOR));
- final index = name.indexOf('.');
- expect(element.name, index >= 0 ? name.substring(index + 1) : '');
- return cs;
- }
-
- CompletionSuggestion assertSuggestEnum(String completion,
- {bool isDeprecated: false}) {
- final suggestion = assertSuggest(completion, isDeprecated: isDeprecated);
- expect(suggestion.isDeprecated, isDeprecated);
- expect(suggestion.element.kind, protocol.ElementKind.ENUM);
- return suggestion;
- }
-
- CompletionSuggestion assertSuggestEnumConst(String completion,
- {int relevance: DART_RELEVANCE_DEFAULT, bool isDeprecated: false}) {
- final suggestion = assertSuggest(completion,
- relevance: relevance, isDeprecated: isDeprecated);
- expect(suggestion.completion, completion);
- expect(suggestion.isDeprecated, isDeprecated);
- expect(suggestion.element.kind, protocol.ElementKind.ENUM_CONSTANT);
- return suggestion;
- }
-
- CompletionSuggestion assertSuggestField(String name, String type,
- {int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- bool isDeprecated: false}) {
- final cs = assertSuggest(name,
- csKind: kind,
- relevance: relevance,
- importUri: importUri,
- elemKind: protocol.ElementKind.FIELD,
- isDeprecated: isDeprecated);
- // The returnType represents the type of a field
- expect(cs.returnType, type != null ? type : 'dynamic');
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.FIELD));
- expect(element.name, equals(name));
- expect(element.parameters, isNull);
- // The returnType represents the type of a field
- expect(element.returnType, type != null ? type : 'dynamic');
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestFunction(String name, String returnType,
- {CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- bool isDeprecated: false,
- int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- String elementName}) {
- final cs = assertSuggest(name,
- csKind: kind,
- relevance: relevance,
- importUri: importUri,
- isDeprecated: isDeprecated);
- if (returnType != null) {
- expect(cs.returnType, returnType);
- } else if (isNullExpectedReturnTypeConsideredDynamic) {
- expect(cs.returnType, 'dynamic');
- }
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.FUNCTION));
- expect(element.name, equals(elementName ?? name));
- expect(element.isDeprecated, equals(isDeprecated));
- final param = element.parameters;
- expect(param, isNotNull);
- expect(param[0], equals('('));
- expect(param[param.length - 1], equals(')'));
- if (returnType != null) {
- expect(element.returnType, returnType);
- } else if (isNullExpectedReturnTypeConsideredDynamic) {
- expect(element.returnType, 'dynamic');
- }
- assertHasParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestFunctionTypeAlias(
- String name, String returnType,
- {bool isDeprecated: false,
- int relevance: DART_RELEVANCE_DEFAULT,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- String importUri}) {
- final cs = assertSuggest(name,
- csKind: kind,
- relevance: relevance,
- importUri: importUri,
- isDeprecated: isDeprecated);
- if (returnType != null) {
- expect(cs.returnType, returnType);
- } else if (isNullExpectedReturnTypeConsideredDynamic) {
- expect(cs.returnType, 'dynamic');
- } else {
- expect(cs.returnType, isNull);
- }
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.FUNCTION_TYPE_ALIAS));
- expect(element.name, equals(name));
- expect(element.isDeprecated, equals(isDeprecated));
- // TODO (danrubel) Determine why params are null
- // final param = element.parameters;
- // expect(param, isNotNull);
- // expect(param[0], equals('('));
- // expect(param[param.length - 1], equals(')'));
- expect(element.returnType,
- equals(returnType != null ? returnType : 'dynamic'));
- // TODO (danrubel) Determine why param info is missing
- // assertHasParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestGetter(String name, String returnType,
- {int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- bool isDeprecated: false,
- String elementName}) {
- final cs = assertSuggest(name,
- csKind: kind,
- relevance: relevance,
- importUri: importUri,
- elemKind: protocol.ElementKind.GETTER,
- isDeprecated: isDeprecated);
- expect(cs.returnType, returnType != null ? returnType : 'dynamic');
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.GETTER));
- expect(element.name, equals(elementName ?? name));
- expect(element.parameters, isNull);
- expect(element.returnType,
- equals(returnType != null ? returnType : 'dynamic'));
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestLabel(String name,
- {int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- String returnType: 'dynamic'}) {
- final cs = assertSuggest(name,
- csKind: kind,
- relevance: relevance,
- importUri: importUri,
- elemKind: protocol.ElementKind.LABEL);
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.LABEL));
- expect(element.name, equals(name));
- if (element.returnType != null) {
- expect(element.returnType, returnType);
- }
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestLibrary(String name,
- {int relevance: DART_RELEVANCE_DEFAULT}) {
- final cs = assertSuggest(name,
- csKind: CompletionSuggestionKind.IDENTIFIER, relevance: relevance);
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.LIBRARY));
- expect(element.parameters, isNull);
- expect(element.returnType, isNull);
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestLocalVar(String name, String returnType,
- {int relevance: DART_RELEVANCE_LOCAL_VARIABLE,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- String importUri}) {
- final cs = assertSuggest(name,
- csKind: kind, relevance: relevance, importUri: importUri);
- if (returnType != null) {
- expect(cs.returnType, returnType);
- } else if (isNullExpectedReturnTypeConsideredDynamic) {
- expect(cs.returnType, 'dynamic');
- }
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.LOCAL_VARIABLE));
- expect(element.name, equals(name));
- expect(element.parameters, isNull);
- if (returnType != null) {
- expect(element.returnType, returnType);
- } else if (isNullExpectedReturnTypeConsideredDynamic) {
- expect(element.returnType, 'dynamic');
- }
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestMethod(
- String name, String declaringType, String returnType,
- {int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- bool isDeprecated: false}) {
- final cs = assertSuggest(name,
- csKind: kind,
- relevance: relevance,
- importUri: importUri,
- isDeprecated: isDeprecated);
- expect(cs.declaringType, equals(declaringType));
- expect(cs.returnType, returnType != null ? returnType : 'dynamic');
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.METHOD));
- expect(element.name, equals(name));
- final param = element.parameters;
- expect(param, isNotNull);
- expect(param[0], equals('('));
- expect(param[param.length - 1], equals(')'));
- expect(element.returnType, returnType != null ? returnType : 'dynamic');
- assertHasParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestName(String name,
- {int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- CompletionSuggestionKind kind: CompletionSuggestionKind.IDENTIFIER,
- bool isDeprecated: false}) {
- final cs = assertSuggest(name,
- csKind: kind,
- relevance: relevance,
- importUri: importUri,
- isDeprecated: isDeprecated);
- expect(cs.completion, equals(name));
- expect(cs.element, isNull);
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestSetter(String name,
- {int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- String returnType: 'dynamic'}) {
- final cs = assertSuggest(name,
- csKind: kind,
- relevance: relevance,
- importUri: importUri,
- elemKind: protocol.ElementKind.SETTER);
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.SETTER));
- expect(element.name, equals(name));
- // TODO (danrubel) assert setter param
- //expect(element.parameters, isNull);
- // TODO (danrubel) it would be better if this was always null
- if (element.returnType != null) {
- expect(element.returnType, returnType);
- }
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestStar(String name,
- {int relevance: DART_RELEVANCE_DEFAULT,
- CompletionSuggestionKind kind: CompletionSuggestionKind.IDENTIFIER}) {
- final cs = assertSuggest(name, csKind: kind, relevance: relevance);
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.CLASS));
- expect(element.name, equals(name));
- expect(element.parameters, isNull);
- expect(element.returnType, isNull);
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestTemplateInput(String name,
- {String elementName,
- int relevance: DART_RELEVANCE_DEFAULT,
- String importUri,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION}) {
- final cs = assertSuggest(name,
- csKind: kind,
- relevance: relevance,
- importUri: importUri,
- elemKind: protocol.ElementKind.SETTER);
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.SETTER));
- expect(element.name, equals(elementName));
- if (element.returnType != null) {
- expect(element.returnType, 'dynamic');
- }
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- CompletionSuggestion assertSuggestTopLevelVar(String name, String returnType,
- {int relevance: DART_RELEVANCE_DEFAULT,
- CompletionSuggestionKind kind: CompletionSuggestionKind.INVOCATION,
- String importUri}) {
- final cs = assertSuggest(name,
- csKind: kind, relevance: relevance, importUri: importUri);
- if (returnType != null) {
- expect(cs.returnType, returnType);
- } else if (isNullExpectedReturnTypeConsideredDynamic) {
- expect(cs.returnType, 'dynamic');
- }
- final element = cs.element;
- expect(element, isNotNull);
- expect(element.kind, equals(protocol.ElementKind.TOP_LEVEL_VARIABLE));
- expect(element.name, equals(name));
- expect(element.parameters, isNull);
- if (returnType != null) {
- expect(element.returnType, returnType);
- } else if (isNullExpectedReturnTypeConsideredDynamic) {
- expect(element.returnType, 'dynamic');
- }
- assertHasNoParameterInfo(cs);
- return cs;
- }
-
- Future computeSuggestions([int times = 200]);
-
- void failedCompletion(String message,
- [Iterable<CompletionSuggestion> completions]) {
- final sb = new StringBuffer(message);
- if (completions != null) {
- sb.write('\n found');
- completions.toList()
- ..sort(suggestionComparator)
- ..forEach((final suggestion) {
- sb.write('\n ${suggestion.completion} -> $suggestion');
- });
- }
- fail(sb.toString());
- }
-
- CompletionSuggestion getSuggest(
- {String completion,
- CompletionSuggestionKind csKind,
- protocol.ElementKind elemKind}) {
- CompletionSuggestion cs;
- if (suggestions != null) {
- suggestions.forEach((s) {
- if (completion != null && completion != s.completion) {
- return;
- }
- if (csKind != null && csKind != s.kind) {
- return;
- }
- if (elemKind != null) {
- final element = s.element;
- if (element == null || elemKind != element.kind) {
- return;
- }
- }
- if (cs == null) {
- cs = s;
- } else {
- failedCompletion('expected exactly one $cs',
- suggestions.where((s) => s.completion == completion));
- }
- });
- }
- return cs;
- }
-}
diff --git a/angular_analyzer_plugin/test/element_assert.dart b/angular_analyzer_plugin/test/element_assert.dart
deleted file mode 100644
index cdaee07..0000000
--- a/angular_analyzer_plugin/test/element_assert.dart
+++ /dev/null
@@ -1,165 +0,0 @@
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/ast.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-import 'package:test/test.dart';
-
-// ignore_for_file: deprecated_member_use
-
-class AngularElementAssert extends _AbstractElementAssert {
- final AngularElement element;
-
- AngularElementAssert(this.element, Source source) : super(source);
-
- AngularElementAssert get inCoreHtml {
- _inCoreHtml(element.source);
- return this;
- }
-
- AngularElementAssert at(String search) {
- _at(element.nameOffset, search);
- return this;
- }
-
- AngularElementAssert inFileName(String expectedName) {
- expect(element.source.fullName, endsWith(expectedName));
- _source = element.source;
- _code = null;
- return this;
- }
-
- AngularElementAssert name(String expectedName) {
- expect(element.name, expectedName);
- return this;
- }
-}
-
-class DartElementAssert extends _AbstractElementAssert {
- final Element element;
-
- DartElementAssert(this.element, Source source, String code)
- : super(source, code);
-
- DartElementAssert get getter {
- expect(element.kind, ElementKind.GETTER);
- return this;
- }
-
- DartElementAssert get inCoreHtml {
- _inCoreHtml(element.source);
- return this;
- }
-
- DartElementAssert get method {
- expect(element.kind, ElementKind.METHOD);
- return this;
- }
-
- DartElementAssert get prefix {
- expect(element.kind, ElementKind.PREFIX);
- return this;
- }
-
- DartElementAssert at(String search) {
- _at(element.nameOffset, search);
- return this;
- }
-
- DartElementAssert inFile(String path) {
- _inFile(element.source, path);
- return this;
- }
-}
-
-class ElementAssert {
- final String _dartCode;
- final Source _dartSource;
- final String _htmlCode;
- final Source _htmlSource;
- final AngularElement element;
- final int _referenceOffset;
-
- ElementAssert(this._dartCode, this._dartSource, this._htmlCode,
- this._htmlSource, this.element, this._referenceOffset);
-
- AngularElementAssert get angular {
- expect(element, const isInstanceOf<AngularElement>());
- return new AngularElementAssert(element, _dartSource);
- }
-
- DartElementAssert get dart {
- expect(element, const isInstanceOf<DartElement>());
- final dartElement = element as DartElement;
- return new DartElementAssert(dartElement.element, _dartSource, _dartCode);
- }
-
- AngularElementAssert get input {
- expect(element, const isInstanceOf<InputElement>());
- return new AngularElementAssert(element, _dartSource);
- }
-
- LocalVariableAssert get local {
- expect(element, const isInstanceOf<LocalVariable>());
- return new LocalVariableAssert(
- element as LocalVariable, _referenceOffset, _htmlSource, _htmlCode);
- }
-
- AngularElementAssert get output {
- expect(element, const isInstanceOf<OutputElement>());
- return new AngularElementAssert(element, _dartSource);
- }
-
- AngularElementAssert get selector {
- expect(element, const isInstanceOf<SelectorName>());
- return new AngularElementAssert(element, _dartSource);
- }
-}
-
-class LocalVariableAssert extends _AbstractElementAssert {
- final LocalVariable variable;
- final int _referenceOffset;
-
- LocalVariableAssert(
- this.variable, this._referenceOffset, Source htmlSource, String htmlCode)
- : super(htmlSource, htmlCode);
-
- LocalVariableAssert get declaration {
- expect(variable.nameOffset, _referenceOffset);
- return this;
- }
-
- LocalVariableAssert at(String search) {
- _at(variable.nameOffset, search);
- return this;
- }
-
- LocalVariableAssert type(String expectedTypeName) {
- expect(variable.dartVariable.type.displayName, expectedTypeName);
- return this;
- }
-}
-
-class _AbstractElementAssert {
- Source _source;
- String _code;
-
- _AbstractElementAssert([this._source, this._code]);
-
- void _at(int actualOffset, String search) {
- _code ??= _source.contents.data;
- final offset = _code.indexOf(search);
- expect(offset, isNonNegative, reason: "|$search| in |$_code|");
- expect(actualOffset, offset);
- }
-
- void _inCoreHtml(Source actualSource) {
- _inFile(actualSource, '/sdk/lib/html/dartium/html_dartium.dart');
- }
-
- void _inFile(Source actualSource, String expectedPath) {
- expect(actualSource.fullName, expectedPath);
- _source = actualSource;
- _code = null;
- }
-}
diff --git a/angular_analyzer_plugin/test/file_tracker_test.dart b/angular_analyzer_plugin/test/file_tracker_test.dart
deleted file mode 100644
index 57967b9..0000000
--- a/angular_analyzer_plugin/test/file_tracker_test.dart
+++ /dev/null
@@ -1,422 +0,0 @@
-import 'package:analyzer/src/summary/api_signature.dart';
-import 'package:angular_analyzer_plugin/src/file_tracker.dart';
-import 'package:angular_analyzer_plugin/src/options.dart';
-import 'package:mockito/mockito.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(FileTrackerTest);
- });
-}
-
-@reflectiveTest
-class FileTrackerTest {
- FileTracker _fileTracker;
- _FileHasherMock _fileHasher;
- _AngularOptionsMock _options;
-
- void setUp() {
- _fileHasher = new _FileHasherMock();
- _options = new _AngularOptionsMock();
- _fileTracker = new FileTracker(_fileHasher, _options);
-
- when(_options.customTagNames).thenReturn(<String>[]);
- }
-
- // ignore: non_constant_identifier_names
- void test_dartHasTemplate() {
- _fileTracker.setDartHtmlTemplates("foo.dart", ["foo.html"]);
- expect(_fileTracker.getHtmlPathsReferencedByDart("foo.dart"),
- equals(["foo.html"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_dartHasTemplates() {
- _fileTracker.setDartHtmlTemplates("foo.dart", ["foo.html", "foo_bar.html"]);
- expect(_fileTracker.getHtmlPathsReferencedByDart("foo.dart"),
- equals(["foo.html", "foo_bar.html"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_dartSignature_includesCustomTagNames() async {
- _fileTracker.setDartHasTemplate("foo.dart", true);
-
- final fooDartElementSignature = '1';
- when(_fileHasher.getUnitElementSignature("foo.dart"))
- .thenAnswer((_) async => fooDartElementSignature);
- when(_options.customTagNames).thenReturn(['foo', 'bar']);
- when(_options.customEventsHashString).thenReturn('');
-
- final expectedSignature = new ApiSignature()
- ..addInt(FileTracker.salt)
- ..addString(fooDartElementSignature)
- ..addString('t:foo')
- ..addString('t:bar');
-
- expect((await _fileTracker.getDartSignature("foo.dart")).toHex(),
- equals(expectedSignature.toHex()));
- }
-
- // ignore: non_constant_identifier_names
- void test_getContentHashIsSalted() {
- final fooHtmlSignature = new ApiSignature()..addInt(1);
- final expectedSignature = new ApiSignature()
- ..addInt(FileTracker.salt)
- ..addBytes(fooHtmlSignature.toByteList());
- when(_fileHasher.getContentHash("foo.html")).thenReturn(fooHtmlSignature);
- expect(_fileTracker.getContentSignature("foo.html").toHex(),
- equals(expectedSignature.toHex()));
- }
-
- // ignore: non_constant_identifier_names
- void test_getUnitElementSignatureIsSalted() async {
- final fooDartElementSignature = '1';
- final expectedSignature = new ApiSignature()
- ..addInt(FileTracker.salt)
- ..addString(fooDartElementSignature);
- when(_fileHasher.getUnitElementSignature("foo.dart"))
- .thenAnswer((_) async => fooDartElementSignature);
- expect((await _fileTracker.getUnitElementSignature("foo.dart")).toHex(),
- equals(expectedSignature.toHex()));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlAffectingDart() {
- _fileTracker
- ..setDartHasTemplate("foo.dart", true)
- ..setDartImports("foo.dart", ["bar.dart"])
- ..setDartHtmlTemplates("bar.dart", ["bar.html"]);
- expect(_fileTracker.getHtmlPathsAffectingDart("foo.dart"),
- equals(["bar.html"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlAffectingDartEmpty() {
- expect(_fileTracker.getHtmlPathsAffectingDart("foo.dart"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlAffectingDartEmptyNoImportedDart() {
- _fileTracker.setDartHtmlTemplates("foo.dart", ["foo.html"]);
- expect(_fileTracker.getHtmlPathsAffectingDart("foo.dart"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlAffectingDartEmptyNotDartTemplate() {
- _fileTracker
- ..setDartImports("foo.dart", ["bar.dart"])
- ..setDartHtmlTemplates("bar.dart", ["bar.html"]);
- expect(_fileTracker.getHtmlPathsAffectingDart("foo.dart"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasDart() {
- _fileTracker
- ..setDartHasTemplate("foo.dart", true)
- ..setDartImports("foo.dart", ["bar.dart"])
- ..setDartHtmlTemplates("bar.dart", ["bar.html"]);
- expect(_fileTracker.getDartPathsAffectedByHtml("bar.html"),
- equals(["foo.dart"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasDartEmpty() {
- expect(_fileTracker.getDartPathsAffectedByHtml("foo.html"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasDartEmptyNoImportedDart() {
- _fileTracker.setDartHtmlTemplates("foo.dart", ["foo.html"]);
- expect(_fileTracker.getDartPathsAffectedByHtml("foo.html"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasDartEmptyNotDartTemplate() {
- _fileTracker
- ..setDartImports("foo.dart", ["bar.dart"])
- ..setDartHtmlTemplates("bar.dart", ["bar.html"]);
- expect(_fileTracker.getDartPathsAffectedByHtml("bar.html"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasDartGetSignature() async {
- _fileTracker
- ..setDartHasTemplate("foo.dart", true)
- ..setDartImports("foo.dart", ["bar.dart"])
- ..setDartHtmlTemplates("bar.dart", ["bar.html"]);
-
- final fooDartElementSignature = '1';
- final barHtmlSignature = new ApiSignature()..addInt(2);
-
- when(_fileHasher.getContentHash("bar.html")).thenReturn(barHtmlSignature);
- when(_fileHasher.getUnitElementSignature("foo.dart"))
- .thenAnswer((_) async => fooDartElementSignature);
- when(_options.customEventsHashString).thenReturn('');
-
- final expectedSignature = new ApiSignature()
- ..addInt(FileTracker.salt)
- ..addString(fooDartElementSignature)
- ..addBytes(barHtmlSignature.toByteList());
-
- expect((await _fileTracker.getDartSignature("foo.dart")).toHex(),
- equals(expectedSignature.toHex()));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasDartMultiple() {
- _fileTracker
- ..setDartHasTemplate("foo.dart", true)
- ..setDartImports("foo.dart", ["bar.dart", "baz.dart"])
- ..setDartHtmlTemplates("bar.dart", ["bar.html", "bar_b.html"])
- ..setDartHtmlTemplates("baz.dart", ["baz.html", "baz_b.html"]);
- expect(_fileTracker.getDartPathsAffectedByHtml("bar.html"),
- equals(["foo.dart"]));
- expect(_fileTracker.getDartPathsAffectedByHtml("bar_b.html"),
- equals(["foo.dart"]));
- expect(_fileTracker.getDartPathsAffectedByHtml("baz.html"),
- equals(["foo.dart"]));
- expect(_fileTracker.getDartPathsAffectedByHtml("baz_b.html"),
- equals(["foo.dart"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasDartNotGrandchildren() {
- _fileTracker
- ..setDartHasTemplate("foo.dart", true)
- ..setDartImports("foo.dart", ["child.dart"])
- ..setDartHtmlTemplates("child.dart", ["child.html"])
- ..setDartImports("child.dart", ["grandchild.dart"])
- ..setDartHtmlTemplates("grandchild.dart", ["grandchild.html"]);
- expect(_fileTracker.getDartPathsAffectedByHtml("child.html"),
- equals(["foo.dart"]));
- expect(
- _fileTracker.getDartPathsAffectedByHtml("grandchild.html"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasHtml() {
- _fileTracker
- ..setDartHtmlTemplates("foo.dart", ["foo.html"])
- ..setDartImports("foo.dart", ["bar.dart"])
- ..setDartHtmlTemplates("bar.dart", ["bar.html"]);
- expect(_fileTracker.getHtmlPathsReferencingHtml("bar.html"),
- equals(["foo.html"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasHtmlButNotGrandchildren() {
- _fileTracker
- ..setDartHtmlTemplates("foo.dart", ["foo.html"])
- ..setDartImports("foo.dart", ["child.dart"])
- ..setDartHtmlTemplates("child.dart", ["child.html"])
- ..setDartImports("child.dart", ["grandchild.dart"])
- ..setDartHtmlTemplates("grandchild.dart", ["grandchild.html"]);
- expect(_fileTracker.getHtmlPathsReferencingHtml("child.html"),
- equals(["foo.html"]));
- expect(_fileTracker.getHtmlPathsReferencingHtml("grandchild.html"),
- equals(["child.html"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasHtmlEmpty() {
- expect(_fileTracker.getHtmlPathsReferencingHtml("foo.html"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasHtmlEmptyNoHtml() {
- _fileTracker
- ..setDartHtmlTemplates("foo.dart", [])
- ..setDartImports("foo.dart", ["bar.dart"])
- ..setDartHtmlTemplates("bar.dart", ["bar.html"]);
- expect(_fileTracker.getHtmlPathsReferencingHtml("bar.html"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasHtmlEmptyNoImportedDart() {
- _fileTracker.setDartHtmlTemplates("foo.dart", ["foo.html"]);
- expect(_fileTracker.getHtmlPathsReferencingHtml("foo.html"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasHtmlGetSignature() async {
- _fileTracker
- ..setDartHtmlTemplates("foo.dart", ["foo.html"])
- ..setDartHtmlTemplates("foo_test.dart", ["foo.html"])
- ..setDartImports("foo.dart", ["bar.dart"])
- ..setDartHtmlTemplates("bar.dart", ["bar.html"]);
-
- final fooHtmlSignature = new ApiSignature()..addInt(1);
- final fooDartElementSignature = '2';
- final fooTestDartElementSignature = '3';
- final barHtmlSignature = new ApiSignature()..addInt(4);
-
- when(_fileHasher.getContentHash("foo.html")).thenReturn(fooHtmlSignature);
- when(_fileHasher.getContentHash("bar.html")).thenReturn(barHtmlSignature);
- when(_fileHasher.getUnitElementSignature("foo.dart"))
- .thenAnswer((_) async => fooDartElementSignature);
- when(_fileHasher.getUnitElementSignature("foo_test.dart"))
- .thenAnswer((_) async => fooTestDartElementSignature);
- when(_options.customEventsHashString).thenReturn('');
-
- final expectedSignature = new ApiSignature()
- ..addInt(FileTracker.salt)
- ..addBytes(fooHtmlSignature.toByteList())
- ..addString(fooDartElementSignature)
- ..addBytes(barHtmlSignature.toByteList())
- ..addString(fooTestDartElementSignature);
-
- expect((await _fileTracker.getHtmlSignature("foo.html")).toHex(),
- equals(expectedSignature.toHex()));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlHasHtmlMultipleResults() {
- _fileTracker
- ..setDartHtmlTemplates("foo.dart", ["foo.html", "foo_b.html"])
- ..setDartImports("foo.dart", ["bar.dart", "baz.dart"])
- ..setDartHtmlTemplates("bar.dart", ["bar.html"])
- ..setDartHtmlTemplates("baz.dart", ["baz.html", "baz_b.html"]);
- expect(_fileTracker.getHtmlPathsReferencingHtml("bar.html"),
- equals(["foo.html", "foo_b.html"]));
- expect(_fileTracker.getHtmlPathsReferencingHtml("baz.html"),
- equals(["foo.html", "foo_b.html"]));
- expect(_fileTracker.getHtmlPathsReferencingHtml("baz_b.html"),
- equals(["foo.html", "foo_b.html"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_htmlSignature_includesCustomEvents() async {
- _fileTracker.setDartHtmlTemplates("foo.dart", ["foo.html"]);
-
- final fooHtmlSignature = new ApiSignature()..addInt(1);
- final fooDartElementSignature = '2';
-
- when(_fileHasher.getContentHash("foo.html")).thenReturn(fooHtmlSignature);
- when(_fileHasher.getUnitElementSignature("foo.dart"))
- .thenAnswer((_) async => fooDartElementSignature);
-
- final expectedSignature = new ApiSignature()
- ..addInt(FileTracker.salt)
- ..addBytes(fooHtmlSignature.toByteList())
- ..addString(fooDartElementSignature)
- ..addString(r'$customEvents');
-
- when(_options.customEventsHashString).thenReturn(r'$customEvents');
-
- expect((await _fileTracker.getHtmlSignature("foo.html")).toHex(),
- equals(expectedSignature.toHex()));
- }
-
- // ignore: non_constant_identifier_names
- void test_minimallyRehashesHtml() {
- final fooHtmlSignature = new ApiSignature()..addInt(1);
- when(_fileHasher.getContentHash("foo.html")).thenReturn(fooHtmlSignature);
-
- for (var i = 0; i < 3; ++i) {
- _fileTracker.getContentSignature("foo.html");
- }
- verify(_fileHasher.getContentHash("foo.html")).called(1);
-
- _fileTracker.rehashContents("foo.html");
-
- for (var i = 0; i < 3; ++i) {
- _fileTracker.getContentSignature("foo.html");
- }
- verify(_fileHasher.getContentHash("foo.html")).called(1);
- }
-
- // ignore: non_constant_identifier_names
- void test_notReferencedDart() {
- expect(_fileTracker.getDartPathsReferencingHtml("foo.html"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_notReferencedHtml() {
- expect(_fileTracker.getDartPathsReferencingHtml("foo.dart"), equals([]));
- }
-
- // ignore: non_constant_identifier_names
- void test_templateHasDart() {
- _fileTracker.setDartHtmlTemplates("foo.dart", ["foo.html"]);
- expect(_fileTracker.getDartPathsReferencingHtml("foo.html"),
- equals(["foo.dart"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_templatesHaveDart() {
- _fileTracker
- ..setDartHtmlTemplates("foo.dart", ["foo.html"])
- ..setDartHtmlTemplates("foo_test.dart", ["foo.html"]);
- expect(_fileTracker.getDartPathsReferencingHtml("foo.html"),
- equals(["foo.dart", "foo_test.dart"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_templatesHaveDartComplex() {
- _fileTracker
- ..setDartHtmlTemplates("foo.dart", ["foo.html", "foo_b.html"])
- ..setDartHtmlTemplates("foo_test.dart", ["foo.html", "foo_b.html"])
- ..setDartHtmlTemplates("unrelated.dart", ["unrelated.html"]);
- expect(_fileTracker.getDartPathsReferencingHtml("foo.html"),
- equals(["foo.dart", "foo_test.dart"]));
- expect(_fileTracker.getDartPathsReferencingHtml("foo_b.html"),
- equals(["foo.dart", "foo_test.dart"]));
-
- _fileTracker.setDartHtmlTemplates("foo_test.dart", ["foo_b.html"]);
- expect(_fileTracker.getDartPathsReferencingHtml("foo.html"),
- equals(["foo.dart"]));
- expect(_fileTracker.getDartPathsReferencingHtml("foo_b.html"),
- equals(["foo.dart", "foo_test.dart"]));
-
- _fileTracker.setDartHtmlTemplates("foo_test.dart", ["foo.html"]);
- expect(_fileTracker.getDartPathsReferencingHtml("foo.html"),
- equals(["foo.dart", "foo_test.dart"]));
- expect(_fileTracker.getDartPathsReferencingHtml("foo_b.html"),
- equals(["foo.dart"]));
-
- _fileTracker
- .setDartHtmlTemplates("foo_test.dart", ["foo.html", "foo_test.html"]);
- expect(_fileTracker.getDartPathsReferencingHtml("foo.html"),
- equals(["foo.dart", "foo_test.dart"]));
- expect(_fileTracker.getDartPathsReferencingHtml("foo_b.html"),
- equals(["foo.dart"]));
- expect(_fileTracker.getDartPathsReferencingHtml("foo_test.html"),
- equals(["foo_test.dart"]));
-
- _fileTracker
- ..setDartHtmlTemplates("foo.dart", ["foo.html"])
- ..setDartHtmlTemplates("foo_b.dart", ["foo_b.html"]);
- expect(_fileTracker.getDartPathsReferencingHtml("foo.html"),
- equals(["foo.dart", "foo_test.dart"]));
- expect(_fileTracker.getDartPathsReferencingHtml("foo_b.html"),
- equals(["foo_b.dart"]));
- expect(_fileTracker.getDartPathsReferencingHtml("foo_test.html"),
- equals(["foo_test.dart"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_templatesHaveDartRemove() {
- _fileTracker
- ..setDartHtmlTemplates("foo_test.dart", ["foo.html"])
- ..setDartHtmlTemplates("foo.dart", ["foo.html"])
- ..setDartHtmlTemplates("foo_test.dart", []);
- expect(_fileTracker.getDartPathsReferencingHtml("foo.html"),
- equals(["foo.dart"]));
- }
-
- // ignore: non_constant_identifier_names
- void test_templatesHaveDartRepeated() {
- _fileTracker
- ..setDartHtmlTemplates("foo.dart", ["foo.html"])
- ..setDartHtmlTemplates("foo_test.dart", ["foo.html"])
- ..setDartHtmlTemplates("foo.dart", ["foo.html"]);
- expect(_fileTracker.getDartPathsReferencingHtml("foo.html"),
- equals(["foo.dart", "foo_test.dart"]));
- }
-}
-
-class _AngularOptionsMock extends Mock implements AngularOptions {}
-
-class _FileHasherMock extends Mock implements FileHasher {}
diff --git a/angular_analyzer_plugin/test/fuzz_test.dart b/angular_analyzer_plugin/test/fuzz_test.dart
deleted file mode 100644
index c8918e5..0000000
--- a/angular_analyzer_plugin/test/fuzz_test.dart
+++ /dev/null
@@ -1,652 +0,0 @@
-import 'dart:async';
-import 'dart:math';
-
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:test/test.dart';
-
-import 'abstract_angular.dart';
-
-//main() {
-// defineReflectiveSuite(() {
-// defineReflectiveTests(FuzzTest);
-// });
-//}
-
-void main() {
- new FuzzTest().test_fuzz_continually();
-}
-
-//@reflectiveTest
-typedef String FuzzModification(String input);
-
-class FuzzTest extends AbstractAngularTest {
- // collected with
- // `find ../deps -name '*.dart' -exec cat {} \; | shuf -n 500 | sort`
- // and cleaned up by hand
- static const String dartSnippets = r'''
-}
-]),
-});
-{
-\'\'\');
- '090cedb3f2833a3f260b0937baae56267a6cd935',
- -4.5035996273704955E15, -4.294967296000001E9, -4.294967296E9, -4.2949672959999995E9, -6031769.5,
- [[549755813990, -1],
- "57,646,075,230,342%"
- 6,
-,[6026.423842661978,5821.897768214317]
- addCodeUnitEscaped(buffer, $LS); // 0x2028.
- ..add(doKeyword)
- afterLineBreak = true;
-args3(a, b, c) {}
- _argumentsAsJson(_arguments));
- assert(context != null);
- assertHasResult(SearchResultKind.WRITE, 'test = 1;');
- _assertInvalid(a, LIBRARY_ERRORS_READY);
- assertNotSuggested('F1');
- assertNull(res[650].firstMatch("** Failers"), 1648);
- assertOpType(returnValue: true, typeNames: true);
- _assertTrue("{ while (true) { x: do { continue x; } while (true); } }");
- _assertUnlinkedConst(variable.initializer.bodyExpr,
- _assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- AstFactory.mapLiteralEntry("b", AstFactory.identifier3("b")),
- ast.NodeList arguments, CallStructure callStructure, _) {
- AstNode node = request.target.containingNode;
- await computeSuggestions();
- await r1Ref.reload();
- _Base64DecoderSink(this._sink);
- baseSegments = [];
- B.mb();
- bool remove(Object o) => _validKey(o) ? super.remove(o) : false;
- break;
- 'C');
- } catch (e) {
- checkFile(build(
-class A {
-class ChM{}
- ClassElement classB = ElementFactory.classElement("B", classA.type);
- ClassElementImpl classB = ElementFactory.classElement2("B", ["F"]);
-class Getter_NodeReplacerTest_test_classTypeAlias
-class Malbounded1 implements Super<String> {} /// static type warning
- c = m.shuffle(Float32x4.WZYY);
- CompilationUnit unit = resolveCompilationUnit(source, library);
- compilePolyfillAndValidate(input, generatedPolyfill);
- Compiler compiler = result.compiler;
- }, (completer) => completer.completeError('oh no'));
- const CommentType(this.name);
- const ErrorProperty<List<FieldElement>>('NOT_INITIALIZED_FIELDS', 0);
- const _MockSdkFile(this.path, this.content);
- const Pair(Namespaces.html, "font"),
- const Symbol('zm'),
- const Visit(VisitKind.VISIT_REDIRECTING_FACTORY_CONSTRUCTOR_DECL,
- context.resolveCompilationUnit2(librarySource, librarySource);
- : counters = const {Metric.functions: 1},
- csKind: CompletionSuggestionKind.IMPORT);
- DartObjectImpl integerDivide(BinaryExpression node,
- 'd': 'd', // DAY
- debug('');
- defineReflectiveTests(AnalysisDriverSchedulerTest);
- document.body.append(outerElement);
- @DomName('WebGLRenderingContext.MIRRORED_REPEAT')
- Element.keyDownEvent.forTarget(_target, useCapture: true).listen(
- element.name == '[]=';
- } else {
- } else if (offset >= JS('int', '#.length', keys)) {
- _emit("print", {
- Encoding encoding;
- env.liveInstructions.forEach((HInstruction instruction, int id) {
- equals('http://dartlang.org/thing.dart 5:10'));
- "error after the listened stream completes", () {
- execRE(re, "y", ["y"]);
- expect(
- expect(() {
- expect(entry.getState(result), CacheState.INVALID);
- Expect.equals(0, IntFromN(NFromInt(0)));
- Expect.equals(1, C.getterInvocation);
- expectEqualSets(incNames.instantiatedNames, fullNames.instantiatedNames);
- Expect.equals(length, l.length);
- Expect.isFalse(map is LinkedHashMap<dynamic, int>);
- Expect.isTrue(count > 0);
- Expect.isTrue(null != 2147483647.hashCode);
- expect(iter.current, _isRune("b"));
- expect(label.name, labelName);
- Expect.listEquals(["map 1",
- expectMatchingErrors(() => classMirror.invoke(#foo, []),
- expect(new Int64(10) >= new Int64(9), true);
- expectNoValidationError((entrypoint) => new PubspecValidator(entrypoint));
- Expect.throws(() => myIterable.elementAt(0), (e) => e is RangeError);
- expect(typeSystem.isSubtypeOf(type1, type2), false);
- expect(view(elements.classes),
- fieldsToBold.add(field.name);
- File file = package.folder.getChildAssumingFile(fileName);
- FINAL,
- final num x;
- FIRSTWEEKCUTOFFDAY: 3),
- Folder folder;
- foo();
-foo3() async { await fut(); }
- format._multiplier = _PERCENT_SCALE;
- f_string();
- _futureOrPrefetch = new AsyncError(error, stackTrace);
- group('excluded', () {
- _hasTimer(_FakeTimer timer) => _timers.contains(timer);
- height: 300px;
- "hellip;",
- _hi ^= high;
- 'Hms': 'HH:mm:ss', // HOUR24_MINUTE_SECOND
- "HtmlEntry.PARSE_ERRORS", AnalysisError.NO_ERRORS);
- if (count++ > 0) {
- if (dartProxy == null || !_isLocalObject(o)) {
- if (_documentationComment != null) {
- if (entry.isEmpty) {
- if (event.kind == ServiceEvent.kPauseBreakpoint) {
- if (!fs._ensureUnknownFields().mergeFieldFromBuffer(tag, input)) {
- if (function.isPublic) {
- if (json == null) {
- if (mainScript == null) {
- if (message == null) return "is not true.";
- IFrameElement x = e.querySelector('iframe');
- if (s == "CSSFontFaceRule") return BlinkCSSFontFaceRule.instance;
- if (_subscription != null) _subscription.cancel();
- if (superName != null) {
- if (targetUnit == _lastOutputUnit) return _lastLibrariesMap;
- if (trimmedLine.startsWith('Observatory listening on ')) {
- if (type == null) return false;
- if (value is num) return value;
- if (value is String) {
- if (x == 0) {
- (i) => i < _dimPrefixLength ? oldDimToInt[i] : new Map<dynamic, int>());
- img.src = url;
-import 'a.dart';
-import 'dart:async';
-import '../../descriptor.dart' as d;
- ImportElement,
-import 'sub folder/lib.dart';
- int count = 0;
- InterfaceType typeA = classA.type;
- int getWidth(int viewLength);
- js.Expression initializeLoadedHunkFunction = js.js(
- Keyword keyword, TypeName type, String parameterName) =>
- l[0] = lSmall;
- 'language/first_class_types_literals_test_08_multi',
-library engine.source;
- listener.setLineInfo(new TestSource(), scanner.lineStarts);
- List<MirrorUsage> usages = mirrorsUsedOnLibraryTag(library, import);
- List output_words = configurations.length > 1
- localsHandler,
- log.add('a');
- m(A a) {}
-main() {
-main(p) {
- (map) => map.remove('a'))));
- measureText_Callback_0_(mthis) => Blink_JsNative_DomException.callMethod(mthis /* CanvasRenderingContext2D */, "measureText", []);
- _metadata = metadata;
- methods.add(sb.toString());
-native "*Window" /// 28: compile-time error
- new C().test('dynamic', true);
- [new TransformerGroup([
- node, new VariableConstantExpression(element),
- onclick_Setter_(mthis, __arg_0) => Blink_JsNative_DomException.setProperty(mthis /* GlobalEventHandlers */, "onclick", __arg_0);
- } on TestException catch (e) {}
- @override
- parser.addOption("dart2js-args",
- 'pkgB': [provider.getResource('/pkgB/lib/')]
- print(await Isolate.resolvePackageUri(
- properties['propagated type'] = node.propagatedType;
- provider.sourcesWithResults.add(source2);
- reportErrorForOffset(errorCode, token.offset, token.length, arguments);
- Request _createGetErrorsRequest(String file) {
- _resolver.nameScope.shouldIgnoreUndefined(superclassName)) {
- return;
- Return _clone() => new Return(value);
- return copy;
- // returned out of the TestTypeProvider don't have a mock 'dart.core'
- return expect42(f());
- return hash;
- return null;
- return receiver.isStable &&
- return segments.toString();
- Set<String> todoFiles =
- shouldBeEqualToString(test3.style.overflowX, "overlay");
- shouldBe(imported.text, 'hello world');
- shouldBe(regex11.firstMatch("baaabac"), ["aba", "a"]);
- shouldBe(style.backgroundPosition, '50% 50%, left 0% bottom 20px');
- _SourcePattern _getSourcePattern(SourceRange range) {
- Source source = addSource(r\'\'\'
- 's': 's', // SECOND
- STANDALONEWEEKDAYS: const [
- start = i + 1;
- .startsWith("package:rasta/")) {
- .statement('# = #(#, $arity)', [name, closureConverter, name]));
- static const EventStreamProvider<Event> pauseEvent = const EventStreamProvider<Event>('pause');
- static const int RESERVED_3 = 3;
- static const int YXXX = 0x1;
- static const String COMPLETE = "complete";
- static int does_something() {
- static toto() => 666;
- [StaticTypeWarningCode.UNDEFINED_METHOD]);
- static void testMain() {
- storage.map.remove(_findBundleForSource(bundles, aSource).id);
- String get logicalHeight =>
- String parameterSource =
- String prefix = utils.getNodePrefix(statement);
- String toString() => "OpenSpan($start, \$$cost)";
-switchTest(value) {
- test((){
- test1("child2", "-webkit-column-count", "auto");
- test('builds the correct URL with state', () {
- test("dot directories are ignored", () {
- testDynamic();
- test("initializerArrowExpression", () {
- test_perform() {
- test_PrefixedIdentifier_trailingStmt_field() async {
- .then((_) => FutureExpect.isFalse(FileSystemEntity.isLink(target)))
- try {
-typedef A();
- unsorted.sort(compare);
- usedElement = prefixed.staticElement;
- validateMethodName("2newName"), RefactoringProblemSeverity.FATAL,
- 'validateModifiersForField_1': new MethodTrampoline(
- var bundle1 = createPackageBundle(
- var foo2 = lib2.find("foo2");
- var obj = new Uint32List(0);
- var p2 = document.getElementById('p2');
- var zGood = 9223372036854775807;
- verify([source]);
- visitor.visitExpressionFunctionBody(this);
- void allDone() {}
- void b() {
- void fire(var event) {
- void f(x) {}
- void mergeDiamondFlow(FieldInitializationScope<T> thenScope,
- void test_binary_equal_string() {
- void test_getReturnType() {
- void test_nonAbstractClassInheritsAbstractMemberOne_getter_fromInterface() {
- void uniform2fv(UniformLocation location, v) native;
- Windows1252Decoder(List<int> bytes, [int offset = 0, int length,
- x_Getter_(mthis) => Blink_JsNative_DomException.getProperty(mthis /* SVGPathSegLinetoHorizontalAbs */, "x");
- yield 42;
- YieldStatement stmt = body.block.statements[0];
- 'yMMM': 'MMM y', // YEAR_ABBR_MONTH
-''';
-
- // collected with
- // `find ~/ng-comps -name '*.html' -exec cat {} \; | shuf -n 150 | sort`
- // and cleaned up by hand
- static const String htmlSnippets = r'''
-<!--
--->
- aria-hidden="true"
- attr.aria-hidden="{{!invalid}}"
- [attr.aria-label]="closePanelMsg">
- [attr.aria-label]="scrollScorecardBarBack">
- attr.aria-valuemin="{{min}}"
- (blur)="inputBlurAction($event, inputEl.validity.valid, inputEl.validationMessage)"
- <br *ngFor="let value of heightForTextbox">
- (change)="inputChange(textareaEl.value, textareaEl.validity.valid, textareaEl.validationMessage);$event.stopPropagation()"
- [class.active]="activeTabIndex == idx"
- [class.animated]="underlineAnimated"></div>
- [class.bottom-scroll-stroke]="shouldShowBottomScrollStroke">
- class="btn btn-yes"
- [class.checked]="checked"
- [class.disable-header-expansion]="disableHeaderExpansion"
- [class.expand-more]="shouldFlipExpandIcon"
- [class.hide]="atScorecardBarEnd"
- [class.invisible]="disabled" [class.invalid]="invalid"></div>
- [class.invisible]="!focused" [class.invalid]="invalid"
- [class.invisible]="!labelVisible"
- [class.right-align]="rightAlign">
- class="textarea"
- [disabled]="disabled"
- [disabled]="yesDisabled || disabled"
- </div>
- <div>
-<div attr.aria-pressed="{{checked}}"
- <div class="active-progress"
- <div class="disabled-underline" [class.invisible]="!disabled">
- <div class="label" aria-hidden="true">
-<div class="spinner">
- <div class="tgl-lbl" *ngIf="hasLabel">{{label}}</div>
-<div (focus)="focusFirst()" tabindex="0"></div>
- <div *ngIf="maxCount != null && focused"
- <!-- Expanded section -->
- focusItem>
- </footer>
- </glyph>
- <glyph class="glyph leading"
-<h3>{{label}}<ng-content select="name"></ng-content></h3>
- </header>
- <header>
- <header buttonDecorator
- {{hintText}}
-<i [class.material-icons]="useMaterialIconsExtended"
- icon="chevron_right"
- icon="{{leadingGlyph}}"
- (input)="inputKeypress(textareaEl.value, textareaEl.validity.valid, textareaEl.validationMessage)"></textarea>
- {{label}}
- </main>
- </material-button>
- <material-button class="scroll-button scroll-left-button"
-<material-button #noButton
- </material-ripple>
-<material-ripple (mousedown)="onMouseDown($event)"
- <material-ripple *ngIf="!disabled"
-<material-ripple *ngIf="selectable"></material-ripple>
- <material-ripple [style.color]="rippleColor"
-</material-tab-strip>
- (mouseenter)="isHovered=true"
- <ng-content select="[header]"></ng-content>
- <ng-content select="[trailing]"></ng-content>
- <ng-content select="[value]"></ng-content>
- *ngIf="isScrollable">
- *ngIf="!pending && noDisplayed"
- *ngIf="shouldShowExpandIcon"
- *ngSwitchWhen="emptyState"
- <p class="primary-text">{{name}}</p>
- [pending]="activeSaveCancelAction"
- [raised]="yesRaised || raised"
- role="alert"
- </span>
-<span *ngIf="suggestionBefore != null" class="suggestion before">{{suggestionBefore}}</span>
- [style.transform]="secondaryTransform"></div>
- </tab-button>
- (tabChange)="onTabChange($event)"
- tabindex="-1"
- (trigger)="handleExpandIconClick()">
- (trigger)="yes.add($event)">
- (yes)="doSave()"
- [yesText]="saveText"
-''';
-
- static const String baseDart = r'''
-import 'package:angular2/angular2.dart';
-
-@Component(
- selector: 'my-aaa',
- templateUrl: 'test.html',
- directives: const [CounterComponent, NgIf, NgFor, NgForm, NgModel])
-class ComponentA {
- List<String> items;
- String header;
-}
-
-@Component(
- selector: 'my-counter',
- inputs: const ['count'],
- outputs: const ['resetEvent: reset'],
- template: '{{count}} <button (click)="increment()" [value]="\'add\'"></button>')
-class CounterComponent {
- int count;
- @Input() int maxCount;
- EventEmitter<String> resetEvent;
- @Output() EventEmitter<int> incremented;
-
- @ContentChild(CounterComponent)
- CounterComponent recursedComponent;
-
- void reset() {}
- void increment() {}
-}
-''';
-
- static const String baseHtml = r'''
-<!-- @ngIgnoreErrors: -->
-<h1 #h1>Showing {{items.length}} items:</h1>
-<li *ngFor='let item of items; let x=index' [hidden]='item != null'>
- {{x}} : {{item.trim()}}
-</li>
-
-<div *ngIf="items.length > 0">
- <form #ngForm="ngForm"></form>
- {{ngForm.dirty}}
-
- <input [(ngModel)]="header" />
-
- <my-counter
- #counter
- [count]="items.length"
- [maxCount]='4'
- (reset)=''
- (click)='h1.hidden = !h1.hidden; counter.reset()'
- (incremented)='items.add($event.toString())'>
- <my-counter></my-counter>
- </my-counter>
-</div>
-''';
-
- String dart = baseDart;
- String html = baseHtml;
-
- Random random = new Random();
-
- // ignore: non_constant_identifier_names
- /// More or less expect(), but without failing the test. Returns a [Future] so
- /// that you can chain things to do when this succeeds or fails.
- Future check(Object actual, Matcher matcher, {String reason}) {
- final matchState = {};
-
- print('failed');
- final description = new StringDescription();
- description.add('Expected: ').addDescriptionOf(matcher).add('\n');
- description.add(' Actual: ').addDescriptionOf(actual).add('\n');
-
- final mismatchDescription = new StringDescription();
- matcher.describeMismatch(actual, mismatchDescription, matchState, false);
-
- if (mismatchDescription.length > 0) {
- description.add(' Which: $mismatchDescription\n');
- }
- if (reason != null) {
- description.add(reason).add('\n');
- }
-
- print(description.toString());
- return new Future.error(description);
- }
-
- Future checkNoCrash(String dart, String html) {
- final zoneCompleter = new Completer<Null>();
- var complete = false;
- final reason =
- '<<==DART CODE==>>\n$dart\n<<==HTML CODE==>>\n$html\n<<==DONE==>>';
-
- runZoned(() {
- super.setUp();
- newSource('/test.dart', dart);
- newSource('/test.html', html);
- final resultFuture =
- angularDriver.requestDartResult('/test.dart').then((result) {
- if (result.directives.isNotEmpty) {
- final directive = result.directives.first;
- if (directive is Component &&
- directive.view?.templateUriSource?.fullName == '/test.html') {
- return angularDriver.requestHtmlResult('/test.html');
- }
- }
- });
- Future.wait([resultFuture]).then((_) => zoneCompleter.complete());
- }, onError: (e, stacktrace) {
- print("Fuzz Failure \n$reason\n$e\n$stacktrace");
- if (!complete) {
- zoneCompleter.complete();
- complete = true;
- }
- });
-
- return zoneCompleter.future;
- }
-
- String fuzz_addChar(String input) {
- String newchar;
- if (input.isEmpty) {
- newchar = new String.fromCharCode(random.nextInt(128));
- } else {
- newchar = input[randomIndex(input.codeUnits)];
- }
- final charpos = randomPos(input);
- return input.replaceRange(charpos, charpos, newchar);
- }
-
- // ignore: non_constant_identifier_names
- String fuzz_addDartChunk(String input) {
- var chunk = fuzz_truncate(dartSnippets);
- if (chunk.length > 80) {
- chunk = chunk.substring(0, random.nextInt(80));
- } else if (chunk.isEmpty) {
- return input;
- } else {
- chunk = chunk.substring(randomPos(chunk));
- }
- final charpos = randomPos(input);
- return input.replaceRange(charpos, charpos, chunk);
- }
-
- // ignore: non_constant_identifier_names
- String fuzz_addHtmlChunk(String input) {
- var chunk = fuzz_truncate(htmlSnippets);
- if (chunk.length > 80) {
- chunk = chunk.substring(0, random.nextInt(80));
- } else if (chunk.isEmpty) {
- return input;
- } else {
- chunk = chunk.substring(randomPos(chunk));
- }
- final charpos = randomPos(input);
- return input.replaceRange(charpos, charpos, chunk);
- }
-
- // ignore: non_constant_identifier_names
- String fuzz_addKeyword(String input) {
- final token = Keyword.values[randomIndex(Keyword.values)];
- if (input.isEmpty) {
- return input;
- }
-
- final charpos = randomPos(input);
- return input.replaceRange(charpos, charpos, token.lexeme);
- }
-
- // ignore: non_constant_identifier_names
- String fuzz_copyChunk(String input) {
- if (input.isEmpty) {
- return input;
- }
-
- final chunk = fuzz_truncate(input.substring(randomIndex(input.codeUnits)));
- final charpos = randomPos(input);
- return input.replaceRange(charpos, charpos, chunk);
- }
-
- // ignore: non_constant_identifier_names
- String fuzz_copyLine(String input) {
- final lines = input.split('\n');
- if (lines.length == 1) {
- return input;
- }
- final which = randomIndex(lines);
- final toPrepend = lines[which];
- lines.removeAt(which);
- // ignore: prefer_interpolation_to_compose_strings
- lines[which] = toPrepend + lines[which];
- return lines.join('\n');
- }
-
- // ignore: non_constant_identifier_names
- String fuzz_dropLine(String input) {
- final lines = input.split('\n');
- lines.removeAt(randomIndex(lines)); // ignore: cascade_invocations
- return lines.join('\n');
- }
-
- // ignore: non_constant_identifier_names
- String fuzz_joinLine(String input) {
- final lines = input.split('\n');
- if (lines.length == 1) {
- return input;
- }
- final which = randomIndex(lines);
- final toPrepend = lines[which];
- lines.removeAt(which);
- // ignore: prefer_interpolation_to_compose_strings
- lines[which] = toPrepend + lines[which];
- return lines.join('\n');
- }
-
- // ignore: non_constant_identifier_names
- String fuzz_removeChar(String input) {
- final charpos = randomIndex(input.codeUnits);
- if (charpos == null) {
- return input;
- }
- return input.replaceRange(charpos, charpos + 1, '');
- }
-
- // ignore: non_constant_identifier_names
- String fuzz_shuffleLines(String input) {
- final lines = input.split('\n')..shuffle(random);
- return lines.join('\n');
- }
-
- // ignore: non_constant_identifier_names
- String fuzz_truncate(String input) {
- final charpos = randomPos(input);
- if (charpos == 0) {
- return '';
- }
- return input.substring(0, charpos);
- }
-
- // ignore: non_constant_identifier_names
- int randomIndex(List s) {
- if (s.isEmpty) {
- return null;
- } else if (s.length == 1) {
- return 0;
- }
- // range is between 1 and n, but a random pos is 0 to n
- return random.nextInt(s.length - 1);
- }
-
- int randomPos(String s) {
- if (s.isEmpty) {
- return 0;
- }
- // range is between 1 and n, but a random pos is 0 to n
- return random.nextInt(s.length);
- }
-
- Future test_fuzz_continually() async {
- final fuzzOptions = <FuzzModification>[
- fuzz_removeChar,
- fuzz_truncate,
- fuzz_addChar,
- fuzz_copyLine,
- fuzz_dropLine,
- fuzz_joinLine,
- fuzz_shuffleLines,
- fuzz_copyChunk,
- fuzz_addKeyword,
- fuzz_addDartChunk,
- fuzz_addHtmlChunk,
- ];
-
- const iters = 1000000;
- for (var i = 0; i < iters; ++i) {
- final transforms = random.nextInt(20) + 1;
- print("Fuzz $i: $transforms transforms");
- dart = baseDart;
- html = baseHtml;
-
- for (var x = 0; x < transforms; ++x) {
- if (random.nextBool()) {
- dart = fuzzOptions[random.nextInt(fuzzOptions.length)](dart);
- } else {
- html = fuzzOptions[random.nextInt(fuzzOptions.length)](html);
- }
- }
-
- await checkNoCrash(dart, html);
- }
- }
-}
diff --git a/angular_analyzer_plugin/test/mock_angular.dart b/angular_analyzer_plugin/test/mock_angular.dart
deleted file mode 100644
index 6f9e706..0000000
--- a/angular_analyzer_plugin/test/mock_angular.dart
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-void addAngularSources(Function(String, [String]) newSource,
- {bool includeQueryList: false}) {
- newSource('/angular2/angular2.dart', r'''
-library angular2;
-
-export 'package:angular/angular.dart';
-''');
- newSource('/angular2/security.dart', r'''
-library angular2.security;
-
-export 'package:angular/security.dart';
-''');
- newSource('/angular/angular.dart', r'''
-library angular;
-
-export 'src/core/async.dart';
-export 'src/core/metadata.dart';
-export 'src/core/ng_if.dart';
-export 'src/core/ng_for.dart';
-export 'src/core/change_detection.dart';
-''');
- newSource('/angular/security.dart', r'''
-library angular.security;
-export 'src/security/dom_sanitization_service.dart';
-''');
- newSource(
- '/angular/src/core/metadata.dart',
- r'''
-import 'dart:async';
-
-abstract class Directive {
- const Directive(
- {String selector,
- Map<String, String> host,
- @Deprecated('Use `providers` instead') List bindings,
- List providers,
- String exportAs,
- String moduleId,
- Map<String, dynamic> queries})
- : super(
- selector: selector,
- properties: properties,
- events: events,
- host: host,
- bindings: bindings,
- providers: providers,
- exportAs: exportAs,
- moduleId: moduleId,
- queries: queries);
-}
-
-class Component extends Directive {
- final List<Object> directives;
- const Component(
- {String selector,
- Map<String, String> host,
- @Deprecated('Use `providers` instead') List bindings,
- List providers,
- String exportAs,
- String moduleId,
- Map<String, dynamic> queries,
- @Deprecated('Use `viewProviders` instead') List viewBindings,
- List viewProviders,
- ChangeDetectionStrategy changeDetection,
- String templateUrl,
- String template,
- this.directives,
- dynamic pipes,
- ViewEncapsulation encapsulation,
- List exports,
- List<String> styles,
- List<String> styleUrls});
-}
-
-class Pipe {
- final String name;
- final bool _pure;
- const Pipe(this.name, {bool pure});
-}
-
-class Input {
- final String bindingPropertyName;
- const Input([this.bindingPropertyName]);
-}
-
-class Output {
- final String bindingPropertyName;
- const Output([this.bindingPropertyName]);
-}
-
-class Attribute {
- final String attributeName;
- const Attribute(this.attributeName);
-}
-
-class ContentChild extends Query {
- const ContentChild(dynamic /* Type | String */ selector,
- {dynamic read: null}) : super(selector, read: read);
-}
-
-class ContentChildren extends Query {
- const ContentChildren(dynamic /* Type | String */ selector,
- {dynamic read: null}) : super(selector, read: read);
-}
-
-class Query extends DependencyMetadata {
- final dynamic /* Type | String */ selector;
- final dynamic /* String | Function? */ read;
- const DependencyMetadata(this.selector, {this.read}) : super();
-}
-
-class DependencyMetadata {
- const DependencyMetadata();
-}
-
-class TemplateRef {}
-class ElementRef {}
-''' +
- (includeQueryList
- ? r'''
-class QueryList<T> implements Iterable<T> {}
-'''
- : '') +
- r'''
-class ViewContainerRef {}
-class PipeTransform {}
-''');
- newSource('/angular/src/core/async.dart', r'''
-import 'dart:async';
-
-class EventEmitter<T> extends Stream<T> {
- StreamController<dynamic> _controller;
-
- /**
- * Creates an instance of [EventEmitter], which depending on [isAsync],
- * delivers events synchronously or asynchronously.
- */
- EventEmitter([bool isAsync = true]) {
- _controller = new StreamController.broadcast(sync: !isAsync);
- }
-
- StreamSubscription listen(void onData(dynamic line),
- {void onError(Error error), void onDone(), bool cancelOnError}) {
- return _controller.stream.listen(onData,
- onError: onError, onDone: onDone, cancelOnError: cancelOnError);
- }
-
- void add(value) {
- _controller.add(value);
- }
-
- void addError(error) {
- _controller.addError(error);
- }
-
- void close() {
- _controller.close();
- }
-}
-''');
- newSource('/angular/src/core/ng_if.dart', r'''
-import 'metadata.dart';
-
-@Directive(selector: "[ngIf]")
-class NgIf {
- @Input()
- NgIf(TemplateRef tpl);
-
- @Input()
- set ngIf(newCondition) {}
-}
-''');
- newSource('/angular/src/core/ng_for.dart', r'''
-import 'metadata.dart';
-
-@Directive(
- selector: "[ngFor][ngForOf]")
-class NgFor {
- @Input()
- NgFor(TemplateRef tpl);
- @Input()
- set ngForOf(dynamic value) {}
- @Input()
- set ngForTrackBy(TrackByFn value) {}
-}
-
-typedef dynamic TrackByFn(num index, dynamic item);
-''');
- newSource('/angular/src/security/dom_sanitization_service.dart', r'''
-class SafeValue {}
-
-abstract class SafeHtml extends SafeValue {}
-
-abstract class SafeStyle extends SafeValue {}
-
-abstract class SafeScript extends SafeValue {}
-
-abstract class SafeUrl extends SafeValue {}
-
-abstract class SafeResourceUrl extends SafeValue {}
-''');
-}
diff --git a/angular_analyzer_plugin/test/mock_sdk.dart b/angular_analyzer_plugin/test/mock_sdk.dart
deleted file mode 100644
index 99cf448..0000000
--- a/angular_analyzer_plugin/test/mock_sdk.dart
+++ /dev/null
@@ -1,863 +0,0 @@
-import 'package:analyzer/file_system/file_system.dart' as resource;
-import 'package:analyzer/file_system/memory_file_system.dart' as resource;
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/idl.dart' show PackageBundle;
-import 'package:analyzer/src/summary/summary_file_builder.dart';
-
-const librariesContent = r'''
-const libraries = const <String, LibraryInfo>{
- "async": const LibraryInfo("async/async.dart"),
- "collection": const LibraryInfo("collection/collection.dart"),
- "convert": const LibraryInfo("convert/convert.dart"),
- "core": const LibraryInfo("core/core.dart"),
- "html": const LibraryInfo(
- "html/dartium/html_dartium.dart",
- dart2jsPath: "html/dart2js/html_dart2js.dart"),
- "math": const LibraryInfo("math/math.dart"),
- "_foreign_helper": const LibraryInfo("_internal/js_runtime/lib/foreign_helper.dart"),
-};
-''';
-
-const sdkRoot = '/sdk';
-
-const _LIB_ASYNC =
- const _MockSdkLibrary('dart:async', '$sdkRoot/lib/async/async.dart', '''
-library dart.async;
-
-part 'stream.dart';
-part 'future.dart';
-
-class Duration {}
-''', const <String, String>{
- '$sdkRoot/lib/async/stream.dart': r'''
-part of dart.async;
-abstract class Stream<T> {
- Future<T> get first;
- StreamSubscription<T> listen(void onData(T event),
- { Function onError,
- void onDone(),
- bool cancelOnError});
-}
-
-abstract class StreamSubscription<T> {
- Future cancel();
- void onData(void handleData(T data));
- void onError(Function handleError);
- void onDone(void handleDone());
- void pause([Future resumeSignal]);
- void resume();
- bool get isPaused;
- Future<E> asFuture<E>([E futureValue]);
-}
-
-abstract class StreamTransformer<S, T> {}
-''',
- '$sdkRoot/lib/async/future.dart': r'''
-part of dart.async;
-class Future<T> {
- factory Future(computation()) => null;
- factory Future.delayed(Duration duration, [T computation()]) => null;
- factory Future.value([value]) => null;
-
- static Future<List/*<T>*/> wait/*<T>*/(
- Iterable<Future/*<T>*/> futures) => null;
- Future/*<R>*/ then/*<R>*/(FutureOr/*<R>*/ onValue(T value)) => null;
-
- Future<T> whenComplete(action()) => null;
-}
-
-abstract class FutureOr<T> {}
-
-abstract class Completer<T> {
- factory Completer() => new _AsyncCompleter<T>();
- factory Completer.sync() => new _SyncCompleter<T>();
- Future<T> get future;
- void complete([value]);
- void completeError(Object error, [StackTrace stackTrace]);
- bool get isCompleted;
-}
-
-class _AsyncCompleter<T> implements Completer<T> {
- Future<T> get future => null;
- void complete([value]) => null;
- void completeError(Object error, [StackTrace stackTrace]) => null;
- bool get isCompleted => null;
-}
-class _SyncCompleter<T> implements Completer<T> {
- Future<T> get future => null;
- void complete([value]) => null;
- void completeError(Object error, [StackTrace stackTrace]) => null;
- bool get isCompleted => null;
-}
-'''
-});
-
-const _LIB_COLLECTION = const _MockSdkLibrary(
- 'dart:collection', '$sdkRoot/lib/collection/collection.dart', '''
-library dart.collection;
-
-abstract class HashMap<K, V> implements Map<K, V> {}
-''');
-
-const _LIB_CONVERT = const _MockSdkLibrary(
- 'dart:convert', '$sdkRoot/lib/convert/convert.dart', '''
-library dart.convert;
-
-import 'dart:async';
-
-abstract class Converter<S, T> implements StreamTransformer {}
-class JsonDecoder extends Converter<String, Object> {}
-''');
-
-const _LIB_CORE =
- const _MockSdkLibrary('dart:core', '$sdkRoot/lib/core/core.dart', '''
-library dart.core;
-
-import 'dart:async';
-
-class Object {
- const Object() {}
- bool operator ==(other) => identical(this, other);
- String toString() => 'a string';
- int get hashCode => 0;
- Type get runtimeType => null;
- dynamic noSuchMethod(Invocation invocation) => null;
-}
-
-class Function {}
-class StackTrace {}
-
-class Symbol {
- const factory Symbol(String name) {
- return null;
- }
-}
-
-class Type {}
-
-abstract class Comparable<T> {
- int compareTo(T other);
-}
-
-abstract class Pattern {}
-abstract class String implements Comparable<String>, Pattern {
- external factory String.fromCharCodes(Iterable<int> charCodes,
- [int start = 0, int end]);
- String operator +(String other) => null;
- bool get isEmpty => false;
- bool get isNotEmpty => false;
- int get length => 0;
- String substring(int len) => null;
- String toLowerCase();
- String toUpperCase();
- List<int> get codeUnits;
-}
-abstract class RegExp implements Pattern {
- external factory RegExp(String source);
-}
-
-class bool extends Object {
- external const factory bool.fromEnvironment(String name,
- {bool defaultValue: false});
-}
-
-abstract class Invocation {}
-
-abstract class num implements Comparable<num> {
- bool operator <(num other);
- bool operator <=(num other);
- bool operator >(num other);
- bool operator >=(num other);
- num operator +(num other);
- num operator -(num other);
- num operator *(num other);
- num operator /(num other);
- int operator ^(int other);
- int operator |(int other);
- int operator <<(int other);
- int operator >>(int other);
- int operator ~/(num other);
- num operator %(num other);
- int operator ~();
- num operator -();
- int toInt();
- double toDouble();
- num abs();
- int round();
-}
-abstract class int extends num {
- external const factory int.fromEnvironment(String name, {int defaultValue});
-
- bool get isNegative;
- bool get isEven => false;
-
- int operator &(int other);
- int operator |(int other);
- int operator ^(int other);
- int operator ~();
- int operator <<(int shiftAmount);
- int operator >>(int shiftAmount);
-
- int operator -();
-
- external static int parse(String source,
- { int radix,
- int onError(String source) });
-}
-
-abstract class double extends num {
- static const double NAN = 0.0 / 0.0;
- static const double INFINITY = 1.0 / 0.0;
- static const double NEGATIVE_INFINITY = -INFINITY;
- static const double MIN_POSITIVE = 5e-324;
- static const double MAX_FINITE = 1.7976931348623157e+308;
-
- double remainder(num other);
- double operator +(num other);
- double operator -(num other);
- double operator *(num other);
- double operator %(num other);
- double operator /(num other);
- int operator ~/(num other);
- double operator -();
- double abs();
- double get sign;
- int round();
- int floor();
- int ceil();
- int truncate();
- double roundToDouble();
- double floorToDouble();
- double ceilToDouble();
- double truncateToDouble();
- external static double parse(String source,
- [double onError(String source)]);
-}
-
-class DateTime extends Object {}
-
-class Null extends Object {
- factory Null._uninstantiable() {
- throw new UnsupportedError('class Null cannot be instantiated');
- }
-}
-
-class Deprecated extends Object {
- final String expires;
- const Deprecated(this.expires);
-}
-const Object deprecated = const Deprecated("next release");
-
-class Iterator<E> {
- bool moveNext();
- E get current;
-}
-
-abstract class Iterable<E> {
- Iterator<E> get iterator;
- bool get isEmpty;
- E get first;
-
- Iterable/*<R>*/ map/*<R>*/(/*=R*/ f(E e));
-
- /*=R*/ fold/*<R>*/(/*=R*/ initialValue,
- /*=R*/ combine(/*=R*/ previousValue, E element));
-
- Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(E element));
-
- List<E> toList();
-}
-
-class List<E> implements Iterable<E> {
- List();
- void add(E value) {}
- void addAll(Iterable<E> iterable) {}
- E operator [](int index) => null;
- void operator []=(int index, E value) {}
- Iterator<E> get iterator => null;
- void clear() {}
-
- bool get isEmpty => false;
- E get first => null;
- E get last => null;
-
- Iterable/*<R>*/ map/*<R>*/(/*=R*/ f(E e)) => null;
-
- /*=R*/ fold/*<R>*/(/*=R*/ initialValue,
- /*=R*/ combine(/*=R*/ previousValue, E element)) => null;
-
-}
-
-class Map<K, V> extends Object {
- V operator [](K key) => null;
- void operator []=(K key, V value) {}
- Iterable<K> get keys => null;
- int get length;
- Iterable<V> get values;
-}
-
-external bool identical(Object a, Object b);
-
-void print(Object object) {}
-
-class _Proxy { const _Proxy(); }
-const Object proxy = const _Proxy();
-
-class _Override { const _Override(); }
-const Object override = const _Override();
-''');
-
-const _LIB_FOREIGN_HELPER = const _MockSdkLibrary('dart:_foreign_helper',
- '$sdkRoot/lib/_foreign_helper/_foreign_helper.dart', '''
-library dart._foreign_helper;
-
-JS(String typeDescription, String codeTemplate,
- [arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11])
-{}
-''');
-
-const _LIB_HTML_DART2JS = const _MockSdkLibrary(
- 'dart:html', '$sdkRoot/lib/html/dart2js/html_dart2js.dart', '''
-library dart.html;
-import 'dart:async';
-
-class Event {}
-class MouseEvent extends Event {}
-class FocusEvent extends Event {}
-class KeyEvent extends Event {}
-
-abstract class ElementStream<T extends Event> implements Stream<T> {}
-
-abstract class Element {
- /// Stream of `cut` events handled by this [Element].
- ElementStream<Event> get onCut => null;
-
- String get id => null;
-
- set id(String value) => null;
-}
-
-class HtmlElement extends Element {
- int tabIndex;
- ElementStream<Event> get onChange => null;
- ElementStream<MouseEvent> get onClick => null;
- ElementStream<KeyEvent> get onKeyUp => null;
- ElementStream<KeyEvent> get onKeyDown => null;
-
- bool get hidden => null;
- set hidden(bool value) => null;
-
- void set className(String s){}
- void set readOnly(bool b){}
- void set tabIndex(int i){}
-
- String _innerHtml;
- String get innerHtml {
- throw 'not the real implementation';
- }
- set innerHtml(String value) {
- // stuff
- }
-
-}
-
-dynamic JS(a, b, c, d) {}
-
-class AnchorElement extends HtmlElement {
- factory AnchorElement({String href}) {
- AnchorElement e = JS('returns:AnchorElement;creates:AnchorElement;new:true',
- '#.createElement(#)', document, "a");
- if (href != null) e.href = href;
- return e;
- }
- String href;
- String _privateField;
-}
-
-class BodyElement extends HtmlElement {
- factory BodyElement() => document.createElement("body");
-
- ElementStream<Event> get onUnload => null;
-}
-
-class ButtonElement extends HtmlElement {
- factory ButtonElement._() { throw new UnsupportedError("Not supported"); }
- factory ButtonElement() => document.createElement("button");
- bool autofocus;
-}
-
-class HeadingElement extends HtmlElement {
- factory HeadingElement._() { throw new UnsupportedError("Not supported"); }
- factory HeadingElement.h1() => document.createElement("h1");
- factory HeadingElement.h2() => document.createElement("h2");
- factory HeadingElement.h3() => document.createElement("h3");
-}
-
-class InputElement extends HtmlElement {
- factory InputElement._() { throw new UnsupportedError("Not supported"); }
- factory InputElement() => document.createElement("input");
- String value;
- String validationMessage;
-}
-
-class IFrameElement extends HtmlElement {
- factory IFrameElement._() { throw new UnsupportedError("Not supported"); }
- factory IFrameElement() => JS(
- 'returns:IFrameElement;creates:IFrameElement;new:true',
- '#.createElement(#)',
- document,
- "iframe");
- String src;
-}
-
-class OptionElement extends HtmlElement {
- factory OptionElement({String data: '', String value : '', bool selected: false}) {
- }
-
- factory OptionElement._([String data, String value, bool defaultSelected, bool selected]) {
- }
-}
-
-class TableSectionElement extends HtmlElement {
-
- List<TableRowElement> get rows => null;
-
- TableRowElement addRow() {
- }
-
- TableRowElement insertRow(int index) => null;
-
- factory TableSectionElement._() { throw new UnsupportedError("Not supported"); }
-
- @Deprecated("Internal Use Only")
- external static Type get instanceRuntimeType;
-
- @Deprecated("Internal Use Only")
- TableSectionElement.internal_() : super.internal_();
-}
-
-class TemplateElement extends HtmlElement {
- factory TemplateElement._() { throw new UnsupportedError("Not supported"); }
- factory TemplateElement() => document.createElement("template");
-}
-
-class AudioElement extends MediaElement {
- factory AudioElement._([String src]) {
- if (src != null) {
- return AudioElement._create_1(src);
- }
- return AudioElement._create_2();
- }
- static AudioElement _create_1(src) => JS('AudioElement', 'new Audio(#)', src);
- static AudioElement _create_2() => JS('AudioElement', 'new Audio()');
- AudioElement.created() : super.created();
-
- factory AudioElement([String src]) => new AudioElement._(src);
-}
-
-class MediaElement extends Element {}
-''');
-
-const _LIB_HTML_DARTIUM = const _MockSdkLibrary(
- 'dart:html', '$sdkRoot/lib/html/dartium/html_dartium.dart', '''
-library dart.html;
-import 'dart:async';
-
-class Event {}
-class MouseEvent extends Event {}
-class FocusEvent extends Event {}
-class KeyEvent extends Event {}
-
-abstract class ElementStream<T extends Event> implements Stream<T> {}
-
-abstract class Element {
- /// Stream of `cut` events handled by this [Element].
- ElementStream<Event> get onCut => null;
-
- String get id => null;
-
- set id(String value) => null;
-}
-
-class HtmlElement extends Element {
- int tabIndex;
- ElementStream<Event> get onChange => null;
- ElementStream<MouseEvent> get onClick => null;
- ElementStream<KeyEvent> get onKeyUp => null;
- ElementStream<KeyEvent> get onKeyDown => null;
-
- bool get hidden => null;
- set hidden(bool value) => null;
-
- void set className(String s){}
- void set readOnly(bool b){}
- void set tabIndex(int i){}
-
- String _innerHtml;
- String get innerHtml {
- throw 'not the real implementation';
- }
- set innerHtml(String value) {
- // stuff
- }
-
-}
-
-dynamic JS(a, b, c, d) {}
-
-class AnchorElement extends HtmlElement {
- factory AnchorElement({String href}) {
- AnchorElement e = JS('returns:AnchorElement;creates:AnchorElement;new:true',
- '#.createElement(#)', document, "a");
- if (href != null) e.href = href;
- return e;
- }
- String href;
- String _privateField;
-}
-
-class BodyElement extends HtmlElement {
- factory BodyElement() => document.createElement("body");
-
- ElementStream<Event> get onUnload => null;
-}
-
-class ButtonElement extends HtmlElement {
- factory ButtonElement._() { throw new UnsupportedError("Not supported"); }
- factory ButtonElement() => document.createElement("button");
- bool autofocus;
-}
-
-class HeadingElement extends HtmlElement {
- factory HeadingElement._() { throw new UnsupportedError("Not supported"); }
- factory HeadingElement.h1() => document.createElement("h1");
- factory HeadingElement.h2() => document.createElement("h2");
- factory HeadingElement.h3() => document.createElement("h3");
-}
-
-class InputElement extends HtmlElement {
- factory InputElement._() { throw new UnsupportedError("Not supported"); }
- factory InputElement() => document.createElement("input");
- String value;
- String validationMessage;
-}
-
-class IFrameElement extends HtmlElement {
- factory IFrameElement._() { throw new UnsupportedError("Not supported"); }
- factory IFrameElement() => JS(
- 'returns:IFrameElement;creates:IFrameElement;new:true',
- '#.createElement(#)',
- document,
- "iframe");
- String src;
-}
-
-class OptionElement extends HtmlElement {
- factory OptionElement({String data: '', String value : '', bool selected: false}) {
- }
-
- factory OptionElement._([String data, String value, bool defaultSelected, bool selected]) {
- }
-}
-
-class TableSectionElement extends HtmlElement {
-
- List<TableRowElement> get rows => null;
-
- TableRowElement addRow() {
- }
-
- TableRowElement insertRow(int index) => null;
-
- factory TableSectionElement._() { throw new UnsupportedError("Not supported"); }
-
- @Deprecated("Internal Use Only")
- external static Type get instanceRuntimeType;
-
- @Deprecated("Internal Use Only")
- TableSectionElement.internal_() : super.internal_();
-}
-
-class TemplateElement extends HtmlElement {
- factory TemplateElement._() { throw new UnsupportedError("Not supported"); }
- factory TemplateElement() => document.createElement("template");
-}
-
-class AudioElement extends MediaElement {
- factory AudioElement._([String src]) {
- if (src != null) {
- return AudioElement._create_1(src);
- }
- return AudioElement._create_2();
- }
- static AudioElement _create_1(src) => JS('AudioElement', 'new Audio(#)', src);
- static AudioElement _create_2() => JS('AudioElement', 'new Audio()');
- AudioElement.created() : super.created();
-
- factory AudioElement([String src]) => new AudioElement._(src);
-}
-
-class MediaElement extends Element {}
-''');
-
-const _LIB_INTERCEPTORS = const _MockSdkLibrary('dart:_interceptors',
- '$sdkRoot/lib/_internal/js_runtime/lib/interceptors.dart', '''
-library dart._interceptors;
-''');
-
-const _LIB_MATH =
- const _MockSdkLibrary('dart:math', '$sdkRoot/lib/math/math.dart', '''
-library dart.math;
-
-const double E = 2.718281828459045;
-const double PI = 3.1415926535897932;
-const double LN10 = 2.302585092994046;
-
-T min<T extends num>(T a, T b) => null;
-T max<T extends num>(T a, T b) => null;
-
-external double cos(num x);
-external double sin(num x);
-external double sqrt(num x);
-class Random {
- bool nextBool() => true;
- double nextDouble() => 2.0;
- int nextInt() => 1;
-}
-''');
-
-const _LIBRARIES = const <SdkLibrary>[
- _LIB_CORE,
- _LIB_ASYNC,
- _LIB_COLLECTION,
- _LIB_CONVERT,
- _LIB_FOREIGN_HELPER,
- _LIB_MATH,
- _LIB_HTML_DART2JS,
- _LIB_HTML_DARTIUM,
- _LIB_INTERCEPTORS,
-];
-
-class MockSdk implements DartSdk {
- static const Map<String, String> FULL_URI_MAP = const {
- "dart:core": "$sdkRoot/lib/core/core.dart",
- "dart:html": "$sdkRoot/lib/html/dartium/html_dartium.dart",
- "dart:async": "$sdkRoot/lib/async/async.dart",
- "dart:async/stream.dart": "$sdkRoot/lib/async/stream.dart",
- "dart:async/future.dart": "$sdkRoot/lib/async/future.dart",
- "dart:collection": "$sdkRoot/lib/collection/collection.dart",
- "dart:convert": "$sdkRoot/lib/convert/convert.dart",
- "dart:_foreign_helper": "$sdkRoot/lib/_foreign_helper/_foreign_helper.dart",
- "dart:_interceptors":
- "$sdkRoot/lib/_internal/js_runtime/lib/interceptors.dart",
- "dart:math": "$sdkRoot/lib/math/math.dart"
- };
-
- static const Map<String, String> NO_ASYNC_URI_MAP = const {
- "dart:core": "$sdkRoot/lib/core/core.dart",
- };
-
- final resource.MemoryResourceProvider provider;
-
- final Map<String, String> uriMap;
-
- /// The [AnalysisContextImpl] which is used for all of the sources.
- AnalysisContextImpl _analysisContext;
-
- @override
- final List<SdkLibrary> sdkLibraries;
-
- /// The cached linked bundle of the SDK.
- PackageBundle _bundle;
-
- MockSdk(
- {bool generateSummaryFiles: false,
- bool dartAsync: true,
- resource.MemoryResourceProvider resourceProvider})
- : provider = resourceProvider ?? new resource.MemoryResourceProvider(),
- sdkLibraries = dartAsync ? _LIBRARIES : [_LIB_CORE],
- uriMap = dartAsync ? FULL_URI_MAP : NO_ASYNC_URI_MAP {
- for (var library in sdkLibraries.cast<_MockSdkLibrary>()) {
- provider.newFile(provider.convertPath(library.path), library.content);
- library.parts.forEach((path, content) {
- provider.newFile(provider.convertPath(path), content);
- });
- }
- provider.newFile(
- provider.convertPath(
- '$sdkRoot/lib/_internal/sdk_library_metadata/lib/libraries.dart'),
- librariesContent);
- if (generateSummaryFiles) {
- final bytes = _computeLinkedBundleBytes();
- provider
- ..newFileWithBytes(
- provider.convertPath('/lib/_internal/spec.sum'), bytes)
- ..newFileWithBytes(
- provider.convertPath('/lib/_internal/strong.sum'), bytes);
- }
- }
-
- @override
- AnalysisContextImpl get context {
- if (_analysisContext == null) {
- _analysisContext = new _SdkAnalysisContext(this);
- final factory = new SourceFactory([new DartUriResolver(this)]);
- _analysisContext.sourceFactory = factory;
- }
- return _analysisContext;
- }
-
- @override
- String get sdkVersion => throw new UnimplementedError();
-
- @override
- List<String> get uris =>
- sdkLibraries.map((library) => library.shortName).toList();
-
- @override
- Source fromFileUri(Uri uri) {
- final filePath = provider.pathContext.fromUri(uri);
- if (!filePath.startsWith(provider.convertPath('$sdkRoot/lib/'))) {
- return null;
- }
- for (final library in sdkLibraries) {
- final libraryPath = provider.convertPath(library.path);
- if (filePath == libraryPath) {
- try {
- final file = provider.getResource(filePath) as resource.File;
- final dartUri = Uri.parse(library.shortName);
- return file.createSource(dartUri);
- } catch (exception) {
- return null;
- }
- }
- // ignore: prefer_interpolation_to_compose_strings
- final libraryRootPath = provider.pathContext.dirname(libraryPath) +
- provider.pathContext.separator;
- if (filePath.startsWith(libraryRootPath)) {
- final pathInLibrary = filePath.substring(libraryRootPath.length);
- final uriStr = '${library.shortName}/$pathInLibrary';
- try {
- final file = provider.getResource(filePath) as resource.File;
- final dartUri = Uri.parse(uriStr);
- return file.createSource(dartUri);
- } catch (exception) {
- return null;
- }
- }
- }
- return null;
- }
-
- @override
- PackageBundle getLinkedBundle() {
- if (_bundle == null) {
- final summaryFile =
- provider.getFile(provider.convertPath('/lib/_internal/spec.sum'));
- List<int> bytes;
- if (summaryFile.exists) {
- bytes = summaryFile.readAsBytesSync();
- } else {
- bytes = _computeLinkedBundleBytes();
- }
- _bundle = new PackageBundle.fromBuffer(bytes);
- }
- return _bundle;
- }
-
- @override
- SdkLibrary getSdkLibrary(String dartUri) {
- for (final library in _LIBRARIES) {
- if (library.shortName == dartUri) {
- return library;
- }
- }
- return null;
- }
-
- @override
- Source mapDartUri(String dartUri) {
- final path = uriMap[dartUri];
- if (path != null) {
- final file =
- provider.getResource(provider.convertPath(path)) as resource.File;
- final uri = new Uri(scheme: 'dart', path: dartUri.substring(5));
- return file.createSource(uri);
- }
- // If we reach here then we tried to use a dartUri that's not in the
- // table above.
- return null;
- }
-
- /// This method is used to apply patches to [MockSdk]. It may be called only
- /// before analysis, i.e. before the analysis context was created.
- void updateUriFile(String uri, String updateContent(String content)) {
- assert(_analysisContext == null);
- var path = FULL_URI_MAP[uri];
- assert(path != null);
- path = provider.convertPath(path);
- final content = provider.getFile(path).readAsStringSync();
- final newContent = updateContent(content);
- provider.updateFile(path, newContent);
- }
-
- /// Compute the bytes of the linked bundle associated with this SDK.
- List<int> _computeLinkedBundleBytes() {
- final librarySources =
- sdkLibraries.map((library) => mapDartUri(library.shortName)).toList();
- return new SummaryBuilder(librarySources, context).build();
- }
-}
-
-class _MockSdkLibrary implements SdkLibrary {
- @override
- final String shortName;
- @override
- final String path;
- final String content;
- final Map<String, String> parts;
-
- const _MockSdkLibrary(this.shortName, this.path, this.content,
- [this.parts = const <String, String>{}]);
-
- @override
- String get category => throw new UnimplementedError();
-
- @override
- bool get isDart2JsLibrary => throw new UnimplementedError();
-
- @override
- bool get isDocumented => throw new UnimplementedError();
-
- @override
- bool get isImplementation => throw new UnimplementedError();
-
- @override
- bool get isInternal => shortName.startsWith('dart:_');
-
- @override
- bool get isShared => throw new UnimplementedError();
-
- @override
- bool get isVmLibrary => throw new UnimplementedError();
-}
-
-/// An [AnalysisContextImpl] that only contains sources for a Dart SDK.
-class _SdkAnalysisContext extends AnalysisContextImpl {
- final DartSdk sdk;
-
- _SdkAnalysisContext(this.sdk);
-
- @override
- AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
- if (factory == null) {
- return super.createCacheFromSourceFactory(factory);
- }
- return new AnalysisCache(
- <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]);
- }
-}
diff --git a/angular_analyzer_plugin/test/mock_sdk_test.dart b/angular_analyzer_plugin/test/mock_sdk_test.dart
deleted file mode 100644
index 9e31a2a..0000000
--- a/angular_analyzer_plugin/test/mock_sdk_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-import 'dart:async';
-
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'abstract_angular.dart';
-import 'mock_sdk.dart';
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(MockSdkTest);
- });
-}
-
-@reflectiveTest
-class MockSdkTest extends AbstractAngularTest {
- // ignore: non_constant_identifier_names
- Future test_futureOr() async {
- final dartResult =
- await dartDriver.getResult('$sdkRoot/lib/async/async.dart');
- expect(dartResult.errors, isEmpty);
- expect(
- dartResult.libraryElement.exportNamespace.get('FutureOr'), isNotNull);
- expect(
- dartResult.libraryElement.context.typeProvider.futureOrType, isNotNull);
- }
-}
diff --git a/angular_analyzer_plugin/test/navigation_test.dart b/angular_analyzer_plugin/test/navigation_test.dart
deleted file mode 100644
index ddd35a0..0000000
--- a/angular_analyzer_plugin/test/navigation_test.dart
+++ /dev/null
@@ -1,485 +0,0 @@
-import 'dart:async';
-
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
-import 'package:analyzer_plugin/utilities/navigation/navigation.dart';
-import 'package:angular_analyzer_plugin/src/angular_driver.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/navigation.dart';
-import 'package:angular_analyzer_plugin/src/navigation_request.dart';
-import 'package:mockito/mockito.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'abstract_angular.dart';
-
-// 'typed' is deprecated and shouldn't be used.
-// ignore_for_file: deprecated_member_use
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(AngularNavigationTest);
- });
-}
-
-@reflectiveTest
-class AngularNavigationTest extends AbstractAngularTest {
- String code;
-
- List<_RecordedNavigationRegion> regions = <_RecordedNavigationRegion>[];
-
- NavigationCollector collector = new NavigationCollectorMock();
-
- _RecordedNavigationRegion region;
- protocol.Location targetLocation;
-
- /// Compute all the views declared in the given [dartSource], and return its
- /// result
- Future<DirectivesResult> resolveDart(Source dartSource) async =>
- await angularDriver.requestDartResult(dartSource.fullName);
-
- /// Resolve the external templates of the views declared in the [dartSource].
- Future<DirectivesResult> resolveLinkedHtml(Source dartSource) async {
- final result = await angularDriver.requestDartResult(dartSource.fullName);
- for (var d in result.directives) {
- if (d is Component && d.view.templateUriSource != null) {
- final htmlPath = d.view.templateUriSource.fullName;
- return await angularDriver.requestHtmlResult(htmlPath);
- }
- }
-
- return null;
- }
-
- @override
- void setUp() {
- super.setUp();
- // TODO(mfairhurst): remove `as dynamic`. See https://github.com/dart-lang/sdk/issues/33934
- when(collector.addRegion(
- typed(argThat(const isInstanceOf<int>())),
- typed(argThat(const isInstanceOf<int>())),
- typed(any),
- typed(any)) as dynamic)
- .thenAnswer((invocation) {
- final offset = invocation.positionalArguments[0] as int;
- final length = invocation.positionalArguments[1] as int;
- final targetKind =
- invocation.positionalArguments[2] as protocol.ElementKind;
- final targetLocation =
- invocation.positionalArguments[3] as protocol.Location;
- regions.add(new _RecordedNavigationRegion(
- offset, length, targetKind, targetLocation));
- });
- }
-
- // ignore: non_constant_identifier_names
- Future test_dart_templates() async {
- code = r'''
-import '/angular/src/core/metadata.dart';
-
-@Component(selector: 'text-panel', template: r"<div>some text</div>")
-class TextPanel {
- @Input('my-text') String text; // 1
- @Input() longform; // 4
-}
-
-@Component(selector: 'UserPanel', template: r"""
-<div>
- <text-panel [my-text]='user.name' [longform]='""'></text-panel> // close
-</div>
-""", directives: [TextPanel])
-class UserPanel {
- User user; // 2
-}
-
-class User {
- String name; // 3
-}
-''';
- final source = newSource('/test.dart', code);
- // compute navigation regions
- final result = await resolveDart(source);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(null, null, null, result), collector,
- templatesOnly: false);
- // template references component (open tag)
- {
- _findRegionString('text-panel', ' [my-text]');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf("text-panel', template"));
- }
- // template references component (close tag)
- {
- _findRegionString('text-panel', '> // close');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf("text-panel', template"));
- }
- // template references input
- {
- _findRegionString('my-text', ']=');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf("my-text"));
- }
- // template references field
- {
- _findRegionString('user', ".name' ");
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf("user; // 2"));
- }
- // template references field
- {
- _findRegionString('name', "' [");
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf("name; // 3"));
- }
- // template references input
- {
- _findRegionString('longform', ']=');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf("longform; // 4"));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_dart_view_templateUrl() async {
- code = r'''
-import 'package:angular/src/core/metadata.dart';
-
-@Component(selector: 'text-panel', templateUrl: 'text_panel.html')
-class TextPanel {}
-''';
- final dartSource = newSource('/test.dart', code);
- newSource('/text_panel.html', "");
- final result = await resolveDart(dartSource);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(null, null, null, result), collector,
- templatesOnly: false);
- // input references setter
- {
- _findRegionString("'text_panel.html'", ')');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/text_panel.html');
- expect(targetLocation.offset, 0);
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_dart_view_templateUrl_notForTemplateOnly() async {
- code = r'''
-import 'package:angular/src/core/metadata.dart';
-
-@Component(selector: 'text-panel', templateUrl: 'test.html')
-class TextPanel {}
-''';
- final dartSource = newSource('/test.dart', code);
- newSource('/test.html', ''); // empty template HTML file.
- final result = await resolveLinkedHtml(dartSource);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(null, null, null, result), collector,
- templatesOnly: true);
- // no resolved ranges.
- expect(regions, isEmpty);
- }
-
- // ignore: non_constant_identifier_names
- Future test_html_templates() async {
- final dartCode = r'''
-import 'package:angular/src/core/metadata.dart';
-
-@Component(selector: 'text-panel', templateUrl: 'text_panel.html')
-class TextPanel {
- String text; // 1
-}
-''';
- final htmlCode = r"""
-<div>
- {{text}}
-</div>
-""";
- final dartSource = newSource('/test.dart', dartCode);
- newSource('/text_panel.html', htmlCode);
- final result = await resolveLinkedHtml(dartSource);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(null, null, null, result), collector,
- templatesOnly: false);
- // template references field
- {
- _findRegionString('text', "}}", codeOverride: htmlCode);
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, dartCode.indexOf("text; // 1"));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_navigate_attrIf() async {
- code = r'''
-import 'package:angular/src/core/metadata.dart';
-
-@Component(selector: 'foo', template: r"""
-<div
- [attr.foo]="123"
- [attr.foo.if]="true">
-</div>
-""")
-class TextPanel {
-}
-''';
- final source = newSource('/test.dart', code);
- // compute navigation regions
- final result = await resolveDart(source);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(null, null, null, result), collector,
- templatesOnly: false);
- {
- _findRegionString('foo', '.if');
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf('foo]'));
- }
- }
-
- // ignore: non_constant_identifier_names
- Future test_navigateOnfocusin() async {
- code = r'''
-import 'package:angular/src/core/metadata.dart';
-
-@Component(selector: 'test-comp', template: '<div (focusin)=""></div>')
-class TestComponent {
-}
-''';
- final source = newSource('/test.dart', code);
- // compute navigation regions
- final result = await resolveDart(source);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(
- null, 'focusin'.length, code.indexOf('focusin'), result),
- collector,
- templatesOnly: false);
-
- expect(regions, hasLength(0));
- }
-
- // ignore: non_constant_identifier_names
- Future test_searchRange_fitPerfectlyLeftAndRight() async {
- code = r'''
-import 'package:angular/src/core/metadata.dart';
-
-@Component(
- selector: 'test-comp', template: '{{fieldOne}}{{fieldTwo}}', directives: [])
-class TestComponent {
- String fieldOne;
- String fieldTwo;
-}
-''';
- final source = newSource('/test.dart', code);
- // compute navigation regions
- final result = await resolveDart(source);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(null, 'fieldOne}}{{fieldTwo'.length,
- code.indexOf('fieldOne}}{{fieldTwo'), result),
- collector,
- templatesOnly: false);
- {
- _findRegionString('fieldOne', '}}');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf('fieldOne;'));
- }
- {
- _findRegionString('fieldTwo', '}}');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf('fieldTwo;'));
- }
-
- expect(regions, hasLength(2));
- }
-
- // ignore: non_constant_identifier_names
- Future test_searchRange_narrowMiss() async {
- code = r'''
-import 'package:angular/src/core/metadata.dart';
-
-@Component(
- selector: 'test-comp', template: '{{fieldOne}}{{fieldTwo}}', directives: [])
-class TestComponent {
- String fieldOne;
- String fieldTwo;
-}
-''';
- final source = newSource('/test.dart', code);
- // compute navigation regions
- final result = await resolveDart(source);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(
- null, '}}{{'.length, code.indexOf('}}{{'), result),
- collector,
- templatesOnly: false);
- expect(regions, hasLength(0));
- }
-
- // ignore: non_constant_identifier_names
- Future test_searchRange_overlapLeftAndRight() async {
- code = r'''
-import 'package:angular/src/core/metadata.dart';
-
-@Component(
- selector: 'test-comp', template: '{{fieldOne}}{{fieldTwo}}', directives: [])
-class TestComponent {
- String fieldOne;
- String fieldTwo;
-}
-''';
- final source = newSource('/test.dart', code);
- // compute navigation regions
- final result = await resolveDart(source);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(
- null, 'e}}{{f'.length, code.indexOf('e}}{{f'), result),
- collector,
- templatesOnly: false);
- {
- _findRegionString('fieldOne', '}}');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf('fieldOne;'));
- }
- {
- _findRegionString('fieldTwo', '}}');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf('fieldTwo;'));
- }
-
- expect(regions, hasLength(2));
- }
-
- // ignore: non_constant_identifier_names
- Future test_searchRange_overlapsEntirely() async {
- code = r'''
-import 'package:angular/src/core/metadata.dart';
-
-@Component(
- selector: 'test-comp', template: 'blah {{fieldOne}} blah', directives: [])
-class TestComponent {
- String fieldOne;
- String fieldTwo;
-}
-''';
- final source = newSource('/test.dart', code);
- // compute navigation regions
- final result = await resolveDart(source);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(
- null, ' {{fieldOne}} '.length, code.indexOf(' {{'), result),
- collector,
- templatesOnly: false);
- {
- _findRegionString('fieldOne', '}}');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf('fieldOne;'));
- }
-
- expect(regions, hasLength(1));
- }
-
- // ignore: non_constant_identifier_names
- Future test_searchRange_perfectMatch() async {
- code = r'''
-import 'package:angular/src/core/metadata.dart';
-
-@Component(
- selector: 'test-comp', template: '{{fieldOne}}{{fieldTwo}}', directives: [])
-class TestComponent {
- String fieldOne;
- String fieldTwo;
-}
-''';
- final source = newSource('/test.dart', code);
- // compute navigation regions
- final result = await resolveDart(source);
- new AngularNavigation(angularDriver.contentOverlay).computeNavigation(
- new AngularNavigationRequest(
- null, 'fieldOne'.length, code.indexOf('fieldOne}}'), result),
- collector,
- templatesOnly: false);
- _findRegionString('fieldOne', '}}');
- expect(region.targetKind, protocol.ElementKind.UNKNOWN);
- expect(targetLocation.file, '/test.dart');
- expect(targetLocation.offset, code.indexOf('fieldOne;'));
-
- expect(regions, hasLength(1));
- }
-
- void _findRegion(int offset, int length) {
- for (final region in regions) {
- if (region.offset == offset && region.length == length) {
- this.region = region;
- targetLocation = region.targetLocation;
- return;
- }
- }
- final regionsString = regions.join('\n');
- fail('Unable to find a region at ($offset, $length) in $regionsString');
- }
-
- void _findRegionString(String str, String suffix,
- {final String codeOverride}) {
- final code = codeOverride != null ? codeOverride : this.code;
- final search = '$str$suffix';
- final offset = code.indexOf(search);
- expect(offset, isNonNegative, reason: 'Cannot find |$search| in |$code|');
- _findRegion(offset, str.length);
- }
-}
-
-/// Instances of the class [GatheringErrorListener] implement an error listener
-/// that collects all of the errors passed to it for later examination.
-class GatheringErrorListener implements AnalysisErrorListener {
- /// A list containing the errors that were collected.
- final _errors = <AnalysisError>[];
-
- void addAll(List<AnalysisError> errors) {
- for (final error in errors) {
- onError(error);
- }
- }
-
- @override
- void onError(AnalysisError error) {
- _errors.add(error);
- }
-}
-
-class NavigationCollectorMock extends Mock implements NavigationCollector {}
-
-class SourceMock extends Mock implements Source {
- final String fullPath;
-
- SourceMock([String name = 'mocked.dart']) : fullPath = name;
-
- @override
- String toString() => fullPath;
-}
-
-class _RecordedNavigationRegion {
- final int offset;
- final int length;
- final protocol.ElementKind targetKind;
- final protocol.Location targetLocation;
-
- _RecordedNavigationRegion(
- this.offset, this.length, this.targetKind, this.targetLocation);
-
- @override
- String toString() => '$offset $length $targetKind $targetLocation';
-}
diff --git a/angular_analyzer_plugin/test/occurrences_test.dart b/angular_analyzer_plugin/test/occurrences_test.dart
deleted file mode 100644
index 32b7090..0000000
--- a/angular_analyzer_plugin/test/occurrences_test.dart
+++ /dev/null
@@ -1,109 +0,0 @@
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-void main() {
- defineReflectiveSuite(() {
- // TODO get this working with new plugin arch
- //defineReflectiveTests(AngularOccurrencesContributorTest);
- defineReflectiveTests(EmptyTest);
- });
-}
-
-@reflectiveTest
-class EmptyTest {
- // ignore: non_constant_identifier_names
- void test_soTheSuitePasses() {
- expect(null, isNull);
- }
-}
-// TODO get this working with new plugin arch
-//@reflectiveTest
-//class AngularOccurrencesContributorTest extends AbstractAngularTest {
-// String code;
-//
-// OccurrencesCollector collector = new OccurrencesCollectorMock();
-// List<protocol.Occurrences> occurrencesList = <protocol.Occurrences>[];
-//
-// protocol.Occurrences occurrences;
-//
-// @override
-// void setUp() {
-// super.setUp();
-// when(collector.addOccurrences(anyObject)).thenAnswer(occurrencesList.add);
-// }
-//
-// // ignore: non_constant_identifier_names
-// void test_dart_templates() {
-// code = r'''
-//import 'package:angular/src/core/metadata.dart';
-//
-//@Component(selector: 'text-panel', inputs: const ['text: my-text'])
-//@View(template: r"<div>some text</div>")
-//class TextPanel {
-// String text; // 1
-//}
-//
-//@Component(selector: 'UserPanel')
-//@View(template: r"""
-//<div>
-// <text-panel [my-text]='user.value'></text-panel> // cl
-//</div>
-//""", directives: [TextPanel])
-//class UserPanel {
-// ObjectContainer<String> user; // 2
-//}
-//
-//class ObjectContainer<T> {
-// T value; // 3
-//}
-//''';
-// final source = newSource('/test.dart', code);
-// //LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-// //computeResult(target, DART_TEMPLATES);
-// // compute navigation regions
-// new AngularOccurrencesContributor()
-// .computeOccurrences(collector, null, source);
-// // "text" field
-// {
-// _findOccurrences(code.indexOf('text: my-text'));
-// expect(occurrences.element.name, 'text');
-// expect(occurrences.length, 'text'.length);
-// expect(occurrences.offsets, contains(code.indexOf('text; // 1')));
-// }
-// // "text-panel" component
-// {
-// _findOccurrences(code.indexOf("text-panel', "));
-// expect(occurrences.element.name, 'text-panel');
-// expect(occurrences.length, 'text-panel'.length);
-// expect(occurrences.offsets, contains(code.indexOf("text-panel [")));
-// expect(occurrences.offsets, contains(code.indexOf("text-panel> // cl")));
-// }
-// // "user" field
-// {
-// _findOccurrences(code.indexOf("user.value'><"));
-// expect(occurrences.element.name, 'user');
-// expect(occurrences.length, 'user'.length);
-// expect(occurrences.offsets, contains(code.indexOf('user; // 2')));
-// }
-// // "value" field
-// {
-// _findOccurrences(code.indexOf("value'><"));
-// expect(occurrences.element.name, 'value');
-// expect(occurrences.length, 'value'.length);
-// expect(occurrences.offsets, contains(code.indexOf('value; // 3')));
-// }
-// }
-//
-// void _findOccurrences(int offset) {
-// for (final occurrences in occurrencesList) {
-// if (occurrences.offsets.contains(offset)) {
-// this.occurrences = occurrences;
-// return;
-// }
-// }
-// final listStr = occurrencesList.join('\n');
-// fail('Unable to find occurrences at $offset in $listStr');
-// }
-//}
-//
-//class OccurrencesCollectorMock extends Mock implements OccurrencesCollector {}
diff --git a/angular_analyzer_plugin/test/offsetting_constant_value_visitor_test.dart b/angular_analyzer_plugin/test/offsetting_constant_value_visitor_test.dart
deleted file mode 100644
index b1d3f3b..0000000
--- a/angular_analyzer_plugin/test/offsetting_constant_value_visitor_test.dart
+++ /dev/null
@@ -1,167 +0,0 @@
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart' as utils;
-import 'package:analyzer/src/dart/scanner/reader.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/source/source_resource.dart' show FileSource;
-import 'package:angular_analyzer_plugin/src/tasks.dart';
-import 'package:mockito/mockito.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(OffsettingConstantValueVisitorTest);
- });
-}
-
-@reflectiveTest
-class OffsettingConstantValueVisitorTest {
- // ignore: non_constant_identifier_names
- void assertCaretOffsetIsPreserved(String code) {
- final pos = code.indexOf('^');
- expect(pos, greaterThan(-1), reason: 'the code should contain a caret');
-
- final expression = _parseDartExpression(code);
-
- final evaluator = new OffsettingConstantEvaluator();
- final value = expression.accept(evaluator);
-
- if (value is String) {
- expect(value.indexOf('^'), equals(pos),
- reason: "```$value``` moved the caret");
- } else {
- fail("Expected string, got $value");
- }
- }
-
- // ignore: non_constant_identifier_names
- void assertNotOffsettable(String code, {String at}) {
- final expression = _parseDartExpression(code);
- final pos = code.indexOf(at);
- final length = at.length;
- expect(pos, greaterThan(-1),
- reason: "```$code```` doesn't contain ```$at```");
-
- final evaluator = new OffsettingConstantEvaluator();
- expression.accept(evaluator);
- expect(evaluator.offsetsAreValid, isFalse);
- expect(evaluator.lastUnoffsettableNode, isNotNull);
- expect(evaluator.lastUnoffsettableNode.offset, equals(pos),
- reason: "The snippet didn't match the suspect node");
- expect(evaluator.lastUnoffsettableNode.length, equals(length),
- reason: "The snippet didn't match the suspect node");
- }
-
- // ignore: non_constant_identifier_names
- void test_adjacentStrings() {
- assertCaretOffsetIsPreserved("'my template^' 'which continues'");
- assertCaretOffsetIsPreserved("'my template' 'which continues ^'");
- assertCaretOffsetIsPreserved("r'my template' r'which continues ^'");
- assertCaretOffsetIsPreserved("'my template'\n 'which continues ^'");
- assertCaretOffsetIsPreserved("'no gap''then continue ^'");
- assertCaretOffsetIsPreserved("'' 'after empty string ^'");
- assertCaretOffsetIsPreserved(
- "'my template'\n\n 'which continues' ' and continues ^'");
- }
-
- // ignore: non_constant_identifier_names
- void test_computedStringsLookRight() {
- final expression =
- _parseDartExpression("('my template'\n) + 'which continues^'");
- final value = expression.accept(new OffsettingConstantEvaluator());
- expect(value, equals(" my template which continues^ "));
- }
-
- // ignore: non_constant_identifier_names
- void test_concatenatedAfterParenthesis() {
- assertCaretOffsetIsPreserved("('my template^') + 'which continues'");
- assertCaretOffsetIsPreserved("('my template') + 'which continues^'");
- assertCaretOffsetIsPreserved("('my template' ) + 'which continues^'");
- assertCaretOffsetIsPreserved("('my template'\n) + 'which continues^'");
- }
-
- // ignore: non_constant_identifier_names
- void test_concatenatedStrings() {
- assertCaretOffsetIsPreserved("'my template^' + 'which continues'");
- assertCaretOffsetIsPreserved("'my template' + 'which continues ^'");
- assertCaretOffsetIsPreserved("r'my template' + r'which continues ^'");
- assertCaretOffsetIsPreserved("'my template' +\n 'which continues ^'");
- assertCaretOffsetIsPreserved("'no gap'+'then continue ^'");
- assertCaretOffsetIsPreserved("'' + 'after empty string ^'");
- assertCaretOffsetIsPreserved(
- "'my template' +\n\n 'which continues' + ' and continues ^'");
- }
-
- // ignore: non_constant_identifier_names
- void test_error() {
- final expression = _parseDartExpression("1 + 'hello'");
- final value = expression.accept(new OffsettingConstantEvaluator());
- expect(value, equals(utils.ConstantEvaluator.NOT_A_CONSTANT));
- }
-
- // ignore: non_constant_identifier_names
- void test_notOffsettableGetter() {
- assertNotOffsettable(r"'hello' + world ", at: 'world');
- }
-
- // ignore: non_constant_identifier_names
- void test_notOffsettableInterp() {
- assertNotOffsettable(r"'hello $world'", at: 'world');
- }
-
- // ignore: non_constant_identifier_names
- void test_notOffsettableInterpExpr() {
- assertNotOffsettable(r"'hello ${world}'", at: 'world');
- }
-
- // ignore: non_constant_identifier_names
- void test_notOffsettableMethod() {
- assertNotOffsettable(r"'hello' + method() ", at: 'method()');
- }
-
- // ignore: non_constant_identifier_names
- void test_notOffsettablePrefixedIdent() {
- assertNotOffsettable(r"'hello' + prefixed.identifier ",
- at: 'prefixed.identifier');
- }
-
- // ignore: non_constant_identifier_names
- void test_notStringComputation() {
- final expression = _parseDartExpression("1 + 2");
- final value = expression.accept(new OffsettingConstantEvaluator());
- expect(value, equals(3));
- }
-
- void test_parenthesizedString() {
- assertCaretOffsetIsPreserved("('my template^')");
- assertCaretOffsetIsPreserved("( 'my template^')");
- assertCaretOffsetIsPreserved("( 'my template^')");
- assertCaretOffsetIsPreserved("(\n'my template^')");
- }
-
- void test_simpleString() {
- assertCaretOffsetIsPreserved("'my template^'");
- assertCaretOffsetIsPreserved("r'my template^'");
- assertCaretOffsetIsPreserved('"my template^"');
- assertCaretOffsetIsPreserved('r"my template^"');
- assertCaretOffsetIsPreserved("'''my template^'''");
- assertCaretOffsetIsPreserved("r'''my template^'''");
- }
-
- Expression _parseDartExpression(String code) {
- final token = _scanDartCode(code);
- final parser = new Parser(new _MockSource(), new BooleanErrorListener());
- return parser.parseExpression(token);
- }
-
- Token _scanDartCode(String code) {
- final reader = new CharSequenceReader(code);
- final scanner = new Scanner(null, reader, null);
- return scanner.tokenize();
- }
-}
-
-class _MockSource extends Mock implements FileSource {}
diff --git a/angular_analyzer_plugin/test/options_test.dart b/angular_analyzer_plugin/test/options_test.dart
deleted file mode 100644
index d032f8c..0000000
--- a/angular_analyzer_plugin/test/options_test.dart
+++ /dev/null
@@ -1,265 +0,0 @@
-import 'package:angular_analyzer_plugin/src/options.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(AngularOptionsTest);
- });
-}
-
-@reflectiveTest
-class AngularOptionsTest {
- // ignore: non_constant_identifier_names
- void test_buildEmpty() {
- final options = new AngularOptions.defaults();
- expect(options.customTagNames, isNotNull);
- expect(options.customTagNames, isEmpty);
- }
-
- // ignore: non_constant_identifier_names
- void test_buildExact() {
- final options = new AngularOptions(customTagNames: ['foo']);
- expect(options.customTagNames, isNotNull);
- expect(options.customTagNames, equals(['foo']));
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_defaults() {
- final options = new AngularOptions.fromString('''
-analyzer:
- plugins:
- - angular
-''', null);
- expect(options.customTagNames, isNotNull);
- expect(options.customTagNames, isEmpty);
- expect(options.customEvents, isNotNull);
- expect(options.customEvents, isEmpty);
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_defaults_emptyObject() {
- final options = new AngularOptions.fromString('''
-analyzer:
- plugins:
- - angular
-
-angular:
-''', null);
- expect(options.customTagNames, isNotNull);
- expect(options.customTagNames, isEmpty);
- expect(options.customEvents, isNotNull);
- expect(options.customEvents, isEmpty);
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_defaults_legacy_emptyObject() {
- final options = new AngularOptions.fromString('''
-analyzer:
- plugins:
- angular:
-''', null);
- expect(options.customTagNames, isNotNull);
- expect(options.customTagNames, isEmpty);
- expect(options.customEvents, isNotNull);
- expect(options.customEvents, isEmpty);
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_dynamic_events() {
- final code = '''
-analyzer:
- plugins:
- - angular
-
-angular:
- custom_events:
- foo:
- type: String
- bar:
- type: BarEvent
- path: 'package:foo/bar/baz.dart'
- empty:
-''';
- final options = new AngularOptions.fromString(code, null);
- expect(options.customEvents, isNotNull);
- expect(options.customEvents, hasLength(3));
-
- {
- final event = options.customEvents['foo'];
- expect(event, isNotNull);
- expect(event.name, 'foo');
- expect(event.typeName, 'String');
- expect(event.typePath, isNull);
- expect(event.nameOffset, code.indexOf('foo'));
- }
-
- {
- final event = options.customEvents['bar'];
- expect(event, isNotNull);
- expect(event.name, 'bar');
- expect(event.typeName, 'BarEvent');
- expect(event.typePath, 'package:foo/bar/baz.dart');
- expect(event.nameOffset, code.indexOf('bar'));
- }
-
- {
- final event = options.customEvents['empty'];
- expect(event, isNotNull);
- expect(event.name, 'empty');
- expect(event.typeName, null);
- expect(event.typePath, null);
- expect(event.nameOffset, code.indexOf('empty'));
- }
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_events_hashString() {
- final code = '''
-analyzer:
- plugins:
- angular:
- custom_events:
- foo:
- type: String
- bar:
- type: BarEvent
- path: 'package:foo/bar/baz.dart'
- empty:
-
-''';
- final options = new AngularOptions.fromString(code, null);
- expect(options.customEvents, isNotNull);
- expect(options.customEventsHashString,
- 'e:bar,BarEvent,package:foo/bar/baz.dart,empty,,,foo,String,,');
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_legacy_dynamic_events() {
- final code = '''
-analyzer:
- plugins:
- angular:
- custom_events:
- foo:
- type: String
- bar:
- type: BarEvent
- path: 'package:foo/bar/baz.dart'
- empty:
-
-''';
- final options = new AngularOptions.fromString(code, null);
- expect(options.customEvents, isNotNull);
- expect(options.customEvents, hasLength(3));
-
- {
- final event = options.customEvents['foo'];
- expect(event, isNotNull);
- expect(event.name, 'foo');
- expect(event.typeName, 'String');
- expect(event.typePath, isNull);
- expect(event.nameOffset, code.indexOf('foo'));
- }
-
- {
- final event = options.customEvents['bar'];
- expect(event, isNotNull);
- expect(event.name, 'bar');
- expect(event.typeName, 'BarEvent');
- expect(event.typePath, 'package:foo/bar/baz.dart');
- expect(event.nameOffset, code.indexOf('bar'));
- }
-
- {
- final event = options.customEvents['empty'];
- expect(event, isNotNull);
- expect(event.name, 'empty');
- expect(event.typeName, null);
- expect(event.typePath, null);
- expect(event.nameOffset, code.indexOf('empty'));
- }
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_legacy_mangledValueIgnored() {
- // TODO(mfairhurst) this should be an error/warning.
- // However, the most important thing is that we don't propagate the mangled
- // values which can cause later crashes.
- final options = new AngularOptions.fromString('''
-analyzer:
- plugins:
- angular:
- custom_tag_names: true
-''', null);
- expect(options.customTagNames, isNotNull);
- expect(options.customTagNames, const TypeMatcher<List>());
- expect(options.customTagNames, isEmpty);
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_legacy_selfLoading() {
- final options = new AngularOptions.fromString('''
-analyzer:
- plugins:
- angular_analyzer_plugin:
- custom_tag_names:
- - foo
- - bar
- - baz
-
-''', null);
- expect(options.customTagNames, isNotNull);
- expect(options.customTagNames, equals(['foo', 'bar', 'baz']));
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_legacy_simple_tags() {
- final options = new AngularOptions.fromString('''
-analyzer:
- plugins:
- angular:
- custom_tag_names:
- - foo
- - bar
- - baz
-''', null);
- expect(options.customTagNames, isNotNull);
- expect(options.customTagNames, equals(['foo', 'bar', 'baz']));
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_mangledValueIgnored() {
- // TODO(mfairhurst) this should be an error/warning.
- // However, the most important thing is that we don't propagate the mangled
- // values which can cause later crashes.
- final options = new AngularOptions.fromString('''
-analyzer:
- plugins:
- - angular
-
-angular:
- custom_tag_names: true
-''', null);
- expect(options.customTagNames, isNotNull);
- expect(options.customTagNames, const TypeMatcher<List>());
- expect(options.customTagNames, isEmpty);
- }
-
- // ignore: non_constant_identifier_names
- void test_buildYaml_simple_tags() {
- final options = new AngularOptions.fromString('''
-analyzer:
- plugins:
- - angular
-
-angular:
- custom_tag_names:
- - foo
- - bar
- - baz
-''', null);
- expect(options.customTagNames, isNotNull);
- expect(options.customTagNames, equals(['foo', 'bar', 'baz']));
- }
-}
diff --git a/angular_analyzer_plugin/test/plugin_test.dart b/angular_analyzer_plugin/test/plugin_test.dart
deleted file mode 100644
index 1152c60..0000000
--- a/angular_analyzer_plugin/test/plugin_test.dart
+++ /dev/null
@@ -1,305 +0,0 @@
-import 'dart:async';
-
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer_plugin/channel/channel.dart';
-import 'package:analyzer_plugin/protocol/protocol.dart' as protocol;
-import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
-import 'package:analyzer_plugin/protocol/protocol_generated.dart' as protocol;
-import 'package:angular_analyzer_plugin/plugin.dart';
-import 'package:angular_analyzer_plugin/src/angular_driver.dart';
-import 'package:mockito/mockito.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'mock_angular.dart';
-import 'mock_sdk.dart';
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(PluginIntegrationTest);
- defineReflectiveTests(PluginCreateDriverTest);
- defineReflectiveTests(AnalysisOptionsUtilsTest);
- });
-}
-
-/// Unfortunately, package:yaml doesn't support dumping to yaml. So this is
-/// what we are stuck with, for now. Put it in a base class so we can test it
-class AnalysisOptionsUtilsBase extends PluginIntegrationTestBase {
- String optionsHeader = '''
-analyzer:
- plugins:
-''';
-
- void enableAnalyzerPluginsAngular({List<String> extraOptions = const []}) =>
- setOptionsFileContent(optionsHeader +
- optionsSection('angular', extraOptions: extraOptions));
-
- void enableAnalyzerPluginsAngularPlugin(
- {List<String> extraOptions = const []}) =>
- setOptionsFileContent(optionsHeader +
- optionsSection('angular_analyzer_plugin',
- extraOptions: extraOptions));
-
- String optionsSection(String key, {List<String> extraOptions = const []}) =>
- '''
- $key:${extraOptions.map((option) => "\n $option").join('')}\n
-''';
-
- void setOptionsFileContent(String content) {
- resourceProvider.newFile('/test/analysis_options.yaml', content);
- }
-}
-
-/// Since our yaml generation is...not ideal, let's test it.
-@reflectiveTest
-class AnalysisOptionsUtilsTest extends AnalysisOptionsUtilsBase {
- // ignore: non_constant_identifier_names
- void test_enableAnalyzerPluginsAngular_extraOptions() {
- enableAnalyzerPluginsAngular(extraOptions: ['foo: bar', 'baz:', ' - qux']);
- final optionsText = resourceProvider
- .getFile('/test/analysis_options.yaml')
- .readAsStringSync();
-
- expect(optionsText, '''
-analyzer:
- plugins:
- angular:
- foo: bar
- baz:
- - qux
-
-''');
- }
-
- // ignore: non_constant_identifier_names
- void test_enableAnalyzerPluginsAngular_noExtraOptions() {
- enableAnalyzerPluginsAngular();
- final optionsText = resourceProvider
- .getFile('/test/analysis_options.yaml')
- .readAsStringSync();
-
- expect(optionsText, '''
-analyzer:
- plugins:
- angular:
-
-''');
- }
-
- void test_enableAnalyzerPluginsAngularPlugin_extraOptions() {
- enableAnalyzerPluginsAngularPlugin(
- extraOptions: ['foo: bar', 'baz:', ' - qux']);
- final optionsText = resourceProvider
- .getFile('/test/analysis_options.yaml')
- .readAsStringSync();
-
- expect(optionsText, '''
-analyzer:
- plugins:
- angular_analyzer_plugin:
- foo: bar
- baz:
- - qux
-
-''');
- }
-
- // ignore: non_constant_identifier_names
- /// Since our yaml generation is...not ideal, let's test it.
- // ignore: non_constant_identifier_names
- void test_enableAnalyzerPluginsAngularPlugin_noExtraOptions() {
- enableAnalyzerPluginsAngularPlugin();
- final optionsText = resourceProvider
- .getFile('/test/analysis_options.yaml')
- .readAsStringSync();
-
- expect(optionsText, '''
-analyzer:
- plugins:
- angular_analyzer_plugin:
-
-''');
- }
-}
-
-class MockPluginCommunicationChannel extends Mock
- implements PluginCommunicationChannel {}
-
-class MockResourceProvider extends Mock implements ResourceProvider {}
-
-class NamedNavigationNotificationMatcher implements Matcher {
- final String filename;
-
- NamedNavigationNotificationMatcher(this.filename);
-
- @override
- Description describe(Description description) =>
- description..add('that is a navigation notification for file $filename');
-
- @override
- Description describeMismatch(item, Description mismatchDescription,
- Map matchState, bool verbose) =>
- mismatchDescription
- ..add('is not a navigation notification for file $filename');
-
- @override
- bool matches(item, Map matchState) =>
- item is protocol.Notification &&
- item.event == 'analysis.navigation' &&
- item.params['file'] == filename;
-}
-
-@reflectiveTest
-class PluginCreateDriverTest extends AnalysisOptionsUtilsBase {
- // ignore: non_constant_identifier_names
- void test_createAnalysisDriver() {
- enableAnalyzerPluginsAngular();
- final driver = plugin.createAnalysisDriver(root) as AngularDriver;
-
- expect(driver, isNotNull);
- expect(driver.byteStore, isNotNull);
- }
-
- // ignore: non_constant_identifier_names
- void test_createAnalysisDriver_containsDartDriver() {
- enableAnalyzerPluginsAngular();
- final driver = plugin.createAnalysisDriver(root) as AngularDriver;
-
- expect(driver, isNotNull);
- expect(driver.dartDriver, isNotNull);
- expect(driver.dartDriver.analysisOptions, isNotNull);
- expect(driver.dartDriver.fsState, isNotNull);
- expect(driver.dartDriver.name, equals("/test"));
- expect(driver.dartDriver.sourceFactory, isNotNull);
- expect(driver.dartDriver.contextRoot, isNotNull);
- }
-
- // ignore: non_constant_identifier_names
- void test_createAnalysisDriver_customTagNames() {
- enableAnalyzerPluginsAngular(extraOptions: [
- 'custom_tag_names:',
- ' - foo',
- ' - bar',
- ' - baz',
- ]);
- final driver = plugin.createAnalysisDriver(root) as AngularDriver;
-
- expect(driver, isNotNull);
- expect(driver.options, isNotNull);
- expect(driver.options.customTagNames, isNotNull);
- expect(driver.options.customTagNames, equals(['foo', 'bar', 'baz']));
- }
-
- // ignore: non_constant_identifier_names
- void test_createAnalysisDriver_customTagNames_pluginSelfLoader() {
- enableAnalyzerPluginsAngularPlugin(extraOptions: [
- 'custom_tag_names:',
- ' - foo',
- ' - bar',
- ' - baz',
- ]);
- final driver = plugin.createAnalysisDriver(root) as AngularDriver;
-
- expect(driver, isNotNull);
- expect(driver.options, isNotNull);
- expect(driver.options.customTagNames, isNotNull);
- expect(driver.options.customTagNames, equals(['foo', 'bar', 'baz']));
- }
-
- // ignore: non_constant_identifier_names
- void test_createAnalysisDriver_defaultOptions() {
- enableAnalyzerPluginsAngular();
- final driver = plugin.createAnalysisDriver(root) as AngularDriver;
-
- expect(driver, isNotNull);
- expect(driver.options, isNotNull);
- expect(driver.options.customTagNames, isNotNull);
- expect(driver.options.customTagNames, isEmpty);
- }
-}
-
-@reflectiveTest
-class PluginIntegrationTest extends PluginIntegrationTestBase {
- @override
- void setUp() async {
- super.setUp();
-
- addAngularSources((filename, [contents = ""]) =>
- resourceProvider.newFile(filename, contents));
- resourceProvider.newFile('/test/.packages', 'angular:/angular/');
- plugin.start(mockChannel);
- await plugin.handleAnalysisSetContextRoots(
- new protocol.AnalysisSetContextRootsParams([root]));
- }
-
- // ignore: non_constant_identifier_names
- void test_navigation_dart() async {
- resourceProvider.newFile('/test/test.dart', r'''
-import 'package:angular/angular.dart';
-@Component(
- selector: 'foo'
-)
-class MyComponent {}
-''');
-
- await (plugin.driverForPath('/test/test.dart') as AngularDriver)
- .requestDartResult('/test/test.dart');
- verifyNever(mockChannel.sendNotification(
- argThat(new NamedNavigationNotificationMatcher('/test/test.dart'))));
-
- await plugin.handleAnalysisSetSubscriptions(
- new protocol.AnalysisSetSubscriptionsParams({
- protocol.AnalysisService.NAVIGATION: ['/test/test.dart']
- }));
-
- await Future.delayed(const Duration(milliseconds: 300));
- verify(mockChannel.sendNotification(
- argThat(new NamedNavigationNotificationMatcher('/test/test.dart'))));
- }
-
- // ignore: non_constant_identifier_names
- void test_navigation_html() async {
- resourceProvider..newFile('/test/test.dart', r'''
-import 'package:angular/angular.dart';
-@Component(
- selector: 'foo'
- templateUrl: 'test.html';
-)
-class MyComponent {}
-''')..newFile('/test/test.html', '');
-
- final driver = (plugin.driverForPath('/test/test.dart') as AngularDriver);
- await driver.requestDartResult('/test/test.dart');
- await driver.requestHtmlResult('/test/test.html');
- verifyNever(mockChannel.sendNotification(
- argThat(new NamedNavigationNotificationMatcher('/test/test.html'))));
-
- await plugin.handleAnalysisSetSubscriptions(
- new protocol.AnalysisSetSubscriptionsParams({
- protocol.AnalysisService.NAVIGATION: ['/test/test.html']
- }));
-
- await Future.delayed(const Duration(milliseconds: 300));
- verify(mockChannel.sendNotification(
- argThat(new NamedNavigationNotificationMatcher('/test/test.html'))));
- }
-}
-
-class PluginIntegrationTestBase {
- AngularAnalyzerPlugin plugin;
- MemoryResourceProvider resourceProvider;
- PluginCommunicationChannel mockChannel;
- protocol.ContextRoot root;
- void setUp() {
- resourceProvider = new MemoryResourceProvider();
- new MockSdk(resourceProvider: resourceProvider);
- plugin = new AngularAnalyzerPlugin(resourceProvider);
- final versionCheckParams = new protocol.PluginVersionCheckParams(
- "~/.dartServer/.analysis-driver", "/sdk", "1.0.0");
- plugin.handlePluginVersionCheck(versionCheckParams);
- root = new protocol.ContextRoot("/test", [],
- optionsFile: '/test/analysis_options.yaml');
- mockChannel = new MockPluginCommunicationChannel();
- }
-}
diff --git a/angular_analyzer_plugin/test/resolver_test.dart b/angular_analyzer_plugin/test/resolver_test.dart
deleted file mode 100644
index 1914242..0000000
--- a/angular_analyzer_plugin/test/resolver_test.dart
+++ /dev/null
@@ -1,5901 +0,0 @@
-import 'dart:async';
-
-import 'package:analyzer/src/dart/error/syntactic_errors.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/ast.dart';
-import 'package:angular_analyzer_plugin/errors.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-import 'package:angular_analyzer_plugin/src/tuple.dart';
-import 'package:angular_ast/angular_ast.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'abstract_angular.dart';
-import 'element_assert.dart';
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(TemplateResolverTest);
- });
-}
-
-void assertPropertyElement(AngularElement element,
- {nameMatcher, sourceMatcher}) {
- expect(element, const TypeMatcher<InputElement>());
- final inputElement = element;
- if (nameMatcher != null) {
- expect(inputElement.name, nameMatcher);
- }
- if (sourceMatcher != null) {
- expect(inputElement.source.fullName, sourceMatcher);
- }
-}
-
-typedef bool ElementSearchFn(ElementInfo info);
-
-class ElementSearch extends AngularAstVisitor {
- ElementInfo element;
- ElementSearchFn searchFn;
-
- ElementSearch(this.searchFn);
-
- @override
- void visitElementInfo(ElementInfo info) {
- if (searchFn(info)) {
- element = info;
- } else {
- super.visitElementInfo(info);
- }
- }
-}
-
-@reflectiveTest
-class TemplateResolverTest extends AbstractAngularTest {
- String dartCode;
- String htmlCode;
- Source dartSource;
- Source htmlSource;
-
- List<AbstractDirective> directives;
-
- Template template;
- List<ResolvedRange> ranges;
-
- // ignore: non_constant_identifier_names
- Future test_angleBracketInMustacheNoCrash_githubBug204() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""
-{{<}}
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertErrorsWithCodes([
- ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TYPE_NAME,
- StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT,
- AngularWarningCode.DISALLOWED_EXPRESSION
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_attribute_mixedCase() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- _addHtmlSource(r"""
-<svg viewBox='0, 0, 24 24'></svg>
-""");
- await _resolveSingleTemplate(dartSource);
- expect(ranges, hasLength(0));
- }
-
- // ignore: non_constant_identifier_names
- Future test_attributeInterpolation() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String aaa; // 1
- String bbb; // 2
-}
-''');
- _addHtmlSource(r"""
-<span title='Hello {{aaa}} and {{bbb}}!'></span>
-""");
- await _resolveSingleTemplate(dartSource);
- expect(ranges, hasLength(2));
- _assertElement('aaa}}').dart.getter.at('aaa; // 1');
- _assertElement('bbb}}').dart.getter.at('bbb; // 2');
- }
-
- // ignore: non_constant_identifier_names
- Future test_attributeReference() async {
- _addDartSource(r'''
-@Component(selector: 'name-panel', template: r"<div>AAA</div>")
-class NamePanel {
- NamePanel(@Attribute("name-panel-attr") String namePanelAttr);
-}
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NamePanel])
-class TestPanel {}
-''');
- _addHtmlSource(r"""
-<name-panel name-panel-attr="foo"></name-panel>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement("name-panel-attr=")
- .angular
- .inFileName('/test_panel.dart')
- .at("namePanelAttr");
- }
-
- // ignore: non_constant_identifier_names
- Future test_catchPkgHtmlGithubBug44() async {
- // see https://github.com/dart-lang/html/issues/44
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String aaa; // 1
- String bbb; // 2
-}
-''');
- _addHtmlSource(r"""<button attr<="value"></button>""");
- await _resolveSingleTemplate(dartSource);
-
- // no assertion...this throws in the github bug
- }
-
- // ignore: non_constant_identifier_names
- Future test_customDirective_asTemplateAttrOk() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [CustomTemplateDirective])
-class TestPanel {
-}
-
-@Directive(selector: '[customTemplateDirective]')
-class CustomTemplateDirective {
- CustomTemplateDirective(TemplateRef tpl);
-}
-''');
- final code = r"""
-<div template="customTemplateDirective"></div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_customDirective_noStarError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [CustomTemplateDirective])
-class TestPanel {
-}
-
-@Directive(selector: '[customTemplateDirective]')
-class CustomTemplateDirective {
- CustomTemplateDirective(TemplateRef tpl);
-}
-''');
- final code = r"""
-<div customTemplateDirective></div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.CUSTOM_DIRECTIVE_MAY_REQUIRE_TEMPLATE,
- code,
- "<div customTemplateDirective>");
- }
-
- // ignore: non_constant_identifier_names
- Future test_customDirective_starDoesntTakeTemplateError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NotTemplateDirective])
-class TestPanel {
-}
-
-@Directive(selector: '[notTemplateDirective]')
-class NotTemplateDirective {
-}
-''');
- final code = r"""
-<div *notTemplateDirective></div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.TEMPLATE_ATTR_NOT_USED, code,
- "*notTemplateDirective");
- }
-
- // ignore: non_constant_identifier_names
- Future test_customDirective_templateDoesntTakeTemplateError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NotTemplateDirective])
-class TestPanel {
-}
-
-@Directive(selector: '[notTemplateDirective]')
-class NotTemplateDirective {
-}
-''');
- final code = r"""
-<div template="notTemplateDirective"></div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TEMPLATE_ATTR_NOT_USED, code, 'template');
- }
-
- // ignore: non_constant_identifier_names
- Future test_customDirective_withStarOk() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [CustomTemplateDirective])
-class TestPanel {
-}
-
-@Directive(selector: '[customTemplateDirective]')
-class CustomTemplateDirective {
- CustomTemplateDirective(TemplateRef tpl);
-}
-''');
- final code = r"""
-<div *customTemplateDirective></div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_erroroneousTemplate_starHash_noCrash() async {
- _addDartSource(r'''
-import 'dart:html';
-
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(Element e) {}
-}
-''');
- _addHtmlSource(r"""
-<h1 (click)='handleClick(myTargetElement)'>
- <div *#myTargetElement></div>
-</h1>
-""");
- await _resolveSingleTemplate(dartSource);
- // no assertion. Just don't crash.
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_attrBinding_expressionTypeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int pixels;
-}
-''');
- final code = r"""
-<span [attr.aria]='pixels.length'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticTypeWarningCode.UNDEFINED_GETTER, code, "length");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_attrBinding_valid() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r"""
-<span [attr.aria-title]='text'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_attrBindingIf_attrNotBound() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- bool cond;
-}
-''');
- final code = r"""
-<span [attr.foo.if]='cond'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.UNMATCHED_ATTR_IF_BINDING, code, 'foo');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_attrBindingIf_empty() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text1;
-}
-''');
- final code = r"""
-<span [attr.foo]='text1' [attr.foo.if]></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.EMPTY_BINDING, code, '[attr.foo.if]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_attrBindingIf_emptyWithQuotes() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text1;
-}
-''');
- final code = r"""
-<span [attr.foo]='text1' [attr.foo.if]=''></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.EMPTY_BINDING, code, '[attr.foo.if]');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_attrBindingIf_typeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text1;
- String text2;
-}
-''');
- final code = r"""
-<span [attr.foo]='text1' [attr.foo.if]='text2'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.ATTR_IF_BINDING_TYPE_ERROR, code, 'text2');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_attrBindingIf_valid() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text;
- bool cond;
-}
-''');
- final code = r"""
-<span [attr.foo]='text' [attr.foo.if]='cond'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_classBinding_invalidClassName() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String title;
-}
-''');
- final code = r"""
-<span [class.invalid.class]='title == null'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.INVALID_HTML_CLASSNAME, code, "invalid.class");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_classBinding_typeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String notBoolean;
-}
-''');
- final code = r"""
-<span [class.aria]='notBoolean'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.CLASS_BINDING_NOT_BOOLEAN, code, "notBoolean");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_classBinding_valid() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r"""
-<span [class.my-class]='text == null'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_detect_eof_ellipsis_in_moustache() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String name = "TestPanel";
-}
-''');
- final code = r"""
-<p>{{name...}}</p>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TRAILING_EXPRESSION, code, "...");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_detect_eof_ellipsis_in_property_binding() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int a = 1;
- int b = 1;
-}
-''');
- final code = r"""
-<div [class.selected]="a==b..."></div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TRAILING_EXPRESSION, code, "...");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_detect_eof_post_semicolon_in_moustache() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String name = "TestPanel";
-}
-''');
-
- final code = r"""
-<p>{{name; bad portion}}</p>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TRAILING_EXPRESSION, code, "; bad portion");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_detect_eof_post_semicolon_in_property_binding() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int a = 1;
- int b = 1;
-}
-''');
-
- final code = r"""
-<div [class.selected]="a == b; bad portion"></div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TRAILING_EXPRESSION, code, "; bad portion");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_eventBinding() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- _addHtmlSource(r"""
-<div (click)='handleClick($event)'></div>
-""");
- await _resolveSingleTemplate(dartSource);
- expect(ranges, hasLength(3));
- _assertElement('click)').output.inCoreHtml;
- _assertElement('handleClick').dart.method.at('handleClick(MouseEvent');
-
- errorListener.assertNoErrors();
- final search = new ElementSearch((e) => e.localName == "div");
- template.ast.accept(search);
-
- expect(search.element, isNotNull);
- expect(search.element.boundStandardOutputs, hasLength(1));
- expect(search.element.boundStandardOutputs.first.boundOutput.name, 'click');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_eventBinding_on() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- _addHtmlSource(r"""
-<div on-click='handleClick()'></div>
-""");
- await _resolveSingleTemplate(dartSource);
- expect(ranges, hasLength(2));
- _assertElement('click=').output.inCoreHtml;
- _assertElement('handleClick()').dart.method.at('handleClick(MouseEvent');
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_expression_input_genericDirective_lowerBoundChainTypeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [GenericComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- int notString;
-}
-@Component(selector: 'generic-comp', template: '')
-class GenericComponent<T extends O, O extends String> {
- @Input() T string;
-}
-''');
- final code = r"""
-<generic-comp [string]="notString"></generic-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR, code, "notString");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_expression_input_genericDirective_lowerBoundNestedTypeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [GenericComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- List<int> notStringList;
-}
-@Component(selector: 'generic-comp', template: '')
-class GenericComponent<T extends String> {
- @Input() List<T> stringList;
-}
-''');
- final code = r"""
-<generic-comp [stringList]="notStringList"></generic-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR, code, "notStringList");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_expression_inputAndOutputBinding_extendGenericUnbounded_ok() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [GenericComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String string;
-}
-class Generic<T> {
- @Output()
- EventEmitter<T> output;
- @Input()
- T input;
-
- @Output()
- EventEmitter<T> twoWayChange;
- @Input()
- T twoWay;
-}
-@Component(selector: 'generic-comp', template: '')
-class GenericComponent<T> extends Generic {
-}
-''');
- final code = r"""
-<generic-comp (output)='$event.length' [input]="string" [(twoWay)]="string"></generic-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_expression_inputAndOutputBinding_genericDirective_chain_ok() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [GenericComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String string;
-}
-@Component(selector: 'generic-comp', template: '')
-class GenericComponent<T extends E, E> {
- @Output() EventEmitter<T> output;
- @Input() T input;
-
- @Output() EventEmitter<T> twoWayChange;
- @Input() T twoWay;
-}
-''');
- final code = r"""
-<generic-comp (output)='$event.length' [input]="string" [(twoWay)]="string"></generic-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_expression_inputAndOutputBinding_genericDirective_nested_ok() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [GenericComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- List<String> stringList;
-}
-@Component(selector: 'generic-comp', template: '')
-class GenericComponent<T> {
- @Output() EventEmitter<List<T>> output;
- @Input() List<T> input;
-
- @Output() EventEmitter<List<T>> twoWayChange;
- @Input() List<T> twoWay;
-}
-''');
- final code = r"""
-<generic-comp (output)='$event[0].length' [input]="stringList" [(twoWay)]="stringList"></generic-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputAndOutputBinding_genericDirective_ok() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [GenericComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String string;
-}
-@Component(selector: 'generic-comp', template: '')
-class GenericComponent<T> {
- @Output() EventEmitter<T> output;
- @Input() T input;
-
- @Output() EventEmitter<T> twoWayChange;
- @Input() T twoWay;
-}
-''');
- final code = r"""
-<generic-comp (output)='$event.length' [input]="string" [(twoWay)]="string"></generic-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_expression_inputAndOutputBinding_genericDirectiveChild_ok() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [GenericComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String string;
-}
-class Generic<T> {
- @Output()
- EventEmitter<T> output;
- @Input()
- T input;
-
- @Output()
- EventEmitter<T> twoWayChange;
- @Input()
- T twoWay;
-}
-@Component(selector: 'generic-comp', template: '')
-class GenericComponent<T> extends Generic<T> {
-}
-''');
- final code = r"""
-<generic-comp (output)='$event.length' [input]="string" [(twoWay)]="string"></generic-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_alt_standardHtml() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r"""
-<span [class]='text' [innerHtml]='text'></span>
-""";
- await angularDriver.getStandardHtml();
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_asBool_typeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() bool boolInput;
-}
-''');
-
- final code = r"""
-<title-comp boolInput="foo bar baz"></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.STRING_STYLE_INPUT_BINDING_INVALID,
- code,
- "boolInput");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_asBoool_noError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() bool boolInput;
-}
-''');
-
- final code = r"""
-<title-comp boolInput></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_asString() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() String title;
-}
-''');
- final code = r"""
-<title-comp title='anything can go here' id="some id"></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement('title=').input.inFileName('/test_panel.dart').at('title;');
- _assertElement('id=').input.inCoreHtml;
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_asString_fromDynamic() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- bool _title;
- @Input()
- set title(value) {
- _title = value == "" ? true : false;
- }
- bool get title => _title;
-}
-''');
-
- final code = r"""
-<title-comp title='anything can go here'></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement('title=').input.inFileName('/test_panel.dart').at('title(');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_asString_typeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() int titleInput;
-}
-''');
-
- final code = r"""
-<title-comp titleInput='string binding'></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.STRING_STYLE_INPUT_BINDING_INVALID,
- code,
- "titleInput");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_bind() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-''');
- _addHtmlSource(r"""
-<span bind-title='text'></span>
-""");
- await _resolveSingleTemplate(dartSource);
- expect(ranges, hasLength(1));
- _assertElement("text'>").dart.getter.at('text; // 1');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_boundToNothing() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r"""
-<span [title]='text'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.NONEXIST_INPUT_BOUND, code, "title");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_doesntNeedSafeBinding() async {
- _addDartSource(r'''
-import 'package:angular/security.dart';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- SafeHtml html;
- SafeUrl url;
- SafeStyle style;
- SafeResourceUrl resourceUrl;
-}
-''');
- final code = r"""
-<a [class]='html'></a>
-<a [class]='url'></a>
-<a [class]='style'></a>
-<a [class]='resourceUrl'></a>
-""";
- await angularDriver.getStandardHtml();
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertErrorsWithCodes([
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR,
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR,
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR,
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR,
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_duplicate_standardHtml() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [MyTagComponent])
-class TestPanel {}
-@Component(selector: 'my-tag', template: '')
-class MyTagComponent {
- @Input()
- String readonly;
-}
-''');
- final code = r'''
-<my-tag [readonly]="'blah'"></my-tag>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_empty() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() int title;
-}
-''');
- final code = r"""
-<title-comp [title]=""></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.EMPTY_BINDING, code, "[title]");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_expression_inputBinding_genericDirective_lowerBoundTypeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [GenericComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- int notString;
-}
-@Component(selector: 'generic-comp', template: '')
-class GenericComponent<T extends String> {
- @Input() T string;
-}
-''');
- final code = r"""
-<generic-comp [string]="notString"></generic-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR, code, "notString");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_hardcodedDoesntNeedSanitization() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String unsafe;
-}
-''');
- final code = r"""
-<iframe src='this does no sanitization and succeeds'></iframe>
-""";
- await angularDriver.getStandardHtml();
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_nativeHtml_asString_notTypeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [],
- templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
-<div hidden="allowed because becomes addAttribute() rather than .hidden="></div>
-<img width="allowed because becomes addAttribute() rather than .width=" />
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_noEvent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
-<h1 [hidden]="$event">
-</h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.UNDEFINED_IDENTIFIER, code, r"$event");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_noValue() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() int title;
-}
-''');
- final code = r"""
-<title-comp [title]></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.EMPTY_BINDING, code, "[title]");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_orig_standardHtml() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r"""
-<span [className]='text' [innerHTML]='text'></span>
-""";
- await angularDriver.getStandardHtml();
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_safeBindings() async {
- _addDartSource(r'''
-import 'package:angular/security.dart';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- SafeHtml html;
- SafeUrl url;
- SafeStyle style;
- SafeResourceUrl resourceUrl;
-}
-''');
- final code = r"""
-<a [innerHtml]='html' [innerHTML]='html' [href]='url'></a>
-<iframe [src]='resourceUrl'></iframe><!-- TODO test [style]='style' -->
-""";
- await angularDriver.getStandardHtml();
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_typeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() int title;
-}
-''');
- final code = r"""
-<title-comp [title]='text'></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR, code, "text");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_unsafelyBound() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String unsafe;
-}
-''');
- final code = r"""
-<iframe [src]='unsafe'></iframe>
-""";
- await angularDriver.getStandardHtml();
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.UNSAFE_BINDING, code, 'unsafe');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_unsafelyBoundViaMustache() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String unsafe;
-}
-''');
- final code = r"""
-<iframe src='this is ok until we bind {{unsafe}}'></iframe>
-""";
- await angularDriver.getStandardHtml();
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.UNSAFE_BINDING, code,
- 'this is ok until we bind {{unsafe}}');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_valid() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Directive(selector: '[titled]', template: '')
-class TitleComponent {
- @Input() String title;
-}
-''');
- _addHtmlSource(r"""
-<span titled [title]='text'></span>
-""");
- await _resolveSingleTemplate(dartSource);
-
- errorListener.assertNoErrors();
- final search = new ElementSearch((e) => e.localName == "span");
- template.ast.accept(search);
-
- expect(search.element, isNotNull);
- expect(search.element.boundDirectives, hasLength(1));
- final boundDirective = search.element.boundDirectives.first;
- expect(boundDirective.inputBindings, hasLength(1));
- expect(boundDirective.inputBindings.first.boundInput.name, 'title');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_inputBinding_wrongSafeBindingErrors() async {
- _addDartSource(r'''
-import 'package:angular/security.dart';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- SafeHtml html;
- SafeUrl url;
- SafeStyle style;
- SafeResourceUrl resourceUrl;
-}
-''');
- final code = r"""
-<a [innerHtml]='style' [innerHTML]='url' [href]='resourceUrl'></a>
-<iframe [src]='html'></iframe> <!--TODO test [style]='html' -->
-""";
- await angularDriver.getStandardHtml();
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertErrorsWithCodes([
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR,
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR,
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR,
- AngularWarningCode.UNSAFE_BINDING, // resourceUrl gets reported this way
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_invocation_of_erroneous_assignment_no_crash() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
- Function f;
-}
-''');
- final code = r"""
-{{str = (f)()}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "str = (f)()");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_keyupdownWithKeysOk() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handle(dynamic e) {
- }
-}
-''');
- _addHtmlSource(r"""
-<div (keyup.a)='handle($event)'></div>
-<div (keydown.enter)='handle($event)'></div>
-<div (keydown.shift.x)='handle($event)'></div>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_mustache_closeOpen_githubBug198() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
- }}{{''}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.UNOPENED_MUSTACHE, code, '}}');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_mustache_noEvent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
-<h1>{{$event}}</h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.UNDEFINED_IDENTIFIER, code, r"$event");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_nativeEventBindingOnComponent() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: [SomeComponent])
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-
-@Component(selector: 'some-comp', template: '')
-class SomeComponent {
-}
-''');
- _addHtmlSource(r"""
-<some-comp (click)='handleClick($event)'></some-comp>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement('click').output.inCoreHtml;
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_nativeGlobalAttrBindingOnComponent() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: [SomeComponent])
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-
-@Component(selector: 'some-comp', template: '')
-class SomeComponent {
-}
-''');
- _addHtmlSource(r"""
-<some-comp [hidden]='false'></some-comp>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement('hidden').input.inCoreHtml;
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_outputBinding_boundToNothing() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r"""
-<span (title)='text'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.NONEXIST_OUTPUT_BOUND, code, "title");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_expression_outputBinding_genericDirective_lowerBoundTypeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [GenericComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- takeInt(int i) {}
-}
-@Component(selector: 'generic-comp', template: '')
-class GenericComponent<T extends String> {
- @Output() EventEmitter<T> string;
-}
-''');
- final code = r"""
-<generic-comp (string)="takeInt($event)"></generic-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, code, r"$event");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_outputBinding_noValue() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Output() EventEmitter<int> title;
-}
-''');
- final code = r"""
-<title-comp (title)></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.EMPTY_BINDING, code, "(title)");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_outputBinding_typeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- takeString(String arg);
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Output() EventEmitter<int> output;
-}
-''');
- final code = r"""
-<title-comp (output)='takeString($event)'></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, code, r"$event");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_input_binding() async {
- _addDartSource(r'''
-@Component(selector: 'name-panel', template: r"<div>AAA</div>")
-class NamePanel {
- @Input() int value;
-}
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NamePanel], pipes: [Pipe1])
-class TestPanel {
- int value;
-}
-@Pipe('pipe1')
-class Pipe1 extends PipeTransform {
- int transform(int x) => "";
-}
-''');
- _addHtmlSource(r"""
-<name-panel [value]='value | pipe1'></name-panel>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_moustache() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html', pipes: [Pipe1])
-class TestPanel {
-}
-@Pipe('pipe1')
-class Pipe1 extends PipeTransform {
- String transform(int x) => "";
-}
-''');
- final code = r"""
-<p>{{((1 | pipe1:(2+2):(5 | pipe1:1:2)) + (2 | pipe1:4:2))}}</p>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_moustache_ambiguous() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- pipes: [AmbiguousPipe1, AmbiguousPipe2])
-class TestPanel {
-}
-
-@Pipe('ambiguous')
-class AmbiguousPipe1 extends PipeTransform {
- String transform(String x => "";
-}
-
-@Pipe('ambiguous')
-class AmbiguousPipe2 extends PipeTransform {
- String transform(String x => "";
-}
-''');
- final code = r"""
-{{"" | ambiguous}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.AMBIGUOUS_PIPE, code, 'ambiguous');
- }
-
- @failingTest
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_moustache_extraArg() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-@Pipe('stringPipe')
-class StringPipe extends PipeTransform {
- String transform(String x) => "";
-}
-''');
- final code = r"""
-{{"" | stringPipe: "extra"}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS, code, '"extra"');
- }
-
- @failingTest
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_moustache_extraExtraArg() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-@Pipe('stringPipe')
-class StringPipe extends PipeTransform {
- String transform(String x, [String y]) => "";
-}
-''');
- final code = r"""
-{{"" | stringPipe: "": "extra"}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS, code, '"extra"');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_moustache_noSuchPipe() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
-{{1 | noSuchPipe}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.PIPE_NOT_FOUND, code, 'noSuchPipe');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_moustache_typeErrorInput() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html', pipes: [StringPipe])
-class TestPanel {
-}
-@Pipe('stringPipe')
-class StringPipe extends PipeTransform {
- String transform(String x) => "";
-}
-''');
- final code = r"""
-{{1 | stringPipe}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, code, '1');
- }
-
- @failingTest
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_moustache_typeErrorOptionalArg() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html', pipes: [StringPipe])
-class TestPanel {
-}
-@Pipe('stringPipe')
-class StringPipe extends PipeTransform {
- String transform(String x, [String y]) => "";
-}
-''');
- final code = r"""
-{{"" | stringPipe: 1}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, code, '1');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_moustache_typeErrorResult() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html', pipes: [StringPipe])
-class TestPanel {
- String takeInt(int x) => "";
-}
-@Pipe('stringPipe')
-class StringPipe extends PipeTransform {
- String transform(String x) => "";
-}
-''');
- final code = r"""
-{{takeInt("" | stringPipe)}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
- code, '"" | stringPipe');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_moustache_with_error() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html', pipes: [Pipe1])
-class TestPanel {
- String name = "TestPanel";
-}
-@Pipe('pipe1')
-class Pipe1 extends PipeTransform {
- int transform(int x) => "";
-}
-''');
- final code = r"""
-<p>{{((1 | pipe1:(2+2):(5 | pipe1:1:2)) + (error1 | pipe1:4:2))}}</p>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.UNDEFINED_IDENTIFIER, code, "error1");
- }
-
- @failingTest
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_moustache_with_error_inArg() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html', pipes: [Pipe1])
-class TestPanel {
-}
-@Pipe('pipe1')
-class Pipe1 extends PipeTransform {
- String transform(String x) => "";
-}
-''');
- final code = r"""
-<p>{{1 | pipe1:error1}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.UNDEFINED_IDENTIFIER, code, "error1");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_pipe_in_ngFor() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor], pipes: [Pipe1])
-class TestPanel {
- List<String> operators = [];
-}
-@Pipe('pipe1')
-class Pipe1 extends PipeTransform {
- List<String> transform(List<String> x) => [];
-}
-''');
- _addHtmlSource(r"""
-<li *ngFor='let operator of (operators | pipe1)'>
- {{operator.length}}
-</li>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_reductionsOnRegularOutputsNotAllowed() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handle(dynamic e) {
- }
-}
-''');
- final code = r'''
-<div (click.whatever)='handle($event)'></div>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.EVENT_REDUCTION_NOT_ALLOWED, code, '.whatever');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_styleBinding_noUnit_expressionTypeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int noLength; // 1
-}
-''');
- final code = r"""
-<span [style.background-color]='noLength.length'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticTypeWarningCode.UNDEFINED_GETTER, code, "length");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_styleBinding_noUnit_invalidCssProperty() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r"""
-<span [style.invalid*property]='text'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertMultipleErrorsExplicit(htmlSource, code, [
- new Tuple4(']', 0, AngularWarningCode.NONEXIST_INPUT_BOUND, ['']),
- new Tuple4(']', 1,
- NgParserWarningCode.EXPECTED_WHITESPACE_BEFORE_NEW_DECORATOR, []),
- new Tuple4('[', 14, NgParserWarningCode.SUFFIX_PROPERTY, []),
- new Tuple4('*property', 9, AngularWarningCode.TEMPLATE_ATTR_NOT_USED, []),
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_styleBinding_noUnit_valid() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r"""
-<span [style.background-color]='text'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_styleBinding_withUnit_heightPercent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int percentage; // 1
-}
-''');
- final code = r"""
-<span [style.height.%]='percentage'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_styleBinding_withUnit_invalidPropertyName() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int pixels; // 1
-}
-''');
- final code = r"""
-<span [style.border&radius.px]='pixels'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertMultipleErrorsExplicit(htmlSource, code, [
- new Tuple4(
- "]='pixels'", 0, AngularWarningCode.NONEXIST_INPUT_BOUND, ['']),
- new Tuple4("]='pixels'", 1,
- NgParserWarningCode.EXPECTED_WHITESPACE_BEFORE_NEW_DECORATOR, []),
- new Tuple4('&radius', 1, NgParserWarningCode.UNEXPECTED_TOKEN, []),
- new Tuple4('[style', 14, NgParserWarningCode.SUFFIX_PROPERTY, []),
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_styleBinding_withUnit_invalidUnitName() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- double pixels; // 1
-}
-''');
- final code = r"""
-<span [style.border-radius.p|x]='pixels'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertMultipleErrorsExplicit(htmlSource, code, [
- new Tuple4(
- "]='pixels'", 0, AngularWarningCode.NONEXIST_INPUT_BOUND, ['']),
- new Tuple4("]='pixels'", 1,
- NgParserWarningCode.EXPECTED_WHITESPACE_BEFORE_NEW_DECORATOR, []),
- new Tuple4('|x', 1, NgParserWarningCode.UNEXPECTED_TOKEN, []),
- new Tuple4('[style', 23, NgParserWarningCode.SUFFIX_PROPERTY, []),
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_styleBinding_withUnit_nonWidthOrHeightPercent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int percentage; // 1
-}
-''');
- final code = r"""
-<span [style.something.%]='percentage'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.INVALID_CSS_UNIT_NAME, code, "%");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_styleBinding_withUnit_typeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String notNumber; // 1
-}
-''');
- final code = r"""
-<span [style.border-radius.px]='notNumber'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.CSS_UNIT_BINDING_NOT_NUMBER, code, "notNumber");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_styleBinding_withUnit_widthPercent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int percentage; // 1
-}
-''');
- final code = r"""
-<span [style.width.%]='percentage'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_symbol_invoked_noCrash() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="#symbol()"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "#symbol",
- additionalErrorCodes: [
- StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION
- ]);
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_expression_twoWayBinding_genericDirective_lowerBoundTypeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [GenericComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- int anInt;
-}
-@Component(selector: 'generic-comp', template: '')
-class GenericComponent<T extends String> {
- @Output() EventEmitter<T> stringChange;
- @Input() dynamic string;
-}
-''');
- final code = r"""
-<generic-comp [(string)]="anInt"></generic-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TWO_WAY_BINDING_OUTPUT_TYPE_ERROR, code, "anInt");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_twoWayBinding_inputTypeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() int title;
- @Output() EventEmitter<String> titleChange;
-}
-''');
- final code = r"""
-<title-comp [(title)]='text'></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.INPUT_BINDING_TYPE_ERROR, code, "text");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_twoWayBinding_noAttr_emptyBinding() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Directive(selector: '[titled]', template: '')
-class TitleComponent {
- @Input() String twoWay;
- @Output() EventEmitter<String> twoWayChange;
-}
-''');
- final code = r"""
-<span titled [(twoWay)]></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.EMPTY_BINDING, code, "[(twoWay)]");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_twoWayBinding_noInputToBind() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Output() EventEmitter<String> noInputChange;
-}
-''');
- final code = r"""
-<title-comp [(noInput)]="text"></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.NONEXIST_INPUT_BOUND, code, "noInput");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_twoWayBinding_noOutputToBind() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() String inputOnly;
-}
-''');
- final code = r"""
-<title-comp [(inputOnly)]="text"></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.NONEXIST_TWO_WAY_OUTPUT_BOUND, code, "inputOnly");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_twoWayBinding_notAssignableError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel',
- directives: const [TitleComponent], templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() String title;
- @Output() EventEmitter<String> titleChange;
-}
-''');
- final code = r"""
-<title-comp [(title)]="text.toUpperCase()"></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TWO_WAY_BINDING_NOT_ASSIGNABLE,
- code,
- "text.toUpperCase()");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_twoWayBinding_outputTypeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Component(selector: 'title-comp', template: '')
-class TitleComponent {
- @Input() String title;
- @Output() EventEmitter<int> titleChange;
-}
-''');
- final code = r"""
-<title-comp [(title)]='text'></title-comp>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TWO_WAY_BINDING_OUTPUT_TYPE_ERROR, code, "text");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_twoWayBinding_valid() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', directives: const [TitleComponent],
- templateUrl: 'test_panel.html')
-class TestPanel {
- String text; // 1
-}
-@Directive(selector: '[titled]', template: '')
-class TitleComponent {
- @Input() String title;
- @Output() EventEmitter<String> titleChange;
-}
-''');
- _addHtmlSource(r"""
-<span titled [(title)]='text'></span>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- final search = new ElementSearch((e) => e.localName == "span");
- template.ast.accept(search);
-
- expect(search.element, isNotNull);
- expect(search.element.boundDirectives, hasLength(1));
- final boundDirective = search.element.boundDirectives.first;
- expect(boundDirective.inputBindings, hasLength(1));
- expect(boundDirective.inputBindings.first.boundInput.name, 'title');
- expect(boundDirective.outputBindings, hasLength(1));
- expect(boundDirective.outputBindings.first.boundOutput.name, 'titleChange');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_unaryMinus_allowed() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int x;
-}
-''');
- final code = r"""
-{{-x}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expression_unaryNegate_allowed() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- bool x;
-}
-''');
- final code = r"""
-{{!x}}
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_as() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1>{{str as String}}</h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "str as String");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_await() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="await str"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- //This actually gets parsed as an identifier, which is OK. Still fails!
- errorListener.assertErrorsWithCodes([
- StaticWarningCode.UNDEFINED_IDENTIFIER,
- AngularWarningCode.TRAILING_EXPRESSION
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_cascade() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- bool val;
-}
-''');
- final code = r"""
-<h1 [hidden]="val..toString"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "val..toString");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_func() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="(){} == null"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "(){}");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_func2() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="null == ()=>null"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "()=>null");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_is() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="str is int"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "str is int");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_minusEq() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int x;
-}
-''');
- final code = r"""
-<h1 (click)="x -= 1"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, 'x -= 1');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_namedArgs() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- bool callMe({String arg}) => true;
-}
-''');
- final code = r"""
-<h1 [hidden]="callMe(arg: 'bob')"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_nestedAs() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1>{{(str.isEmpty as String).isEmpty}}</h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.DISALLOWED_EXPRESSION, code,
- "str.isEmpty as String");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_new() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="new TestPanel() != null"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "new TestPanel()");
- }
-
- Future test_expressionNotAllowed_plusEq() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int x;
-}
-''');
- final code = r"""
-<h1 (click)="x += 1"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, 'x += 1');
- }
-
- Future test_expressionNotAllowed_postfixMinusMinus() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int x;
-}
-''');
- final code = r"""
-<h1 (click)="x--"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, 'x--');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_postfixPlusPlus() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int x;
-}
-''');
- final code = r"""
-<h1 (click)="x++"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, 'x++');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_prefixMinusMinus() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int x;
-}
-''');
- final code = r"""
-<h1 (click)="--x"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, '--x');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_prefixPlusPlus() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- int x;
-}
-''');
- final code = r"""
-<h1 (click)="++x"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, '++x');
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_referenceAssignment() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
- <h1 #h1 [hidden]="(h1 = null) == null"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "h1 = null");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_rethrow() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="rethrow"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, code, "rethrow");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_setter() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="(str = 'hey') == null"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "str = 'hey'");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_statementAssignment() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 #h1 (click)="h1 = null"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "h1 = null");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_super() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="super.x"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, code, "super");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_symbol() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="#symbol == null"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "#symbol");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_this() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="this"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS, code, "this");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_throw() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="throw str"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "throw str");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_typedList() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="<String>[].isEmpty"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "<String>[]");
- }
-
- // ignore: non_constant_identifier_names
- Future test_expressionNotAllowed_typedMap() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 [hidden]="<String, String>{}.keys.isEmpty"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DISALLOWED_EXPRESSION, code, "<String, String>{}");
- }
-
- // ignore: non_constant_identifier_names
- Future test_futureOr() async {
- _addDartSource(r'''
-import 'dart:async';
-@Component(selector: 'future-or-apis', templateUrl: 'test_panel.html',
- directives: const [FutureOrApis])
-class FutureOrApis {
- @Input()
- FutureOr<int> futureOrInt;
- @Input()
- Future<int> futureInt;
- @Input()
- int justInt;
-}
-''');
- final code = r"""
-<future-or-apis [futureOrInt]="futureInt"></future-or-apis>
-<future-or-apis [futureOrInt]="justInt"></future-or-apis>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_hashRef_templateElement() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasTemplateInputComponent])
-class TestPanel {
-}
-@Component(selector: 'has-template-input', template: '')
-class HasTemplateInputComponent {
- @Input()
- TemplateRef myTemplate;
-}
-''');
- _addHtmlSource(r"""
-<template #someTemplate></template>
-<has-template-input [myTemplate]="someTemplate"></has-template-input>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement('someTemplate"').local.at('someTemplate>');
- }
-
- // ignore: non_constant_identifier_names
- Future test_inheritedFields() async {
- _addDartSource(r'''
-class BaseComponent {
- String text; // 1
-}
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel extends BaseComponent {
- main() {
- text.length;
- }
-}
-''');
- _addHtmlSource(r"""
-<div>
- Hello {{text}}!
-</div>
-""");
- await _resolveSingleTemplate(dartSource);
- expect(ranges, hasLength(1));
- _assertElement("text}}").dart.getter.at('text; // 1');
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_inputReference() async {
- _addDartSource(r'''
-@Component(selector: 'name-panel', template: r"<div>AAA</div>")
-class NamePanel {
- @Input()
- int aaa;
- @Input()
- int bbb;
- @Input()
- int ccc;
-}
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NamePanel])
-class TestPanel {}
-''');
- _addHtmlSource(r"""
-<name-panel aaa='1' [bbb]='2' bind-ccc='3' id="someid"></name-panel>
-""");
- await _resolveSingleTemplate(dartSource);
- _assertElement("aaa=").input.at("aaa;");
- _assertElement("bbb]=").input.at("bbb;");
- _assertElement("ccc=").input.at("ccc;");
- _assertElement("id=").input.inCoreHtml;
- }
-
- // ignore: non_constant_identifier_names
- Future test_letVar_template_cascading() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor, FoobarDirective])
-class TestPanel {
- List<String> items = [];
-}
-@Directive(selector: '[foobar]')
-class FoobarDirective {
- @Input()
- String foobar;
-}
-''');
- _addHtmlSource(r"""
-<template ngFor let-item [ngForOf]='items' let-i='index'>
- <template [foobar]="item"></template>
-</template>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement("ngFor let").selector.inFileName('ng_for.dart');
- _assertElement("item [").local.declaration.type('String');
- _assertSelectorElement("ngForOf]")
- .selector
- .name('ngForOf')
- .inFileName('ng_for.dart');
- _assertInputElement("ngForOf]")
- .input
- .name('ngForOf')
- .inFileName('ng_for.dart');
- _assertElement("items'").dart.getter.at('items = []');
- _assertElement("i='index").local.declaration.type('int');
- _assertElement("item").local.at('item [');
- }
-
- // ignore: non_constant_identifier_names
- Future test_letVariable_in_nonTemplate() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {}
-''');
- final html = r'''<div let-value></div>''';
- _addHtmlSource(html);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- NgParserWarningCode.INVALID_LET_BINDING_IN_NONTEMPLATE,
- html,
- 'let-value');
- }
-
- // ignore: non_constant_identifier_names
- Future test_localVariable_camelCaseName() async {
- _addDartSource(r'''
-import 'dart:html';
-
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [MyDivComponent])
-class TestPanel {
- void handleClick(String s) {}
-}
-@Component(selector: 'myDiv', template: '')
-class MyDivComponent {
- String someString = 'asdf';
-}
-''');
- _addHtmlSource(r"""
-<h1 (click)='handleClick(myTargetElement.someString)'>
- <myDiv #myTargetElement></myDiv>
-</h1>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement("myTargetElement.someString)").local.at("myTargetElement>");
- }
-
- // ignore: non_constant_identifier_names
- Future test_localVariable_exportAs() async {
- _addDartSource(r'''
-@Directive(selector: '[myDirective]', exportAs: 'exportedValue')
-class MyDirective {
- String aaa; // 1
-}
-
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [MyDirective])
-class TestPanel {}
-''');
- _addHtmlSource(r"""
-<div myDirective #value='exportedValue'>
- {{value.aaa}}
-</div>
-""");
- await _resolveSingleTemplate(dartSource);
- _assertElement("myDirective #").selector.at("myDirective]");
- _assertElement("value=").local.declaration.type('MyDirective');
- _assertElement("exportedValue'>").angular.at("exportedValue')");
- _assertElement("value.aaa").local.at("value=");
- _assertElement("aaa}}").dart.getter.at('aaa; // 1');
- }
-
- // ignore: non_constant_identifier_names
- Future test_localVariable_exportAs_ambiguous() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [Directive1, Directive2])
-class TestPanel {}
-
-@Directive(selector: '[dir1]', exportAs: 'ambiguous')
-class Directive1 {}
-
-@Directive(selector: '[dir2]', exportAs: 'ambiguous')
-class Directive2 {}
-''');
- final code = r"""
-<div dir1 dir2 #value="ambiguous"></div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.DIRECTIVE_EXPORTED_BY_AMBIGIOUS, code, 'ambiguous');
- }
-
- // ignore: non_constant_identifier_names
- Future test_localVariable_exportAs_notFound() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {}
-''');
- final code = r"""
-<div #value='noSuchExportedValue'>
- {{value.aaa}}
- assertErrorInCodeAtPosition fails when it sees multiple errors.
- this shouldn't err because 'value' should be known as uncheckable.
-</div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.NO_DIRECTIVE_EXPORTED_BY_SPECIFIED_NAME,
- code,
- "noSuchExportedValue");
- }
-
- // ignore: non_constant_identifier_names
- Future test_localVariable_scope_forwardReference() async {
- _addDartSource(r'''
-import 'dart:html';
-
-@Component(selector: 'aaa', template: '')
-class ComponentA {
- @Input()
- void set target(ComponentB b) {}
-}
-
-@Component(selector: 'bbb', template: '')
-class ComponentB {}
-
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: [ComponentA, ComponentB])
-class TestPanel {}
-''');
- _addHtmlSource(r"""
-<div>
- <aaa [target]='handle'></aaa>
- <bbb #handle></bbb>
-</div>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement("handle'>").local.at("handle></bbb>").type('ComponentB');
- }
-
- // ignore: non_constant_identifier_names
- Future test_nanTokenizationRangeError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgIf])
-class TestPanel {
- int i;
-}
-''');
- final code = r'''
-<div *ngIf="i > 0e"></div>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertErrorsWithCodes([
- ScannerErrorCode.MISSING_DIGIT,
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngContainer_withStar() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {}
-''');
- final htmlCode = r"""
-<ng-container *foo></ng-container>>
-""";
- _addHtmlSource(htmlCode);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TEMPLATE_ATTR_NOT_USED, htmlCode, '*foo');
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngContent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {}
-''');
- _addHtmlSource(r"""
-<ng-content></ng-content>>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngFor_hash_instead_of_let() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List<String> items = [];
-}
-''');
- final code = r"""
-<li *ngFor='#item of items; let i = index'>
-</li>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.UNEXPECTED_HASH_IN_TEMPLATE, code, "#");
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngFor_iterableElementType() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- MyIterable<String> items = new MyIterable<String>();
-}
-class BaseIterable<T> {
- Iterator<T> get iterator => <T>[].iterator;
-}
-class MyIterable<T> extends BaseIterable<T> {
-}
-''');
- _addHtmlSource(r"""
-<li template='ngFor let item of items'>
- {{item.length}}
-</li>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement("item.").local.at('item of').type('String');
- _assertElement("length}}").dart.getter;
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngFor_noStarError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List<String> items = [];
-}
-''');
- final code = r"""
-<li ngFor='let item of items; let i = index'>
-</li>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.STRUCTURAL_DIRECTIVES_REQUIRE_TEMPLATE,
- code,
- "ngFor");
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngFor_operatorLocalVariable() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List<String> operators = [];
-}
-''');
- _addHtmlSource(r"""
-<li *ngFor='let operator of operators'>
- {{operator.length}}
-</li>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- expect(template.ranges, hasLength(7));
- _assertElement("ngFor=").selector.inFileName('ng_for.dart');
- _assertElement("operator of").local.declaration.type('String');
- _assertElement("length}}").dart.getter;
- errorListener.assertNoErrors();
- final search = new ElementSearch((e) => e.localName == "li");
- template.ast.accept(search);
-
- expect(search.element, isNotNull);
- expect(search.element.templateAttribute, isNotNull);
- expect(search.element.templateAttribute.boundDirectives, hasLength(1));
- final boundDirective =
- search.element.templateAttribute.boundDirectives.first;
- expect(boundDirective.inputBindings, hasLength(1));
- expect(boundDirective.inputBindings.first.boundInput.name, 'ngForOf');
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngFor_operatorLocalVariableVarKeyword() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List<String> operators = [];
-}
-''');
- _addHtmlSource(r"""
-<li *ngFor='var operator of operators'>
- {{operator.length}}
-</li>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- expect(template.ranges, hasLength(7));
- _assertElement("ngFor=").selector.inFileName('ng_for.dart');
- _assertElement("operator of").local.declaration.type('String');
- _assertElement("length}}").dart.getter;
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngFor_star() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List<String> items = [];
-}
-''');
- _addHtmlSource(r"""
-<li *ngFor='let item of items; let i = index; let e = even; let o = odd; let f = first; let l = last;'>
- {{i}} {{item.length}}
- {{o}} {{e}} {{f}} {{l}}
-</li>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- expect(template.ranges, hasLength(22));
- _assertElement("ngFor=").selector.inFileName('ng_for.dart');
- _assertElement("item of").local.declaration.type('String');
- _assertSelectorElement("of items")
- .selector
- .name('ngForOf')
- .inFileName('ng_for.dart');
- _assertInputElement("of items")
- .input
- .name('ngForOf')
- .inFileName('ng_for.dart');
- _assertElement("items;").dart.getter.at('items = []');
- _assertElement("i = index").local.declaration.type('int');
- _assertElement("i}}").local.at('i = index');
- _assertElement("item.").local.at('item of');
- _assertElement("length}}").dart.getter;
- _assertElement("e = even").local.declaration.type('bool');
- _assertElement("e}}").local.at('e = even');
- _assertElement("o = odd").local.declaration.type('bool');
- _assertElement("o}}").local.at('o = odd');
- _assertElement("f = first").local.declaration.type('bool');
- _assertElement("f}}").local.at('f = first');
- _assertElement("l = last").local.declaration.type('bool');
- _assertElement("l}}").local.at('l = last');
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngFor_star_itemHiddenInElement() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List<String> items = [];
-}
-''');
- _addHtmlSource(r"""
-<h1 *ngFor='let item of items' [hidden]='item == null'>
-</h1>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement("item == null").local.at('item of items');
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngFor_templateAttribute() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List<String> items = [];
-}
-''');
- _addHtmlSource(r"""
-<li template='ngFor let item of items; let i = index'>
- {{i}} {{item.length}}
-</li>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement("ngFor let").selector.inFileName('ng_for.dart');
- _assertElement("item of").local.declaration.type('String');
- _assertSelectorElement("of items")
- .selector
- .name('ngForOf')
- .inFileName('ng_for.dart');
- _assertInputElement("of items")
- .input
- .name('ngForOf')
- .inFileName('ng_for.dart');
- _assertElement("items;").dart.getter.at('items = []');
- _assertElement("i = index").local.declaration.type('int');
- _assertElement("i}}").local.at('i = index');
- _assertElement("item.").local.at('item of');
- _assertElement("length}}").dart.getter;
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngFor_templateAttribute2() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List<String> items = [];
-}
-''');
- _addHtmlSource(r"""
-<li template='ngFor: let item, of = items, let i=index'>
- {{i}} {{item.length}}
-</li>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement("ngFor:").selector.inFileName('ng_for.dart');
- _assertElement("item, of").local.declaration.type('String');
- _assertSelectorElement("of = items,")
- .selector
- .name('ngForOf')
- .inFileName('ng_for.dart');
- _assertInputElement("of = items,")
- .input
- .name('ngForOf')
- .inFileName('ng_for.dart');
- _assertElement("items,").dart.getter.at('items = []');
- _assertElement("i=index").local.declaration.type('int');
- _assertElement("i}}").local.at('i=index');
- _assertElement("item.").local.at('item, of');
- _assertElement("length}}").dart.getter;
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngFor_templateElement() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List<String> items = [];
-}
-''');
- _addHtmlSource(r"""
-<template ngFor let-item [ngForOf]='items' let-i='index'>
- <li>{{i}} {{item.length}}</li>
-</template>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement("ngFor let").selector.inFileName('ng_for.dart');
- _assertElement("item [").local.declaration.type('String');
- _assertSelectorElement("ngForOf]")
- .selector
- .name('ngForOf')
- .inFileName('ng_for.dart');
- _assertInputElement("ngForOf]")
- .input
- .name('ngForOf')
- .inFileName('ng_for.dart');
- _assertElement("items'").dart.getter.at('items = []');
- _assertElement("i='index").local.declaration.type('int');
- _assertElement("i}}").local.at("i='index");
- _assertElement("item.").local.at('item [');
- _assertElement("length}}").dart.getter;
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngForSugar_dartExpression() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List<String> getItems(int unused) => [];
- int unused;
-}
-''');
- _addHtmlSource(r"""
-<li template="ngFor let item1 of getItems(unused + 5); let i=index">
- {{item1.length}}
-</li>
-<li *ngFor="let item2 of getItems(unused + 5); let i=index">
- {{item2.length}}
-</li>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngForSugar_noDartExpressionError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
-}
-''');
- final code = r'''
-<li *ngFor="let item of"></li>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.EMPTY_BINDING, code, 'of');
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngForSugar_noTrackByExpressionError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgFor])
-class TestPanel {
- List items;
-}
-''');
- final code = r'''
-<li *ngFor="let item of items; trackBy:"></li>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.EMPTY_BINDING, code, 'trackBy');
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngIf_emptyStarError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgIf])
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r'''
-<span *ngIf=""></span>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- // TODO would be nice if this selected ""
- assertErrorInCodeAtPosition(AngularWarningCode.EMPTY_BINDING, code, 'ngIf');
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngIf_noStarError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgIf])
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r"""
-<span ngIf='text.length != 0'></span>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.STRUCTURAL_DIRECTIVES_REQUIRE_TEMPLATE,
- code,
- "ngIf");
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngIf_star() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgIf])
-class TestPanel {
- String text; // 1
-}
-''');
- _addHtmlSource(r"""
-<span *ngIf='text.length != 0'></span>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertSelectorElement("ngIf=").selector.inFileName('ng_if.dart');
- _assertInputElement("ngIf=").input.inFileName('ng_if.dart');
- _assertElement("text.").dart.getter.at('text; // 1');
- _assertElement("length != 0").dart.getter;
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngIf_starNoAttrError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgIf])
-class TestPanel {
- String text; // 1
-}
-''');
- final code = r'''
-<span *ngIf></span>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.EMPTY_BINDING, code, 'ngIf');
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngIf_templateAttribute() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgIf])
-class TestPanel {
- String text; // 1
-}
-''');
- _addHtmlSource(r"""
-<span template='ngIf text.length != 0'></span>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertSelectorElement("ngIf text").selector.inFileName('ng_if.dart');
- _assertInputElement("ngIf text").input.inFileName('ng_if.dart');
- _assertElement("text.").dart.getter.at('text; // 1');
- _assertElement("length != 0").dart.getter;
- }
-
- // ignore: non_constant_identifier_names
- Future test_ngIf_templateElement() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NgIf])
-class TestPanel {
- String text; // 1
-}
-''');
- _addHtmlSource(r"""
-<template [ngIf]='text.length != 0'></template>
-""");
- await _resolveSingleTemplate(dartSource);
- _assertSelectorElement("ngIf]").selector.inFileName('ng_if.dart');
- _assertInputElement("ngIf]").input.inFileName('ng_if.dart');
- _assertElement("text.").dart.getter.at('text; // 1');
- _assertElement("length != 0").dart.getter;
- }
-
- // ignore: non_constant_identifier_names
- Future test_outputReference() async {
- _addDartSource(r'''
-@Component(selector: 'name-panel', template: r"<div>AAA</div>")
-class NamePanel {
- @Output() EventEmitter aaa;
- @Output() EventEmitter bbb;
- @Output() EventEmitter ccc;
-}
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NamePanel])
-class TestPanel {}
-''');
- _addHtmlSource(r"""
-<name-panel aaa='1' (bbb)='2' on-ccc='3'></name-panel>
-""");
- await _resolveSingleTemplate(dartSource);
- _assertElement("bbb)=").output.at("bbb;");
- _assertElement("ccc=").output.at("ccc;");
- final search = new ElementSearch((e) => e.localName == "name-panel");
- template.ast.accept(search);
-
- expect(search.element, isNotNull);
- expect(search.element.boundDirectives, hasLength(1));
- final boundDirective = search.element.boundDirectives.first;
- expect(boundDirective.outputBindings, hasLength(2));
- expect(boundDirective.outputBindings[0].boundOutput.name, 'bbb');
- expect(boundDirective.outputBindings[1].boundOutput.name, 'ccc');
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolvedTag_complexSelector() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [MyTag])
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-@Component(selector: 'my-tag[my-prop]', template: '')
-class MyTag {
-}
-''');
- final code = r"""
-<my-tag my-prop></my-tag>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolvedTag_evenThoughAlsoMatchesNonTagMatch() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [MyTag])
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-@Component(selector: '[red-herring],my-tag,[unrelated]', template: '')
-class MyTag {
-}
-''');
- final code = r"""
-<my-tag red-herring unrelated></my-tag>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- _assertElement("my-tag")
- .selector
- .inFileName("test_panel.dart")
- .at("my-tag");
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_customEvent_invalid() async {
- newSource('/custom_event.dart', r'''
-class CustomEvent {}
-''');
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [])
-class TestPanel {
- void acceptInt(int x) {}
-}
-''');
- final code = r"""
-<div (custom-event)="acceptInt($event)">
-</div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, code, r'$event');
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_customEvent_valid() async {
- newSource('/custom-event.dart', r'''
-class CustomEvent {
- int foo;
-}
-''');
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [])
-class TestPanel {
- void acceptInt(int x) {}
-}
-''');
- final code = r"""
-<div (custom-event)="acceptInt($event.foo)">
-</div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
-// Future test_ngFor_variousKinds_useLowerIdentifier() async {
-// _addDartSource(r'''
-//@Component(selector: 'test-panel')
-//@View(templateUrl: 'test_panel.html', directives: const [NgFor])
-//class TestPanel {
-// List<String> items = [];
-//}
-//''');
-// _addHtmlSource(r"""
-//<template ngFor let-item1 [ngForOf]='items' let-i='index' {{lowerEl}}>
-// {{item1.length}}
-//</template>
-//<li template="ngFor let item2 of items; let i=index" {{lowerEl}}>
-// {{item2.length}}
-//</li>
-//<li *ngFor="let item3 of items; let i=index" {{lowerEl}}>
-// {{item3.length}}
-//</li>
-//<div #lowerEl></div>
-//""");
-// await _resolveSingleTemplate(dartSource);
-// errorListener.assertNoErrors();
-// }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_customTagNames() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [])
-class TestPanel {
- String foo;
-}
-''');
- final code = r"""
-<my-first-custom-tag [unknownInput]="foo" (unknownOutput)="foo" #first str="val">
- <my-second-custom-tag [unknownInput]="foo" (unknownOutput)="foo" #second str="val">
- </my-second-custom-tag>
-</my-first-custom-tag>
-
-{{first.foo}} should be treated as "dynamic" and pass this check
-{{first.bar}} should be treated as "dynamic" and pass this check
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_customTagNames_unsuppressedErrors() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [])
-class TestPanel {
- String aString;
-}
-''');
- final code = r"""
-<my-first-custom-tag
- [input]="nosuchgetter"
- #foo="nosuchexport"
- *noSuchStar
- (x.noReductionAllowed)=""
- (emptyEvent)
- [emptyInput]>
- {{aString + 1}}
- <other-unknown-tag></other-unknown-tag>
-</my-first-custom-tag>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertErrorsWithCodes([
- StaticWarningCode.UNDEFINED_IDENTIFIER,
- AngularWarningCode.NO_DIRECTIVE_EXPORTED_BY_SPECIFIED_NAME,
- AngularWarningCode.TEMPLATE_ATTR_NOT_USED,
- AngularWarningCode.EVENT_REDUCTION_NOT_ALLOWED,
- AngularWarningCode.EMPTY_BINDING,
- AngularWarningCode.EMPTY_BINDING,
- AngularWarningCode.EMPTY_BINDING,
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
- AngularWarningCode.UNRESOLVED_TAG
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_exportsCantUsePrefixes() async {
- newSource('/prefixed.dart', 'const int prefixRequired = 1;');
- _addDartSource(r'''
-import '/prefixed.dart' as prefixed;
-const int prefixNotAllowed = 1;
-
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- exports: const [prefixNotAllowed, prefixed.prefixRequired])
-class TestPanel {
-}
-''');
- final code = r'''
-component class can't be used with a prefix: {{prefixed.TestPanel}}
-{{prefixed.prefixNotAllowed}}
-{{prefixRequired}}
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- expect(ranges, hasLength(2)); // the 'prefixed' prefixes only
- errorListener.assertErrorsWithCodes([
- StaticTypeWarningCode.UNDEFINED_GETTER,
- StaticTypeWarningCode.UNDEFINED_GETTER,
- StaticWarningCode.UNDEFINED_IDENTIFIER,
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_exportsNoErrors() async {
- newSource('/prefixed.dart', r'''
-const double otherAccessor = 2.0;
-enum OtherEnum { otherVal }
-void otherFunction() {}
-class OtherClass {
- static void otherStaticMethod() {}
- static String get otherStaticGetter => null;
-}
-''');
- _addDartSource(r'''
-import '/prefixed.dart' as prefixed;
-const int myAccessor = 1;
-enum MyEnum { myVal }
-void myFunction() {}
-class MyClass {
- static void myStaticMethod() {}
- static String get myStaticGetter => null;
-}
-
-@Component(
- selector: 'test-panel',
- templateUrl: 'test_panel.html',
- exports: const [
- myAccessor,
- MyEnum,
- myFunction,
- MyClass,
- prefixed.otherAccessor,
- prefixed.OtherEnum,
- prefixed.otherFunction,
- prefixed.OtherClass
-])
-class TestPanel {
- static void componentStatic() {
- }
- local();
- int get getter => null;
- set setter(int x) => null;
- int field = null;
-}
-''');
- final code = r'''
-methods/getters/setters on current class ok:
-{{local()}}
-{{getter}}
-{{field}}
-<div (click)="setter = null"></div>
-static on current class ok:
-{{TestPanel.componentStatic()}}
-exports ok:
-{{myAccessor}}
-{{MyEnum.myVal}}
-{{myFunction()}}
-{{MyClass.myStaticMethod()}}
-{{MyClass.myStaticGetter}}
-{{prefixed.otherAccessor}}
-{{prefixed.OtherEnum.otherVal}}
-{{prefixed.otherFunction()}}
-{{prefixed.OtherClass.otherStaticMethod()}}
-{{prefixed.OtherClass.otherStaticGetter}}
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- expect(ranges, hasLength(28));
- _assertElement('TestPanel').dart.at('TestPanel {');
- _assertElement('componentStatic').dart.method.at('componentStatic() {');
- _assertElement('myAccessor').dart.getter.at('myAccessor = 1');
- _assertElement('MyEnum').dart.at('MyEnum {');
- _assertElement('myVal').dart.at('myVal }');
- _assertElement('myFunction').dart.at('myFunction() {');
- _assertElement('MyClass').dart.at('MyClass {');
- _assertElement('myStaticMethod').dart.at('myStaticMethod() {');
- _assertElement('myStaticGetter').dart.at('myStaticGetter =>');
- _assertElement('prefixed').dart.prefix.at('prefixed;');
- _assertElement('otherAccessor')
- .dart
- .getter
- .inFile('/prefixed.dart')
- .at('otherAccessor = 2.0');
- _assertElement('OtherEnum').dart.inFile('/prefixed.dart').at('OtherEnum {');
- _assertElement('otherVal').dart.inFile('/prefixed.dart').at('otherVal }');
- _assertElement('otherFunction')
- .dart
- .inFile('/prefixed.dart')
- .at('otherFunction() {');
- _assertElement('OtherClass')
- .dart
- .inFile('/prefixed.dart')
- .at('OtherClass {');
- _assertElement('otherStaticMethod')
- .dart
- .inFile('/prefixed.dart')
- .at('otherStaticMethod() {');
- _assertElement('otherStaticGetter')
- .dart
- .inFile('/prefixed.dart')
- .at('otherStaticGetter =>');
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_invalidExportDoesntCrash() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- exports: const [garbage])
-class TestPanel {
-}
-''');
- final code = '{{garbage}}';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- expect(ranges, hasLength(0));
- errorListener.assertErrorsWithCodes([
- StaticWarningCode.UNDEFINED_IDENTIFIER,
- ]);
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_noDashesAroundTranscludedContent_stillError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeAllAndKnowsTag])
-class TestPanel {
-}
-@Component(selector: 'nodashes', template: '')
-class TranscludeAllAndKnowsTag {
-}
-''');
- final code = r"""
-<nodashes>shouldn't be allowed</nodashes>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.CONTENT_NOT_TRANSCLUDED,
- code, "shouldn't be allowed");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_noDashesAroundTranscludedContent_stillMatchesTag() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeAllAndKnowsTag])
-class TestPanel {
-}
-@Component(selector: 'nodashes',
- template: '<ng-content select="custom-tag"></ng-content>')
-class TranscludeAllAndKnowsTag {
-}
-''');
- final code = r"""
-<nodashes>
- <custom-tag></custom-tag>
-</nodashes>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_notExportedError() async {
- newSource('/prefixed.dart', r'''
-const double otherAccessor = 2.0;
-enum OtherEnum { otherVal }
-void otherFunction() {}
-var otherTopLevel = null;
-typedef void OtherFnTypedef();
-class OtherClass {
- static void otherStatic() {
- }
- static String sameNameAsComponentGetter;
-}
-
-String sameNameAsComponentGetter;
-''');
- _addDartSource(r'''
-import '/prefixed.dart' as prefixed;
-const int myAccessor = 1;
-enum MyEnum { otherVal }
-void myFunction() {}
-var myTopLevel = null;
-typedef void MyFnTypedef();
-class MyClass {
- static void myStatic() {
- }
- static String sameNameAsComponentGetter;
-}
-
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- exports: const [])
-class TestPanel {
- String get sameNameAsComponentGetter => null;
-}
-''');
- final code = r'''
-not exported:
-{{myAccessor}}
-{{MyEnum.otherVal}}
-{{myFunction()}}
-{{MyClass.myStatic()}}
-{{MyClass.sameNameAsComponentGetter}}
-{{prefixed.otherAccessor}}
-{{prefixed.sameNameAsComponentGetter}}
-{{prefixed.OtherEnum.otherVal}}
-{{prefixed.otherFunction()}}
-{{prefixed.OtherClass.otherStatic()}}
-{{prefixed.OtherClass.sameNameAsComponentGetter}}
-can't be exported:
-{{myTopLevel}}
-{{MyFnTypedef}}
-{{prefixed.otherTopLevel}}
-{{prefixed.OtherFnTypedef}}
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertErrorsWithCodes([
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- AngularWarningCode.IDENTIFIER_NOT_EXPORTED,
- ]);
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_componentNotElement() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild, SomeComponent])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild', read: Element)
- Element foo;
-}
-@Component(selector: 'some-component', template: '')
-class SomeComponent {
-}
-''');
- final code = r"""
-<has-content-child><some-component #contentChild></some-component></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<some-component #contentChild></some-component>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_componentNotElementRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild, SomeComponent])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- ElementRef foo;
-}
-@Component(selector: 'some-component', template: '')
-class SomeComponent {
-}
-''');
- final code = r"""
-<has-content-child><some-component #contentChild></some-component></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<some-component #contentChild></some-component>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_componentNotTemplateRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild, SomeComponent])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- TemplateRef foo;
-}
-@Component(selector: 'some-component', template: '')
-class SomeComponent {
-}
-''');
- final code = r"""
-<has-content-child><some-component #contentChild></some-component></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<some-component #contentChild></some-component>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_directiveNotElement() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild, SomeDirective])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild', read: Element)
- Element foo;
-}
-@Directive(selector: '[some-directive]', template: '', exportAs: "theDirective")
-class SomeDirective {
-}
-''');
- final code = r"""
-<has-content-child><div some-directive #contentChild="theDirective"></div></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<div some-directive #contentChild=\"theDirective\"></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_directiveNotElement_deeplyNested() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild, SomeDirective])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild', read: Element)
- Element foo;
-}
-@Directive(selector: '[some-directive]', template: '', exportAs: "theDirective")
-class SomeDirective {
-}
-''');
- final code = r"""
-<has-content-child>
- <div>
- <span>
- <div>
- <div some-directive #contentChild="theDirective"></div>
- </div>
- </span>
- </div>
-</has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<div some-directive #contentChild=\"theDirective\"></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_directiveNotElementRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild, SomeDirective])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- ElementRef foo;
-}
-@Directive(selector: '[some-directive]', template: '', exportAs: "theDirective")
-class SomeDirective {
-}
-''');
- final code = r"""
-<has-content-child><div some-directive #contentChild="theDirective"></div></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<div some-directive #contentChild=\"theDirective\"></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_directiveNotTemplateRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild, SomeDirective])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- TemplateRef foo;
-}
-@Directive(selector: '[some-directive]', template: '', exportAs: "theDirective")
-class SomeDirective {
-}
-''');
- final code = r"""
-<has-content-child><div some-directive #contentChild></div></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<div some-directive #contentChild></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_element_directiveNotExported() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild, SomeDirective])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- SomeDirective foo;
-}
-@Directive(selector: '[some-directive]')
-class SomeDirective {
-}
-''');
- final code = r"""
-<has-content-child><div some-directive #contentChild></div></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<div some-directive #contentChild></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_elementNotComponent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- SomeComponent foo;
-}
-@Component(selector: 'some-component', template: '')
-class SomeComponent {
-}
-''');
- final code = r"""
-<has-content-child><div #contentChild></div></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<div #contentChild></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_elementNotDirective() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- SomeDirective foo;
-}
-@Directive(selector: '[some-directive]')
-class SomeDirective {
-}
-''');
- final code = r"""
-<has-content-child><div #contentChild></div></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<div #contentChild></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_elementNotTemplateRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- TemplateRef foo;
-}
-''');
- final code = r"""
-<has-content-child><div #contentChild></div></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<div #contentChild></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_readValueIsAlwaysOk() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '')
-class HasContentChild {
- @ContentChild('contentChild', read: ViewContainerRef)
- ViewContainerRef foo;
-}
-''');
- final code = r"""
-<has-content-child><div #contentChild></div></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_templateNotComponent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- SomeComponent foo;
-}
-@Component(selector: 'some-component', template: '')
-class SomeComponent {
-}
-''');
- final code = r"""
-<has-content-child><template #contentChild></template></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<template #contentChild></template>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_templateNotDirective() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- SomeDirective foo;
-}
-@Directive(selector: '[some-directive]')
-class SomeDirective {
-}
-''');
- final code = r"""
-<has-content-child><template #contentChild></template></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<template #contentChild></template>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_templateNotElement() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild', read: Element)
- Element foo;
-}
-''');
- final code = r"""
-<has-content-child><template #contentChild></template></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<template #contentChild></template>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_templateNotElementRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- ElementRef foo;
-}
-''');
- final code = r"""
-<has-content-child><template #contentChild></template></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<template #contentChild></template>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_wrongComponent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild, SomeOtherComponent])
-class TestPanel {
-}
-@Component(selector: 'has-content-child',
- template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- SomeComponent foo;
-}
-@Component(selector: 'some-component', template: '')
-class SomeComponent {
-}
-@Component(selector: 'some-other-component', template: '')
-class SomeOtherComponent {
-}
-''');
- final code = r"""
-<has-content-child><some-other-component #contentChild></some-other-component></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<some-other-component #contentChild></some-other-component>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentChildLetBound_wrongDirective() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChild, SomeOtherDirective])
-class TestPanel {
-}
-@Component(selector: 'has-content-child', template: '<ng-content></ng-content>')
-class HasContentChild {
- @ContentChild('contentChild')
- SomeDirective foo;
-}
-@Directive(selector: '[some-directive]', exportAs: 'right')
-class SomeDirective {
-}
-@Directive(selector: '[some-other-directive]', exportAs: 'wrong')
-class SomeOtherDirective {
-}
-''');
- final code = r"""
-<has-content-child><div some-other-directive #contentChild="wrong"></div></has-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.MATCHED_LET_BINDING_HAS_WRONG_TYPE,
- code,
- "<div some-other-directive #contentChild=\"wrong\"></div>");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideContentEmptyTextAlwaysOK() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NoTransclude])
-class TestPanel {
-}
-@Component(selector: 'no-transclude', template: '')
-class NoTransclude {
-}
-''');
- final code = r"""
-<no-transclude>
-</no-transclude>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentMatchingHigherComponentsIsStillNotTranscludedError() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone, TranscludeAllWithContentChild])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
-}
-@Component(selector: 'transclude-all-with-content-child',
- template: '<ng-content></ng-content>')
-class TranscludeAllWithContentChild {
- @ContentChild("contentChildOfHigherComponent", read: Element)
- Element foo;
-}
-''');
- final code = r"""
-<transclude-all-with-content-child>
- <transclude-none>
- <div #contentChildOfHigherComponent></div>
- </transclude-none>
-</transclude-all-with-content-child>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.CONTENT_NOT_TRANSCLUDED,
- code, "<div #contentChildOfHigherComponent></div>");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideContentMatchingSelectors() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeSome])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="[transclude-me]"></ng-content>')
-class TranscludeSome {
-}
-''');
- final code = r"""
-<transclude-some><div transclude-me></div></transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentMatchingSelectorsAndAllKnowsTag() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeAllAndKnowsTag])
-class TestPanel {
-}
-@Component(
- selector: 'transclude-all-and-knows-tag',
- template:
- '<ng-content select="transclude-me"></ng-content><ng-content></ng-content>')
-class TranscludeAllAndKnowsTag {
-}
-''');
- final code = r"""
-<transclude-all-and-knows-tag>
- <transclude-me></transclude-me>
-</transclude-all-and-knows-tag>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideContentMatchingSelectorsKnowsTag() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeSome])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="transclude-me"></ng-content>')
-class TranscludeSome {
-}
-''');
- final code = r"""
-<transclude-some><transclude-me></transclude-me></transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentMatchingSelectorsReportsUnknownTag() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeSome])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="[transclude-me]"></ng-content>')
-class TranscludeSome {
-}
-''');
- final code = r"""
-<transclude-some><unknown-tag transclude-me></unknown-tag></transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.UNRESOLVED_TAG, code, "unknown-tag");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideContentNgSelectAll() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeAll])
-class TestPanel {
-}
-@Component(selector: 'transclude-all', template: '<ng-content></ng-content>')
-class TranscludeAll {
-}
-''');
- final code = r"""
-<transclude-all>belongs</transclude-all>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideContentNgSelectAllWithSelectors() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeAll])
-class TestPanel {
-}
-@Component(selector: 'transclude-all',
- template: '<ng-content select="x"></ng-content><ng-content></ng-content>')
-class TranscludeAll {
-}
-''');
- final code = r"""
-<transclude-all>belongs</transclude-all>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideContentNotMatchingSelectors() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeSome])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="transclude-me"></ng-content>')
-class TranscludeSome {
-}
-''');
- final code = r"""
-<transclude-some><div></div></transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.CONTENT_NOT_TRANSCLUDED, code, "<div></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNotMatchingSelectorsButMatchesContentChildElement() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeSome])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="transclude-me"></ng-content>')
-class TranscludeSome {
- @ContentChild(Element)
- Element foo;
-}
-''');
- final code = r"""
-<transclude-some><div></div></transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNotMatchingSelectorsButMatchesContentChildElementRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeSome])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="transclude-me"></ng-content>')
-class TranscludeSome {
- @ContentChild(ElementRef)
- ElementRef foo;
-}
-''');
- final code = r"""
-<transclude-some><div></div></transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNotMatchingSelectorsButMatchesContentChildHtmlElement() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeSome])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="transclude-me"></ng-content>')
-class TranscludeSome {
- @ContentChild(HtmlElement)
- HtmlElement foo;
-}
-''');
- final code = r"""
-<transclude-some><div></div></transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNotMatchingSelectorsButMatchesContentChildTemplateRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone])
-class TestPanel {
-}
-@Component(selector: 'transclude-none',
- template: '<ng-content select="transclude-me"></ng-content>')
-class TranscludeNone {
- @ContentChild(TemplateRef)
- TemplateRef foo;
-}
-''');
- final code = r"""
-<transclude-none><template></template></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNotMatchingSelectorsOrContentChildElement() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeSome])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="transclude-me"></ng-content>')
-class TranscludeSome {
- @ContentChild(Element)
- Element foo;
-}
-''');
- final code = r"""
-<transclude-some><template></template></transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.CONTENT_NOT_TRANSCLUDED,
- code, "<template></template>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNotMatchingSelectorsOrContentChildElementRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeSome])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="transclude-me"></ng-content>')
-class TranscludeSome {
- @ContentChild(ElementRef)
- ElementRef foo;
-}
-''');
- final code = r"""
-<transclude-some><template></template></transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.CONTENT_NOT_TRANSCLUDED,
- code, "<template></template>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNotMatchingSelectorsOrContentChildTemplateRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="transclude-me"></ng-content>')
-class TranscludeNone {
- @ContentChild(TemplateRef)
- TemplateRef foo;
-}
-''');
- final code = r"""
-<transclude-some><div></div></transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.CONTENT_NOT_TRANSCLUDED, code, "<div></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNoTransclusionsButMatchesContentChildDirective() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone, ContentChildComponent])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
- @ContentChild(ContentChildComponent)
- ContentChildComponent foo;
-}
-@Component(selector: 'content-child-comp', template: '')
-class ContentChildComponent {
-}
-''');
- final code = r"""
-<transclude-none><content-child-comp></content-child-comp></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNoTransclusionsButMatchesContentChildLetBoundComponent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone, ContentChildComponent])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
- @ContentChild('contentChild')
- ContentChildComponent foo;
- @ContentChild('contentChild')
- dynamic fooDynamicShouldBeOk;
- @ContentChild('contentChild')
- Object fooObjectShouldBeOk;
- @ContentChild('contentChild')
- Superclass fooSuperclassShouldBeOk;
-}
-@Component(selector: 'content-child-comp', template: '')
-class ContentChildComponent extends Superclass {
-}
-
-class Superclass {}
-''');
- final code = r"""
-<transclude-none><content-child-comp #contentChild></content-child-comp></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNoTransclusionsButMatchesContentChildLetBoundDirective() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone, ContentChildDirective])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
- @ContentChild('contentChild')
- ContentChildDirective foo;
- @ContentChild('contentChild')
- dynamic fooDynamicShouldBeOk;
- @ContentChild('contentChild')
- Object fooObjectShouldBeOk;
- @ContentChild('contentChild')
- Superclass fooSuperclassShouldBeOk;
-}
-@Directive(selector: '[content-child]', exportAs: 'contentChild')
-class ContentChildDirective extends Superclass {
-}
-
-class Superclass {}
-''');
- final code = r"""
-<transclude-none><div content-child #contentChild="contentChild"></div></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNoTransclusionsButMatchesContentChildLetBoundElement() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
- @ContentChild('contentChild', read: Element)
- Element foo;
- @ContentChild('contentChild')
- ElementRef foo; // to be deprecated, but ok
- @ContentChild('contentChild')
- dynamic fooDynamicShouldBeOk;
- @ContentChild('contentChild')
- Object fooObjectShouldBeOk;
-}
-''');
- final code = r"""
-<transclude-none><div #contentChild></div></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNoTransclusionsButMatchesContentChildLetBoundTemplateRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
- @ContentChild('contentChild')
- TemplateRef foo;
- @ContentChild('contentChild')
- dynamic fooDynamicShouldBeOk;
- @ContentChild('contentChild')
- Object fooObjectShouldBeOk;
-}
-''');
- final code = r"""
-<transclude-none><template #contentChild></template></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNoTransclusionsButMatchesContentChildTemplateRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
- @ContentChild(TemplateRef)
- TemplateRef foo;
-}
-''');
- final code = r"""
-<transclude-none><template></template></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNoTransclusionsNoChildElementMatch() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
- @ContentChild(Element)
- Element foo;
-}
-''');
- final code = r"""
-<transclude-none><template></template></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.CONTENT_NOT_TRANSCLUDED,
- code, "<template></template>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNoTransclusionsNoChildElementRefMatch() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
- @ContentChild(ElementRef)
- ElementRef foo;
-}
-''');
- final code = r"""
-<transclude-none><template></template></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(AngularWarningCode.CONTENT_NOT_TRANSCLUDED,
- code, "<template></template>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNoTransclusionsNoContentChildDirectiveMatch() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone, ContentChildComponent])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
- @ContentChild(ContentChildComponent)
- ContentChildComponent foo;
-}
-@Component(selector: 'content-child-comp', template: '')
-class ContentChildComponent {
-}
-''');
- final code = r"""
-<transclude-none><div></div></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.CONTENT_NOT_TRANSCLUDED, code, "<div></div>");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplate_provideContentNoTransclusionsNoContentChildTemplateRefMatch() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeNone])
-class TestPanel {
-}
-@Component(selector: 'transclude-none', template: '')
-class TranscludeNone {
- @ContentChild(TemplateRef)
- TemplateRef foo;
-}
-''');
- final code = r"""
-<transclude-none><div></div></transclude-none>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.CONTENT_NOT_TRANSCLUDED, code, "<div></div>");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideContentWhereInvalid() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NoTransclude])
-class TestPanel {
-}
-@Component(selector: 'no-transclude', template: '')
-class NoTransclude {
-}
-''');
- final code = r"""
-<no-transclude>doesn't belong</no-transclude>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.CONTENT_NOT_TRANSCLUDED, code, "doesn't belong");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideDuplicateContentChildError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChildElementRef])
-class TestPanel {
-}
-@Component(selector: 'has-content-child-element-ref', template: '')
-class HasContentChildElementRef {
- @ContentChild(ElementRef)
- ElementRef theElement;
-}
-''');
- final code = r"""
-<has-content-child-element-ref>
- <div first></div>
- <div second></div>
-</has-content-child-element-ref>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.SINGULAR_CHILD_QUERY_MATCHED_MULTIPLE_TIMES,
- code,
- "<div second></div>");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideDuplicateContentChildNestedOk() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChildElement])
-class TestPanel {
-}
-@Component(selector: 'has-content-child-element', template: '')
-class HasContentChildElement {
- @ContentChild(Element)
- Element theElement;
-}
-''');
- final code = r"""
-<has-content-child-element>
- <div first>
- <div second></div>
- </div>
-</has-content-child-element>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideDuplicateContentChildrenOk() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChildrenElement])
-class TestPanel {
-}
-@Component(selector: 'has-content-children-element', template: '')
-class HasContentChildrenElement {
- @ContentChildren(Element)
- List<Element> theElement;
-}
-''');
- final code = r"""
-<has-content-children-element>
- <div first></div>
- <div second></div>
-</has-content-children-element>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_provideTextInfosDontMatchSelectors() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [TranscludeSome])
-class TestPanel {
-}
-@Component(selector: 'transclude-some',
- template: '<ng-content select="transclude-me"></ng-content>')
-class TranscludeSome {
-}
-''');
- final code = r"""
-<transclude-some>doesn't belong</transclude-some>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.CONTENT_NOT_TRANSCLUDED, code, "doesn't belong");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplate_resolvingBogusImportDoesntCrash() async {
- _addDartSource(r'''
-import ; // synthetic import
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = '{{pants}}';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- expect(ranges, hasLength(0));
- errorListener.assertErrorsWithCodes([
- StaticWarningCode.UNDEFINED_IDENTIFIER,
- ]);
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_resolveTemplateRef_provideDuplicateContentChildSiblingsError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [HasContentChildTemplateRef])
-class TestPanel {
-}
-@Component(selector: 'has-content-child-template-ref',
- template: '<ng-content></ng-content>')
-class HasContentChildTemplateRef {
- @ContentChild(TemplateRef)
- TemplateRef theTemplate;
-}
-''');
- final code = r"""
-<has-content-child-template-ref>
- <div>
- <template first></template>
- </div>
- <div>
- <template second></template>
- </div>
-</has-content-child-template-ref>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.SINGULAR_CHILD_QUERY_MATCHED_MULTIPLE_TIMES,
- code,
- "<template second></template>");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplateWithNgContent_emptySelectorError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
-<div>
- <ng-content select=""></ng-content>
-</div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- expect(template.view.component.ngContents, hasLength(0));
- assertErrorInCodeAtPosition(
- AngularWarningCode.CANNOT_PARSE_SELECTOR, code, "\"\"");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplateWithNgContent_hasContentsError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
-<div>
- <ng-content>with content</ng-content>
-</div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertMultipleErrorsExplicit(htmlSource, code, [
- new Tuple4('<ng-content', 12,
- NgParserWarningCode.NGCONTENT_MUST_CLOSE_IMMEDIATELY, []),
- new Tuple4(
- '</ng-content>', 13, NgParserWarningCode.DANGLING_CLOSE_ELEMENT, []),
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplateWithNgContent_noSelectorIsNull() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
-<div>
- <ng-content></ng-content>
-</div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- expect(template.view.component.ngContents, hasLength(1));
- expect(template.view.component.ngContents.first.selector, isNull);
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplateWithNgContent_noValueError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
-<div>
- <ng-content select></ng-content>
-</div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- expect(template.view.component.ngContents, hasLength(0));
- assertErrorInCodeAtPosition(
- AngularWarningCode.CANNOT_PARSE_SELECTOR, code, "select");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplateWithNgContent_selectorParseError() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
-<div>
- <ng-content select="foo+bar"></ng-content>
-</div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- expect(template.view.component.ngContents, hasLength(0));
- assertErrorInCodeAtPosition(
- AngularWarningCode.CANNOT_PARSE_SELECTOR, code, "+");
- }
-
- // ignore: non_constant_identifier_names
- Future test_resolveTemplateWithNgContentTracksSelectors() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
-}
-''');
- final code = r"""
-<div>
- <ng-content select="foo"></ng-content>
-</div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- expect(template.view.component.ngContents, hasLength(1));
- }
-
- // ignore: non_constant_identifier_names
- Future test_standardHtmlComponent() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void inputChange(String value, String validationMessage) {}
-}
-''');
- _addHtmlSource(r"""
-<input #inputEl M
- (change)='inputChange(inputEl.value, inputEl.validationMessage)'>
-""");
- await _resolveSingleTemplate(dartSource);
- _assertElement('input #').selector.inCoreHtml.at('input");');
- _assertElement('inputEl M').local.at('inputEl M');
- _assertElement('inputChange(inputEl').dart.method.at('inputChange(Str');
- _assertElement('inputEl.value').local.at('inputEl M');
- _assertElement('value, ').dart.getter.inCoreHtml;
- _assertElement('inputEl.validationMessage').local.at('inputEl M');
- _assertElement('validationMessage)').dart.getter.inCoreHtml;
- _assertElement('change)').output.inCoreHtml;
- errorListener.assertNoErrors();
- expect(ranges, hasLength(8));
- }
-
- // ignore: non_constant_identifier_names
- Future test_standardHtmlComponentUsingRef() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void inputChange(String value, String validationMessage) {}
-}
-''');
- _addHtmlSource(r"""
-<input ref-inputEl M
- (change)='inputChange(inputEl.value, inputEl.validationMessage)'>
-""");
- await _resolveSingleTemplate(dartSource);
- _assertElement('input ref').selector.inCoreHtml.at('input");');
- _assertElement('inputEl M').local.at('inputEl M');
- _assertElement('inputChange(inputEl').dart.method.at('inputChange(Str');
- _assertElement('inputEl.value').local.at('inputEl M');
- _assertElement('value, ').dart.getter.inCoreHtml;
- _assertElement('inputEl.validationMessage').local.at('inputEl M');
- _assertElement('validationMessage)').dart.getter.inCoreHtml;
- _assertElement('change)').output.inCoreHtml;
- errorListener.assertNoErrors();
- expect(ranges, hasLength(8));
- }
-
- // ignore: non_constant_identifier_names
- Future test_star_selectTemplateFunctionalDirectiveMatches() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [myStarDirective])
-class TestPanel {
-}
-@Directive(selector: 'template[myStarDirective]')
-void myStarDirective(TemplateRef ref) {}
-''');
- final code = r'''
-<span *myStarDirective></span>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_star_selectTemplateMatches() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [MyStarDirective])
-class TestPanel {
-}
-@Directive(selector: 'template[myStarDirective]')
-class MyStarDirective {
- MyStarDirective(TemplateRef ref) {}
-}
-''');
- final code = r'''
-<span *myStarDirective></span>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_starNoDirectives() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [])
-class TestPanel {
-}
-''');
- final code = r"""
-<div *foo></div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TEMPLATE_ATTR_NOT_USED, code, "*foo");
- }
-
- // ignore: non_constant_identifier_names
- Future test_statement_eventBinding_all_semicolons() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""
-<div (click)=';;;;;;;;;;;;;'></div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_statement_eventBinding_double_statement() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- _addHtmlSource(r"""
-<div (click)='handleClick($event); 5+5;'></div>
-""");
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- _assertElement('handleClick').dart.method.at('handleClick(MouseEvent');
- }
-
- // ignore: non_constant_identifier_names
- Future test_statement_eventBinding_error_on_assignment_statement() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""
-<div (click)='handleClick($event); String s;'></div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.OUTPUT_STATEMENT_REQUIRES_EXPRESSION_STATEMENT,
- code,
- "String s");
- }
-
- // ignore: non_constant_identifier_names
- Future test_statement_eventBinding_error_on_second_statement() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""
-<div (click)='handleClick($event); unknownFunction()'></div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticTypeWarningCode.UNDEFINED_METHOD, code, "unknownFunction");
- }
-
- // ignore: non_constant_identifier_names
- Future test_statement_eventBinding_if_statement_with_semicolon() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""<h2 (click)='if(true){};'></h2>""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.OUTPUT_STATEMENT_REQUIRES_EXPRESSION_STATEMENT,
- code,
- "if(true){}");
- }
-
- // ignore: non_constant_identifier_names
- Future test_statement_eventBinding_if_statement_without_semicolon() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""<h2 (click)='if(true){}'></h2>""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.OUTPUT_STATEMENT_REQUIRES_EXPRESSION_STATEMENT,
- code,
- "if(true){}");
- }
-
- // ignore: non_constant_identifier_names
- Future test_statement_eventBinding_return_statement_with_semicolon() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""<h2 (click)='return 5;'></h2>""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.OUTPUT_STATEMENT_REQUIRES_EXPRESSION_STATEMENT,
- code,
- "return 5");
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_statement_eventBinding_return_statement_without_semicolon() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""<h2 (click)='return 5'></h2>""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.OUTPUT_STATEMENT_REQUIRES_EXPRESSION_STATEMENT,
- code,
- "return 5");
- }
-
- // ignore: non_constant_identifier_names
- Future test_statement_eventBinding_single_statement_with_semicolon() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- _addHtmlSource(r"""
-<div (click)='handleClick($event);'></div>
-""");
- await _resolveSingleTemplate(dartSource);
- _assertElement('handleClick').dart.method.at('handleClick(MouseEvent');
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_statement_eventBinding_single_statement_without_semicolon() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- _addHtmlSource(r"""
-<div (click)='handleClick($event)'></div>
-""");
- await _resolveSingleTemplate(dartSource);
- _assertElement('handleClick').dart.method.at('handleClick(MouseEvent');
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_statement_eventBinding_single_variable() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
- String random_string = "";
-}
-''');
- final code = r"""
-<div (click)='handleClick;'></div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_statement_eventBinding_typechecking_after_unexpected_bracket() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""
-<div (click)='}1.length'></div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertMultipleErrorsExplicit(htmlSource, code, [
- new Tuple4('}1', 1, ParserErrorCode.UNEXPECTED_TOKEN, ['}']),
- new Tuple4('length', 6, StaticTypeWarningCode.UNDEFINED_GETTER,
- ['length', 'int']),
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_statement_eventBinding_typeError() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""
-<div (click)='handleClick($event); 1 + "asdf";'></div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, code, '"asdf"');
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_statement_eventBinding_unexpected_closing_brackets_at_end() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""
-<div (click)='handleClick($event);}}}}'></div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(ParserErrorCode.UNEXPECTED_TOKEN, code, '}}}}');
- }
-
- Future
- // ignore: non_constant_identifier_names
- test_statement_eventBinding_unexpected_closing_brackets_at_start() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-''');
- final code = r"""
-<div (click)='}}handleClick($event)'></div>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(ParserErrorCode.UNEXPECTED_TOKEN, code, '}}');
- }
-
- // ignore: non_constant_identifier_names
- Future test_statements_setter_allowed() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String str;
-}
-''');
- final code = r"""
-<h1 #h1 (click)="str = 'hey'"></h1>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_staticParentReferenceNotOk() async {
- _addDartSource(r'''
-import 'dart:async';
-@Component(selector: 'a', templateUrl: 'test_panel.html')
-class ChildOfHasStatic extends HasStatic {
-}
-class HasStatic {
- static bool myParentsStatic;
-}
-''');
- final code = r'{{myParentsStatic}}';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertErrorsWithCodes([
- StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER
- ]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_staticSelfReferenceOk() async {
- _addDartSource(r'''
-import 'dart:async';
-@Component(selector: 'a', templateUrl: 'test_panel.html')
-class HasStatic {
- static bool myStatic;
-}
-''');
- final code = r'{{myStatic}}';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_strongModeSemantics_strongEnabled() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [])
-class TestPanel {
-}
-''');
- final code = r"""
-{{[1,2,3].add("five")}}
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertErrorsWithCodes(
- [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
- }
-
- // ignore: non_constant_identifier_names
- Future test_template_attribute_withoutValue() async {
- _addDartSource(r'''
-@Directive(selector: '[deferred]')
-class DeferredContentDirective {
- DeferredContentDirective(TemplateRef tpl);
- @Input()
- String deferred;
-}
-
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [DeferredContentDirective])
-class TestPanel {}
-''');
- _addHtmlSource(r"""
-<div *deferred>Deferred content</div>
-""");
- await _resolveSingleTemplate(dartSource);
- _assertElement('deferred>').selector.at("deferred]')");
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_templateAttr() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [MyStarDirective])
-class TestPanel {
-}
-@Directive(selector: 'template[myStarDirective]')
-class MyStarDirective {
- MyStarDirective(TemplateRef ref) {}
-}
-''');
- final code = r'''
-<div template="myStarDirective"></div>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_templateNoDirectives() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [])
-class TestPanel {
-}
-''');
- final code = r"""
-<div template="foo"></div>
-""";
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- assertErrorInCodeAtPosition(
- AngularWarningCode.TEMPLATE_ATTR_NOT_USED, code, 'template');
- }
-
- // ignore: non_constant_identifier_names
- Future test_templateTag_selectTemplateMatches() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel' templateUrl: 'test_panel.html',
- directives: const [MyStarDirective])
-class TestPanel {
-}
-@Directive(selector: 'template[myStarDirective]')
-class MyStarDirective {
- MyStarDirective(TemplateRef ref) {}
- @Input()
- String myStarDirective;
-}
-''');
- final code = r'''
-<template myStarDirective="'foo'"></template>
-''';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_textInterpolation() async {
- _addDartSource(r'''
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html')
-class TestPanel {
- String aaa; // 1
- String bbb; // 2
-}
-''');
- _addHtmlSource(r"""
-<div>
- Hello {{aaa}} and {{bbb}}!
-</div>
-""");
- await _resolveSingleTemplate(dartSource);
- expect(ranges, hasLength(2));
- _assertElement('aaa}}').dart.getter.at('aaa; // 1');
- _assertElement('bbb}}').dart.getter.at('bbb; // 2');
- }
-
- // ignore: non_constant_identifier_names
- Future test_tripleEq() async {
- _addDartSource(r'''
-import 'dart:async';
-@Component(selector: 'a', templateUrl: 'test_panel.html')
-class UseTripleEq {
- bool a;
- int b;
-}
-''');
- final code = r'{{a === b}}';
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- errorListener.assertNoErrors();
- }
-
- // ignore: non_constant_identifier_names
- Future test_twoWayReference() async {
- _addDartSource(r'''
-@Component(selector: 'name-panel', template: r"<div>AAA</div>")
-class NamePanel {
- @Input() int value;
- @Output() EventEmitter<int> valueChange;
-}
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [NamePanel])
-class TestPanel {
- int value;
-}
-''');
- _addHtmlSource(r"""
-<name-panel [(value)]='value'></name-panel>
-""");
- await _resolveSingleTemplate(dartSource);
- _assertElement("value)]").input.at("value;");
- }
-
- // ignore: non_constant_identifier_names
- Future test_unResolvedTag_evenThoughMatchedComplexSelector() async {
- _addDartSource(r'''
-import 'dart:html';
-@Component(selector: 'test-panel', templateUrl: 'test_panel.html',
- directives: const [MyTag])
-class TestPanel {
- void handleClick(MouseEvent e) {
- }
-}
-@Component(selector: 'my-tag.not-this-class,[my-prop]', template: '')
-class MyTag {
-}
-''');
- final code = r"""
-<my-tag my-prop></my-tag>
- """;
- _addHtmlSource(code);
- await _resolveSingleTemplate(dartSource);
- _assertElement("my-prop")
- .selector
- .inFileName("test_panel.dart")
- .at("my-prop");
- assertErrorInCodeAtPosition(
- AngularWarningCode.UNRESOLVED_TAG, code, "my-tag");
- }
-
- void _addDartSource(final code) {
- dartCode = '''
-import 'package:angular2/angular2.dart';
-$code
-''';
- dartSource = newSource('/test_panel.dart', dartCode);
- }
-
- void _addHtmlSource(final String code) {
- htmlCode = code;
- htmlSource = newSource('/test_panel.html', htmlCode);
- }
-
- ElementAssert _assertElement(String atString,
- [ResolvedRangeCondition condition]) {
- final resolvedRange = _findResolvedRange(atString, condition);
-
- return new ElementAssert(dartCode, dartSource, htmlCode, htmlSource,
- resolvedRange.element, resolvedRange.range.offset);
- }
-
- ElementAssert _assertInputElement(String atString) =>
- _assertElement(atString, _isInputElement);
-
- ElementAssert _assertSelectorElement(String atString) =>
- _assertElement(atString, _isSelectorName);
-
- /// Return the [ResolvedRange] that starts at the position of the give
- /// [search] and, if specified satisfies the given [condition].
- ResolvedRange _findResolvedRange(String search,
- [ResolvedRangeCondition condition]) =>
- getResolvedRangeAtString(htmlCode, ranges, search, condition);
-
- /// Compute all the views declared in the given [dartSource], and resolve the
- /// external template of the last one.
- Future _resolveSingleTemplate(Source dartSource) async {
- final result = await angularDriver.requestDartResult(dartSource.fullName);
- bool finder(AbstractDirective d) =>
- d is Component && d.view.templateUriSource != null;
- fillErrorListener(result.errors);
- errorListener.assertNoErrors();
- directives = result.directives;
- final directive = result.directives.singleWhere(finder);
- final htmlPath = (directive as Component).view.templateUriSource.fullName;
- final result2 = await angularDriver.requestHtmlResult(htmlPath);
- fillErrorListener(result2.errors);
- final view = (result2.directives.singleWhere(finder) as Component).view;
-
- template = view.template;
- ranges = template.ranges;
- }
-
- static bool _isInputElement(ResolvedRange region) =>
- region.element is InputElement;
-
- static bool _isSelectorName(ResolvedRange region) =>
- region.element is SelectorName;
-}
diff --git a/angular_analyzer_plugin/test/selector_test.dart b/angular_analyzer_plugin/test/selector_test.dart
deleted file mode 100644
index de7b806..0000000
--- a/angular_analyzer_plugin/test/selector_test.dart
+++ /dev/null
@@ -1,1497 +0,0 @@
-import 'package:analyzer/src/generated/source.dart';
-import 'package:angular_analyzer_plugin/src/model.dart';
-import 'package:angular_analyzer_plugin/src/selector.dart';
-import 'package:mockito/mockito.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-// 'typed' is deprecated and shouldn't be used.
-// ignore_for_file: deprecated_member_use
-
-void main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(AndSelectorTest);
- defineReflectiveTests(AttributeSelectorTest);
- defineReflectiveTests(AttributeContainsSelectorTest);
- defineReflectiveTests(ClassSelectorTest);
- defineReflectiveTests(ElementNameSelectorTest);
- defineReflectiveTests(OrSelectorTest);
- defineReflectiveTests(NotSelectorTest);
- defineReflectiveTests(AttributeValueRegexSelectorTest);
- defineReflectiveTests(AttributeStartsWithSelectorTest);
- defineReflectiveTests(SelectorParserTest);
- defineReflectiveTests(SuggestTagsTest);
- defineReflectiveTests(HtmlTagForSelectorTest);
- });
-}
-
-@reflectiveTest
-class AndSelectorTest extends _SelectorTest {
- final selector1 = new _SelectorMock('aaa');
- final selector2 = new _SelectorMock('bbb');
- final selector3 = new _SelectorMock('ccc');
-
- AndSelector selector;
-
- @override
- void setUp() {
- super.setUp();
- selector = new AndSelector(<Selector>[selector1, selector2, selector3]);
- when(selector1.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NonTagMatch);
- when(selector2.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NonTagMatch);
- when(selector3.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NonTagMatch);
-
- when(selector1.availableTo(typed(any))).thenReturn(true);
- when(selector2.availableTo(typed(any))).thenReturn(true);
- when(selector3.availableTo(typed(any))).thenReturn(true);
- }
-
- // ignore: non_constant_identifier_names
- void test_match() {
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- verify(selector1.match(typed(any), typed(any))).called(2);
- verify(selector2.match(typed(any), typed(any))).called(2);
- verify(selector3.match(typed(any), typed(any))).called(2);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_availableTo_allMatch() {
- expect(selector.availableTo(element), true);
- verify(selector1.availableTo(typed(any))).called(1);
- verify(selector2.availableTo(typed(any))).called(1);
- verify(selector3.availableTo(typed(any))).called(1);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_availableTo_singleUnmatch() {
- when(selector2.availableTo(typed(any))).thenReturn(false);
- expect(selector.availableTo(element), equals(false));
- verify(selector1.availableTo(typed(any))).called(1);
- verify(selector2.availableTo(typed(any))).called(1);
- verifyNever(selector3.availableTo(typed(any)));
- }
-
- // ignore: non_constant_identifier_names
- void test_match_false1() {
- when(selector1.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NoMatch);
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- verify(selector1.match(typed(any), typed(any))).called(1);
- verifyNever(selector2.match(typed(any), typed(any)));
- verifyNever(selector3.match(typed(any), typed(any)));
- }
-
- // ignore: non_constant_identifier_names
- void test_match_false2() {
- when(selector2.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NoMatch);
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- verify(selector1.match(typed(any), typed(any))).called(1);
- verify(selector2.match(typed(any), typed(any))).called(1);
- verifyNever(selector3.match(typed(any), typed(any)));
- }
-
- // ignore: non_constant_identifier_names
- void test_match_falseTagMatch() {
- when(selector1.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.TagMatch);
- when(selector2.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NoMatch);
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- verify(selector1.match(typed(any), typed(any))).called(1);
- verify(selector2.match(typed(any), typed(any))).called(1);
- verifyNever(selector3.match(typed(any), typed(any)));
- }
-
- // ignore: non_constant_identifier_names
- void test_match_TagMatch1() {
- when(selector1.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.TagMatch);
- expect(selector.match(element, template), equals(SelectorMatch.TagMatch));
- verify(selector1.match(typed(any), typed(any))).called(2);
- verify(selector2.match(typed(any), typed(any))).called(2);
- verify(selector3.match(typed(any), typed(any))).called(2);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_TagMatch2() {
- when(selector2.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.TagMatch);
- expect(selector.match(element, template), equals(SelectorMatch.TagMatch));
- verify(selector1.match(typed(any), typed(any))).called(2);
- verify(selector2.match(typed(any), typed(any))).called(2);
- verify(selector3.match(typed(any), typed(any))).called(2);
- }
-
- // ignore: non_constant_identifier_names
- void test_toString() {
- expect(selector.toString(), 'aaa && bbb && ccc');
- }
-}
-
-@reflectiveTest
-class AttributeContainsSelectorTest extends _SelectorTest {
- final AngularElement nameElement =
- new AngularElementImpl('kind', 10, 5, null);
- // ignore: non_constant_identifier_names
- void test_match() {
- final selector = new AttributeContainsSelector(nameElement, 'search');
- when(element.attributes).thenReturn({'kind': 'include the search here'});
- when(element.attributeNameSpans)
- .thenReturn({'kind': _newStringSpan(100, 'kind')});
- // verify
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- _assertRange(resolvedRanges[0], 100, 4, selector.nameElement);
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_begins() {
- final selector = new AttributeContainsSelector(nameElement, 'start');
- when(element.attributes).thenReturn({'kind': 'start is matched'});
- when(element.attributeNameSpans)
- .thenReturn({'kind': _newStringSpan(100, 'kind')});
- // verify
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- _assertRange(resolvedRanges[0], 100, 4, selector.nameElement);
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_ends() {
- final selector = new AttributeContainsSelector(nameElement, 'end');
- when(element.attributes).thenReturn({'kind': 'matches at the end'});
- when(element.attributeNameSpans)
- .thenReturn({'kind': _newStringSpan(100, 'kind')});
- // verify
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- _assertRange(resolvedRanges[0], 100, 4, selector.nameElement);
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_noMatch_attributeName() {
- final selector = new AttributeContainsSelector(nameElement, 'match');
- when(element.attributes).thenReturn({'unmatched': 'this is matched'});
- when(element.attributeNameSpans)
- .thenReturn({'unmatched': _newStringSpan(100, 'unmatched')});
- // verify
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_noMatch_value() {
- final selector =
- new AttributeContainsSelector(nameElement, 'not appearing');
- when(element.attributes).thenReturn({'kind': 'not related'});
- when(element.attributeNameSpans)
- .thenReturn({'kind': _newStringSpan(100, 'kind')});
- // verify
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), false);
- }
-}
-
-@reflectiveTest
-class AttributeSelectorTest extends _SelectorTest {
- final AngularElement nameElement =
- new AngularElementImpl('kind', 10, 5, null);
-
- // ignore: non_constant_identifier_names
- void test_match_name_value() {
- final selector = new AttributeSelector(nameElement, 'silly');
- when(element.attributes).thenReturn({'kind': 'silly'});
- when(element.attributeNameSpans)
- .thenReturn({'kind': _newStringSpan(100, 'kind')});
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- _assertRange(resolvedRanges[0], 100, 4, selector.nameElement);
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_notName() {
- final selector = new AttributeSelector(nameElement, null);
- when(element.attributes).thenReturn({'not-kind': 'no-matter'});
- when(element.attributeNameSpans).thenReturn({'not-kind': null});
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_notValue() {
- final selector = new AttributeSelector(nameElement, 'silly');
- when(element.attributes).thenReturn({'kind': 'strange'});
- when(element.attributeNameSpans)
- .thenReturn({'kind': _newStringSpan(100, "kind")});
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), equals(false));
- }
-
- // ignore: non_constant_identifier_names
- void test_match_noValue() {
- final selector = new AttributeSelector(nameElement, null);
- when(element.attributes).thenReturn({'kind': 'no-matter'});
- when(element.attributeNameSpans)
- .thenReturn({'kind': _newStringSpan(100, "kind")});
- // verify
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- _assertRange(resolvedRanges[0], 100, 4, selector.nameElement);
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_toString_hasValue() {
- final selector = new AttributeSelector(nameElement, 'daffy');
- expect(selector.toString(), '[kind=daffy]');
- }
-
- // ignore: non_constant_identifier_names
- void test_toString_noValue() {
- final selector = new AttributeSelector(nameElement, null);
- expect(selector.toString(), '[kind]');
- }
-}
-
-@reflectiveTest
-class AttributeStartsWithSelectorTest extends _SelectorTest {
- final selector = new AttributeStartsWithSelector(
- new AngularElementImpl('abc', 10, 5, null), 'xyz');
-
- // ignore: non_constant_identifier_names
- void test_exactMatch() {
- when(element.attributes).thenReturn({'abc': 'xyz'});
- when(element.attributeNameSpans)
- .thenReturn({'abc': _newStringSpan(100, 'abc')});
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_justOne() {
- when(element.attributes)
- .thenReturn({'abc': 'xyz and stuff', 'plop': 'zabcz', 'klark': 'efg'});
- when(element.attributeNameSpans).thenReturn({
- 'abc': _newStringSpan(100, 'abc'),
- 'plop': _newStringSpan(110, 'plop'),
- 'klark': _newStringSpan(120, 'klark')
- });
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_noMatch_any() {
- when(element.attributes).thenReturn(
- {'abc': 'wrong value', 'wrong-attr': 'xyz', 'klark': 'efg'});
- when(element.attributeNameSpans).thenReturn({
- 'abc': _newStringSpan(100, 'abc'),
- 'xyz': _newStringSpan(110, 'xyz'),
- 'klark': _newStringSpan(120, 'klark')
- });
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), equals(false));
- }
-
- // ignore: non_constant_identifier_names
- void test_noMatch_valueNotStartWith() {
- when(element.attributes).thenReturn({'abc': 'axyz'});
- when(element.attributeNameSpans)
- .thenReturn({'abc': _newStringSpan(100, 'abc')});
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- // available to is false, because the attribute already exists and so
- // suggesting it would lead to duplication.
- expect(selector.availableTo(element), equals(false));
- }
-
- // ignore: non_constant_identifier_names
- void test_noMatch_wrongAttrName() {
- when(element.attributes).thenReturn({'abcd': 'xyz'});
- when(element.attributeNameSpans)
- .thenReturn({'abcd': _newStringSpan(100, 'abcd')});
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), equals(true));
- }
-
- // ignore: non_constant_identifier_names
- void test_withExtraCharsMatch() {
- when(element.attributes).thenReturn({'abc': 'xyz and stuff'});
- when(element.attributeNameSpans)
- .thenReturn({'abc': _newStringSpan(100, 'abc')});
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- expect(selector.availableTo(element), true);
- }
-}
-
-@reflectiveTest
-class AttributeValueRegexSelectorTest extends _SelectorTest {
- final selector = new AttributeValueRegexSelector("abc");
-
- // ignore: non_constant_identifier_names
- void test_match() {
- when(element.attributes).thenReturn({'kind': '0abcd'});
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_justOne() {
- when(element.attributes)
- .thenReturn({'kind': 'bcd', 'plop': 'zabcz', 'klark': 'efg'});
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_noMatch() {
- when(element.attributes).thenReturn({'kind': 'bcd'});
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), equals(false));
- }
-
- // ignore: non_constant_identifier_names
- void test_noMatch_any() {
- when(element.attributes)
- .thenReturn({'kind': 'bcd', 'plop': 'cde', 'klark': 'efg'});
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), equals(false));
- }
-}
-
-@reflectiveTest
-class ClassSelectorTest extends _SelectorTest {
- final nameElement = new AngularElementImpl('nice', 10, 5, null);
- ClassSelector selector;
-
- @override
- void setUp() {
- super.setUp();
- selector = new ClassSelector(nameElement);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_false_noClass() {
- when(element.attributes).thenReturn({'not-class': 'no-matter'});
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_false_noSuchClass() {
- when(element.attributes).thenReturn({'class': 'not-nice'});
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_true_first() {
- final classValue = 'nice some other';
- when(element.attributes).thenReturn({'class': classValue});
- when(element.attributeValueSpans)
- .thenReturn({'class': _newStringSpan(100, classValue)});
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- expect(selector.availableTo(element), true);
- expect(resolvedRanges, hasLength(1));
- _assertRange(resolvedRanges[0], 100, 4, selector.nameElement);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_true_last() {
- final classValue = 'some other nice';
- when(element.attributes).thenReturn({'class': classValue});
- when(element.attributeValueSpans)
- .thenReturn({'class': _newStringSpan(100, classValue)});
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- expect(selector.availableTo(element), true);
- expect(resolvedRanges, hasLength(1));
- _assertRange(resolvedRanges[0], 111, 4, selector.nameElement);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_true_middle() {
- final classValue = 'some nice other';
- when(element.attributes).thenReturn({'class': classValue});
- when(element.attributeValueSpans)
- .thenReturn({'class': _newStringSpan(100, classValue)});
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- expect(selector.availableTo(element), true);
- expect(resolvedRanges, hasLength(1));
- _assertRange(resolvedRanges[0], 105, 4, selector.nameElement);
- }
-
- // ignore: non_constant_identifier_names
- void test_toString() {
- expect(selector.toString(), '.nice');
- }
-}
-
-@reflectiveTest
-class ElementNameSelectorTest extends _SelectorTest {
- ElementNameSelector selector;
-
- @override
- void setUp() {
- super.setUp();
- selector =
- new ElementNameSelector(new AngularElementImpl('panel', 10, 5, null));
- }
-
- // ignore: non_constant_identifier_names
- void test_match() {
- when(element.localName).thenReturn('panel');
- when(element.openingNameSpan).thenReturn(_newStringSpan(100, 'panel'));
- when(element.closingNameSpan).thenReturn(_newStringSpan(200, 'panel'));
- expect(selector.match(element, template), equals(SelectorMatch.TagMatch));
- expect(selector.availableTo(element), true);
- _assertRange(resolvedRanges[0], 100, 5, selector.nameElement);
- _assertRange(resolvedRanges[1], 200, 5, selector.nameElement);
- }
-
- // ignore: non_constant_identifier_names
- void test_match_not() {
- when(element.localName).thenReturn('not-panel');
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), equals(false));
- }
-
- // ignore: non_constant_identifier_names
- void test_toString() {
- expect(selector.toString(), 'panel');
- }
-}
-
-@reflectiveTest
-class HtmlTagForSelectorTest {
- // ignore: non_constant_identifier_names
- void test_addClassMultipleTimesOKDoesntRepeat() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..addClass("myclass");
- // ignore: cascade_invocations
- tag.addClass("myclass");
- // ignore: cascade_invocations
- tag.addClass("myclass");
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals('<tagname class="myclass"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_addClassOneClass() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..addClass("myclass");
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals('<tagname class="myclass"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_addClassTwoClasses() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..addClass("myclass");
- // ignore: cascade_invocations
- tag.addClass("myotherclass");
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals('<tagname class="myclass myotherclass"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_classesAndClassAttrBindingInvalid() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..addClass("myclass")
- ..setAttribute("class", value: "blah");
- expect(tag.isValid, isFalse);
- }
-
- // ignore: non_constant_identifier_names
- void test_classesAndEmptyClassAttrBindingValid() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..addClass("myclass")
- ..setAttribute("class");
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals('<tagname class="myclass"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_classesAndMatchingClassAttrBindingValid() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..addClass("myclass")
- ..setAttribute("class", value: 'myclass');
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals('<tagname class="myclass"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_cloneHasItsOwnClasses() {
- final tag = new HtmlTagForSelector()..name = "tagname";
- final clone = tag.clone()..addClass("myclass");
- expect(tag.toString(), "<tagname");
- expect(clone.toString(), '<tagname class="myclass"');
- }
-
- // ignore: non_constant_identifier_names
- void test_cloneHasItsOwnProperties() {
- final tag = new HtmlTagForSelector()..name = "tagname";
- final clone = tag.clone()..setAttribute("attr");
- expect(tag.toString(), "<tagname");
- expect(clone.toString(), "<tagname attr");
- }
-
- // ignore: non_constant_identifier_names
- void test_cloneIsAClone() {
- final tag = new HtmlTagForSelector();
- final clone = tag.clone();
- tag.name = "original";
- clone.name = "clone";
- expect(tag, isNot(equals(clone)));
- expect(tag.isValid, isTrue);
- expect(tag.toString(), "<original");
- expect(clone.isValid, isTrue);
- expect(clone.toString(), "<clone");
- }
-
- // ignore: non_constant_identifier_names
- void test_cloneKeepsAttributes() {
- var tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..setAttribute("attr1")
- ..setAttribute("attr2");
- tag = tag.clone();
- expect(tag.toString(), equals("<tagname attr1 attr2"));
- }
-
- // ignore: non_constant_identifier_names
- void test_cloneKeepsAttributeValues() {
- var tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..setAttribute("attr1", value: 'value1')
- ..setAttribute("attr2", value: 'value2');
- tag = tag.clone();
- expect(tag.toString(), equals('<tagname attr1="value1" attr2="value2"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_cloneKeepsClassnames() {
- var tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..addClass("class1")
- ..addClass("class2");
- tag = tag.clone();
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals('<tagname class="class1 class2"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_cloneKeepsName() {
- var tag = new HtmlTagForSelector()..name = "tagname";
- tag = tag.clone();
- expect(tag.toString(), equals("<tagname"));
- }
-
- // ignore: non_constant_identifier_names
- void test_cloneKeepsValid() {
- var tag = new HtmlTagForSelector()..name = "tagname";
-
- // ignore: cascade_invocations
- tag.name = "break this tag";
-
- // ignore: cascade_invocations
- tag = tag.clone();
- expect(tag.isValid, isFalse);
- }
-
- // ignore: non_constant_identifier_names
- void test_cloneWithoutNameCanBecomeValid() {
- var tag = new HtmlTagForSelector();
- tag = tag.clone()..name = "tagname";
- expect(tag.isValid, isTrue);
- }
-
- // ignore: non_constant_identifier_names
- void test_noNameIsInvalid() {
- final tag = new HtmlTagForSelector();
- expect(tag.isValid, isFalse);
- }
-
- // ignore: non_constant_identifier_names
- void test_setAttributeConflictingValues() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..setAttribute("attr", value: "value1");
- // ignore: cascade_invocations
- tag.setAttribute("attr", value: "value2");
- expect(tag.isValid, isFalse);
- }
-
- // ignore: non_constant_identifier_names
- void test_setAttributeNoValue() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..setAttribute("attr");
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals("<tagname attr"));
- }
-
- // ignore: non_constant_identifier_names
- void test_setAttributeNoValueAfterValue() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..setAttribute("attr", value: "value");
- // ignore: cascade_invocations
- tag.setAttribute("attr");
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals('<tagname attr="value"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_setAttributeNoValueTwice() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..setAttribute("attr");
- // ignore: cascade_invocations
- tag.setAttribute("attr");
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals("<tagname attr"));
- }
-
- // ignore: non_constant_identifier_names
- void test_setAttributeValue() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..setAttribute("attr", value: "value");
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals('<tagname attr="value"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_setAttributeValueAfterJustAttr() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..setAttribute("attr");
- // ignore: cascade_invocations
- tag.setAttribute("attr", value: "value");
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals('<tagname attr="value"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_setAttributeValueTwice() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..setAttribute("attr", value: "value");
- // ignore: cascade_invocations
- tag.setAttribute("attr", value: "value");
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals('<tagname attr="value"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_setName() {
- final tag = new HtmlTagForSelector()..name = "myname";
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals("<myname"));
- }
-
- // ignore: non_constant_identifier_names
- void test_setNameConflicting() {
- final tag = new HtmlTagForSelector()..name = "myname1";
- // ignore: cascade_invocations
- tag.name = "myname2";
- expect(tag.isValid, isFalse);
- }
-
- // ignore: non_constant_identifier_names
- void test_setNameTwice() {
- final tag = new HtmlTagForSelector()..name = "myname";
- // ignore: cascade_invocations
- tag.name = "myname";
- expect(tag.isValid, isTrue);
- expect(tag.toString(), equals("<myname"));
- }
-
- // ignore: non_constant_identifier_names
- void test_toStringIsAlphabeticalClasses() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..addClass("apple")
- ..addClass("flick")
- ..addClass("ziggy")
- ..addClass("cow");
- expect(tag.toString(), '<tagname class="apple cow flick ziggy"');
- }
-
- // ignore: non_constant_identifier_names
- void test_toStringIsAlphabeticalProperties() {
- final tag = new HtmlTagForSelector()
- ..name = "tagname"
- ..setAttribute("apple")
- ..setAttribute("flick")
- ..setAttribute("ziggy")
- ..setAttribute("cow")
- ..addClass("classes");
- expect(tag.toString(), '<tagname apple class="classes" cow flick ziggy');
- }
-}
-
-@reflectiveTest
-class NotSelectorTest extends _SelectorTest {
- final condition = new _SelectorMock('aaa');
-
- NotSelector selector;
-
- @override
- void setUp() {
- super.setUp();
- selector = new NotSelector(condition);
- }
-
- // ignore: non_constant_identifier_names
- void test_notAttribute_availableTo_false() {
- final nameElement = new AngularElementImpl('kind', 10, 5, null);
- final attributeSelector = new AttributeSelector(nameElement, null);
- when(element.attributes).thenReturn({'kind': 'strange'});
- when(element.attributeNameSpans)
- .thenReturn({'kind': _newStringSpan(100, 'kind')});
- selector = new NotSelector(attributeSelector);
- expect(selector.availableTo(element), equals(false));
- }
-
- // ignore: non_constant_identifier_names
- void test_notAttribute_availableTo_true() {
- final nameElement = new AngularElementImpl('kind', 10, 5, null);
- final attributeSelector = new AttributeSelector(nameElement, null);
- when(element.attributes).thenReturn({'not-kind': 'strange'});
- when(element.attributeNameSpans)
- .thenReturn({'not-kind': _newStringSpan(100, 'not-kind')});
- selector = new NotSelector(attributeSelector);
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_notFalse() {
- when(condition.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NoMatch);
- when(condition.availableTo(typed(any))).thenReturn(false);
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- expect(selector.availableTo(element), true);
- }
-
- // ignore: non_constant_identifier_names
- void test_notNonTagMatch() {
- when(condition.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NonTagMatch);
- when(condition.availableTo(typed(any))).thenReturn(true);
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), equals(false));
- }
-
- // ignore: non_constant_identifier_names
- void test_notTagMatch() {
- when(condition.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.TagMatch);
- when(condition.availableTo(typed(any))).thenReturn(true);
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- expect(selector.availableTo(element), equals(false));
- }
-}
-
-@reflectiveTest
-class OrSelectorTest extends _SelectorTest {
- final selector1 = new _SelectorMock('aaa');
- final selector2 = new _SelectorMock('bbb');
- final selector3 = new _SelectorMock('ccc');
-
- OrSelector selector;
-
- @override
- void setUp() {
- super.setUp();
- selector = new OrSelector(<Selector>[selector1, selector2, selector3]);
- when(selector1.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NoMatch);
- when(selector1.availableTo(typed(any))).thenReturn(false);
- when(selector2.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NoMatch);
- when(selector2.availableTo(typed(any))).thenReturn(false);
- when(selector3.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NoMatch);
- when(selector3.availableTo(typed(any))).thenReturn(false);
- }
-
- // ignore: non_constant_identifier_names
- void test_match2NonTagMatch() {
- when(selector2.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NonTagMatch);
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- verify(selector1.match(typed(any), typed(any))).called(1);
- verify(selector2.match(typed(any), typed(any))).called(1);
- verify(selector3.match(typed(any), typed(any))).called(1);
- }
-
- // ignore: non_constant_identifier_names
- void test_match2TagAndNonTagMatch() {
- when(selector1.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NonTagMatch);
- when(selector2.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.TagMatch);
- expect(selector.match(element, template), equals(SelectorMatch.TagMatch));
- verify(selector1.match(typed(any), typed(any))).called(1);
- verify(selector2.match(typed(any), typed(any))).called(1);
- verifyNever(selector3.match(typed(any), typed(any)));
- }
-
- // ignore: non_constant_identifier_names
- void test_match2TagMatch() {
- when(selector2.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.TagMatch);
- when(selector2.availableTo(typed(any))).thenReturn(true);
- expect(selector.match(element, template), equals(SelectorMatch.TagMatch));
- verify(selector1.match(typed(any), typed(any))).called(1);
- verify(selector2.match(typed(any), typed(any))).called(1);
- verifyNever(selector3.match(typed(any), typed(any)));
-
- expect(selector.availableTo(element), true);
- verify(selector1.availableTo(typed(any))).called(1);
- verify(selector2.availableTo(typed(any))).called(1);
- verifyNever(selector3.availableTo(typed(any)));
- }
-
- // ignore: non_constant_identifier_names
- void test_match_false() {
- expect(selector.match(element, template), equals(SelectorMatch.NoMatch));
- verify(selector1.match(typed(any), typed(any))).called(1);
- verify(selector2.match(typed(any), typed(any))).called(1);
- verify(selector3.match(typed(any), typed(any))).called(1);
-
- expect(selector.availableTo(element), equals(false));
- verify(selector1.availableTo(typed(any))).called(1);
- verify(selector2.availableTo(typed(any))).called(1);
- verify(selector3.availableTo(typed(any))).called(1);
- }
-
- // ignore: non_constant_identifier_names
- void test_matchFirstIsNonTagMatch() {
- when(selector1.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.NonTagMatch);
- expect(
- selector.match(element, template), equals(SelectorMatch.NonTagMatch));
- verify(selector1.match(typed(any), typed(any))).called(1);
- verify(selector2.match(typed(any), typed(any))).called(1);
- verify(selector3.match(typed(any), typed(any))).called(1);
- }
-
- // ignore: non_constant_identifier_names
- void test_matchFirstIsTagMatch() {
- when(selector1.match(typed(any), typed(any)))
- .thenReturn(SelectorMatch.TagMatch);
- when(selector1.availableTo(typed(any))).thenReturn(true);
- expect(selector.match(element, template), equals(SelectorMatch.TagMatch));
- verify(selector1.match(typed(any), typed(any))).called(1);
- verifyNever(selector2.match(typed(any), typed(any)));
- verifyNever(selector3.match(typed(any), typed(any)));
-
- expect(selector.availableTo(element), true);
- verify(selector1.availableTo(typed(any))).called(1);
- verifyNever(selector2.availableTo(typed(any)));
- verifyNever(selector3.availableTo(typed(any)));
- }
-
- // ignore: non_constant_identifier_names
- void test_toString() {
- expect(selector.toString(), 'aaa || bbb || ccc');
- }
-}
-
-@reflectiveTest
-class SelectorParserTest {
- final Source source = new _SourceMock();
-
- // ignore: non_constant_identifier_names
- void test_and() {
- final selector = new SelectorParser(source, 10, '[ng-for][ng-for-of]')
- .parse() as AndSelector;
- expect(selector.selectors, hasLength(2));
- {
- final subSelector = selector.selectors[0] as AttributeSelector;
- final nameElement = subSelector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'ng-for');
- expect(nameElement.nameOffset, 11);
- expect(nameElement.nameLength, 'ng-for'.length);
- }
- {
- final subSelector = selector.selectors[1] as AttributeSelector;
- final nameElement = subSelector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'ng-for-of');
- expect(nameElement.nameOffset, 19);
- expect(nameElement.nameLength, 'ng-for-of'.length);
- }
- }
-
- // ignore: non_constant_identifier_names
- void test_attribute_beginsWithOperator_noValue() {
- try {
- new SelectorParser(source, 0, '[foo^=]').parse();
- } on FormatException catch (e) {
- expect(e.message, contains('Expected a value after ^=, got ]'));
- expect(e.offset, '[foo^='.length);
- return;
- }
- fail("was supposed to throw");
- }
-
- // ignore: non_constant_identifier_names
- void test_attribute_containsOperator_noValue() {
- try {
- new SelectorParser(source, 0, '[foo*=]').parse();
- } on FormatException catch (e) {
- expect(e.message, contains('Expected a value after *=, got ]'));
- expect(e.offset, '[foo*='.length);
- return;
- }
- fail("was supposed to throw");
- }
-
- // ignore: non_constant_identifier_names
- void test_attribute_hasValue() {
- final selector = new SelectorParser(source, 10, '[kind=pretty]').parse()
- as AttributeSelector;
- {
- final nameElement = selector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'kind');
- expect(nameElement.nameOffset, 11);
- expect(nameElement.nameLength, 'kind'.length);
- }
- expect(selector.value, 'pretty');
- }
-
- // ignore: non_constant_identifier_names
- void test_attribute_hasValueWithQuotes() {
- final selector =
- new SelectorParser(source, 10, '''[single='quotes'][double="quotes"]''')
- .parse() as AndSelector;
- expect(selector.selectors, hasLength(2));
- {
- final subSelector = selector.selectors[0] as AttributeSelector;
- {
- final nameElement = subSelector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'single');
- }
- // Ensure there are no quotes within the value
- expect(subSelector.value, 'quotes');
- }
- {
- final subSelector = selector.selectors[1] as AttributeSelector;
- {
- final nameElement = subSelector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'double');
- }
- // Ensure there are no quotes within the value
- expect(subSelector.value, 'quotes');
- }
- }
-
- // ignore: non_constant_identifier_names
- void test_attribute_hasWildcard() {
- final selector = new SelectorParser(source, 10, '[kind*=pretty]').parse()
- as AttributeContainsSelector;
- {
- final nameElement = selector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'kind');
- expect(nameElement.nameOffset, 11);
- expect(nameElement.nameLength, 'kind'.length);
- }
- expect(selector.value, 'pretty');
- }
-
- // ignore: non_constant_identifier_names
- void test_attribute_noValue() {
- final selector =
- new SelectorParser(source, 10, '[ng-for]').parse() as AttributeSelector;
- {
- final nameElement = selector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'ng-for');
- expect(nameElement.nameOffset, 11);
- expect(nameElement.nameLength, 'ng-for'.length);
- }
- expect(selector.value, isNull);
- }
-
- // ignore: non_constant_identifier_names
- void test_attribute_regularOperator_noValue() {
- try {
- new SelectorParser(source, 0, '[foo=]').parse();
- } on FormatException catch (e) {
- expect(e.message, contains('Expected a value after =, got ]'));
- expect(e.offset, '[foo='.length);
- return;
- }
- fail("was supposed to throw");
- }
-
- // ignore: non_constant_identifier_names
- void test_attribute_startsWith() {
- final selector = new SelectorParser(source, 10, '[foo^=bar]').parse()
- as AttributeStartsWithSelector;
- expect(selector.nameElement.name, 'foo');
- expect(selector.value, 'bar');
- }
-
- // ignore: non_constant_identifier_names
- void test_attribute_startsWith_quoted() {
- final selector = new SelectorParser(source, 10, '[foo^="bar"]').parse()
- as AttributeStartsWithSelector;
- expect(selector.nameElement.name, 'foo');
- expect(selector.value, 'bar');
- }
-
- // ignore: non_constant_identifier_names
- void test_attribute_textRegex() {
- final selector = new SelectorParser(source, 10, '[*=/pretty/]').parse()
- as AttributeValueRegexSelector;
- expect(selector.regexpStr, 'pretty');
- }
-
- // ignore: non_constant_identifier_names
- void test_bad() {
- try {
- new SelectorParser(source, 0, '+name').parse();
- } catch (e) {
- return;
- }
- fail("was supposed to throw");
- }
-
- // ignore: non_constant_identifier_names
- void test_class() {
- final selector =
- new SelectorParser(source, 10, '.nice').parse() as ClassSelector;
- final nameElement = selector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'nice');
- expect(nameElement.nameOffset, 11);
- expect(nameElement.nameLength, 'nice'.length);
- }
-
- // ignore: non_constant_identifier_names
- void test_complex_ast() {
- final selector = new SelectorParser(
- source, 10, 'aaa, bbb:not(ccc), :not(:not(ddd)[eee], fff[ggg])')
- .parse() as OrSelector;
-
- expect(
- selector.toString(),
- equals('aaa || bbb && :not(ccc) || '
- ':not(:not(ddd) && [eee] || fff && [ggg])'));
- {
- final subSelector = selector.selectors[0] as ElementNameSelector;
- expect(subSelector.toString(), "aaa");
- }
- {
- final subSelector = selector.selectors[1] as AndSelector;
- expect(subSelector.toString(), "bbb && :not(ccc)");
- {
- final subSelector2 = subSelector.selectors[0] as ElementNameSelector;
- expect(subSelector2.toString(), "bbb");
- }
- {
- final subSelector2 = subSelector.selectors[1] as NotSelector;
- expect(subSelector2.toString(), ":not(ccc)");
- {
- final subSelector3 = subSelector2.condition as ElementNameSelector;
- expect(subSelector3.toString(), "ccc");
- }
- }
- }
- {
- final subSelector = selector.selectors[2] as NotSelector;
- expect(
- subSelector.toString(), ":not(:not(ddd) && [eee] || fff && [ggg])");
- {
- final subSelector2 = subSelector.condition as OrSelector;
- expect(subSelector2.toString(), ":not(ddd) && [eee] || fff && [ggg]");
- {
- final subSelector3 = subSelector2.selectors[0] as AndSelector;
- expect(subSelector3.toString(), ":not(ddd) && [eee]");
- {
- final subSelector4 = subSelector3.selectors[0] as NotSelector;
- expect(subSelector4.toString(), ":not(ddd)");
- {
- final subSelector5 =
- subSelector4.condition as ElementNameSelector;
- expect(subSelector5.toString(), "ddd");
- }
- }
- {
- final subSelector4 = subSelector3.selectors[1] as AttributeSelector;
- expect(subSelector4.toString(), "[eee]");
- }
- }
- {
- final subSelector3 = subSelector2.selectors[1] as AndSelector;
- expect(subSelector3.toString(), "fff && [ggg]");
- {
- final subSelector4 =
- subSelector3.selectors[0] as ElementNameSelector;
- expect(subSelector4.toString(), "fff");
- }
- {
- final subSelector4 = subSelector3.selectors[1] as AttributeSelector;
- expect(subSelector4.toString(), "[ggg]");
- }
- }
- }
- }
- }
-
- // ignore: non_constant_identifier_names
- void test_contains() {
- final selector = new SelectorParser(source, 10, ':contains(/aaa/)').parse()
- as ContainsSelector;
- expect(selector.regex, 'aaa');
- }
-
- // ignore: non_constant_identifier_names
- void test_elementName() {
- final selector = new SelectorParser(source, 10, 'text-panel').parse()
- as ElementNameSelector;
- final nameElement = selector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'text-panel');
- expect(nameElement.nameOffset, 10);
- expect(nameElement.nameLength, 'text-panel'.length);
- }
-
- // ignore: non_constant_identifier_names
- void test_not() {
- final selector =
- new SelectorParser(source, 10, ':not(aaa)').parse() as NotSelector;
- {
- final condition = selector.condition as ElementNameSelector;
- final nameElement = condition.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'aaa');
- expect(nameElement.nameOffset, 15);
- expect(nameElement.nameLength, 'aaa'.length);
- }
- }
-
- // ignore: non_constant_identifier_names
- void test_or() {
- final selector =
- new SelectorParser(source, 10, 'aaa,bbb').parse() as OrSelector;
- expect(selector.selectors, hasLength(2));
- {
- final subSelector = selector.selectors[0] as ElementNameSelector;
- final nameElement = subSelector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'aaa');
- expect(nameElement.nameOffset, 10);
- expect(nameElement.nameLength, 'aaa'.length);
- }
- {
- final subSelector = selector.selectors[1] as ElementNameSelector;
- final nameElement = subSelector.nameElement;
- expect(nameElement.source, source);
- expect(nameElement.name, 'bbb');
- expect(nameElement.nameOffset, 14);
- expect(nameElement.nameLength, 'bbb'.length);
- }
- }
-}
-
-@reflectiveTest
-class SuggestTagsTest {
- // ignore: non_constant_identifier_names
- void test_suggestAndMergesSuggestionConstraints() {
- final nameSelector =
- new ElementNameSelector(new AngularElementImpl('panel', 10, 5, null));
- final attrSelector = new AttributeContainsSelector(
- new AngularElementImpl('attr', 10, 5, null), "value");
- final selector = new AndSelector([nameSelector, attrSelector]);
-
- final suggestions = selector.suggestTags();
- expect(suggestions.length, 1);
- expect(suggestions.first.isValid, isTrue);
- expect(suggestions.first.toString(), equals('<panel attr="value"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestAndOr() {
- final nameSelector1 =
- new ElementNameSelector(new AngularElementImpl('name1', 10, 5, null));
- final nameSelector2 =
- new ElementNameSelector(new AngularElementImpl('name2', 10, 5, null));
- final orSelector1 = new OrSelector([nameSelector1, nameSelector2]);
-
- final attrSelector1 = new AttributeContainsSelector(
- new AngularElementImpl('attr1', 10, 5, null), "value");
- final attrSelector2 = new AttributeContainsSelector(
- new AngularElementImpl('attr2', 10, 5, null), "value");
- final orSelector2 = new OrSelector([attrSelector1, attrSelector2]);
-
- final selector = new AndSelector([orSelector1, orSelector2]);
-
- final suggestions = selector.suggestTags();
- expect(suggestions.length, 4);
- final suggestionsMap = <String, HtmlTagForSelector>{};
- suggestions.forEach((s) => suggestionsMap[s.toString()] = s);
-
- // basically (name1, name2)(attr1, attr2) though I'm not sure that's legal
- expect(suggestionsMap['<name1 attr1="value"'], isNotNull);
- expect(suggestionsMap['<name1 attr2="value"'], isNotNull);
- expect(suggestionsMap['<name2 attr1="value"'], isNotNull);
- expect(suggestionsMap['<name2 attr2="value"'], isNotNull);
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestClass() {
- final selector =
- new ClassSelector(new AngularElementImpl('myclass', 10, 5, null));
-
- final suggestions = _evenInvalidSuggestions(selector);
- expect(suggestions.length, 1);
- expect(suggestions.first.isValid, isFalse);
- expect(suggestions.first.toString(), equals('<null class="myclass"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestClasses() {
- final selector1 =
- new ClassSelector(new AngularElementImpl('class1', 10, 5, null));
- final selector2 =
- new ClassSelector(new AngularElementImpl('class2', 10, 5, null));
-
- final suggestions =
- selector2.refineTagSuggestions(_evenInvalidSuggestions(selector1));
- expect(suggestions.length, 1);
- expect(suggestions.first.isValid, isFalse);
- // check ClassSelector used tag.addClass(x), not tag.setAttr("class", x)
- expect(suggestions.first.toString(), equals('<null class="class1 class2"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestContainsIsInvalid() {
- final selector = new ContainsSelector("foo");
-
- final suggestions = _evenInvalidSuggestions(selector);
- expect(suggestions.length, 1);
- expect(suggestions.first.isValid, isFalse);
- // we could assert that it can't be made valid by adding a name,
- // but :contains is only allowed if it comprises the WHOLE selector (which
- // is admittedly not as well as the angular team coulddo and might change,
- // but :contains is so rare we can leave this).
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestNodeName() {
- final selector =
- new ElementNameSelector(new AngularElementImpl('panel', 10, 5, null));
-
- final suggestions = selector.suggestTags();
- expect(suggestions.length, 1);
- expect(suggestions.first.isValid, isTrue);
- expect(suggestions.first.toString(), equals("<panel"));
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestOrAnd() {
- final nameSelector1 =
- new ElementNameSelector(new AngularElementImpl('name1', 10, 5, null));
- final attrSelector1 = new AttributeContainsSelector(
- new AngularElementImpl('attr1', 10, 5, null), "value");
- final andSelector1 = new AndSelector([nameSelector1, attrSelector1]);
- final nameSelector2 =
- new ElementNameSelector(new AngularElementImpl('name2', 10, 5, null));
- final attrSelector2 = new AttributeContainsSelector(
- new AngularElementImpl('attr2', 10, 5, null), "value");
- final andSelector2 = new AndSelector([nameSelector2, attrSelector2]);
- final selector = new OrSelector([andSelector1, andSelector2]);
-
- final suggestions = selector.suggestTags();
- expect(suggestions.length, 2);
- final suggestionsMap = <String, HtmlTagForSelector>{};
- suggestions.forEach((s) => suggestionsMap[s.toString()] = s);
- expect(suggestionsMap['<name1 attr1="value"'], isNotNull);
- expect(suggestionsMap['<name2 attr2="value"'], isNotNull);
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestOrMergesSuggestionConstraints() {
- final nameSelector =
- new ElementNameSelector(new AngularElementImpl('panel', 10, 5, null));
- final attrSelector = new AttributeContainsSelector(
- new AngularElementImpl('attr', 10, 5, null), "value");
- final selector = new OrSelector([nameSelector, attrSelector]);
-
- final suggestions = _evenInvalidSuggestions(selector);
- expect(suggestions.length, 2);
- final suggestionsMap = <String, HtmlTagForSelector>{};
- suggestions.forEach((s) => suggestionsMap[s.toString()] = s);
- expect(suggestionsMap["<panel"], isNotNull);
- expect(suggestionsMap["<panel"].isValid, isTrue);
- expect(suggestionsMap['<null attr="value"'], isNotNull);
- expect(suggestionsMap['<null attr="value"'].isValid, isFalse);
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestOrOr() {
- final nameSelector1 =
- new ElementNameSelector(new AngularElementImpl('name1', 10, 5, null));
- final nameSelector2 =
- new ElementNameSelector(new AngularElementImpl('name2', 10, 5, null));
- final orSelector1 = new OrSelector([nameSelector1, nameSelector2]);
-
- final attrSelector1 = new AttributeContainsSelector(
- new AngularElementImpl('attr1', 10, 5, null), "value");
- final attrSelector2 = new AttributeContainsSelector(
- new AngularElementImpl('attr2', 10, 5, null), "value");
- final orSelector2 = new OrSelector([attrSelector1, attrSelector2]);
-
- final selector = new OrSelector([orSelector1, orSelector2]);
-
- final suggestions = _evenInvalidSuggestions(selector);
- expect(suggestions.length, 4);
- final suggestionsMap = <String, HtmlTagForSelector>{};
- suggestions.forEach((s) => suggestionsMap[s.toString()] = s);
-
- // basically (name1, name2),(attr1, attr2) though I'm not sure that's legal
- expect(suggestionsMap['<name1'], isNotNull);
- expect(suggestionsMap['<null attr2="value"'], isNotNull);
- expect(suggestionsMap['<name2'], isNotNull);
- expect(suggestionsMap['<null attr2="value"'], isNotNull);
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestPropertyNoValue() {
- final selector = new AttributeSelector(
- new AngularElementImpl('attr', 10, 5, null), null);
-
- final suggestions = _evenInvalidSuggestions(selector);
- expect(suggestions.length, 1);
- expect(suggestions.first.isValid, isFalse);
- expect(suggestions.first.toString(), equals("<null attr"));
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestPropertyWithValue() {
- final selector = new AttributeSelector(
- new AngularElementImpl('attr', 10, 5, null), "blah");
-
- final suggestions = _evenInvalidSuggestions(selector);
- expect(suggestions.length, 1);
- expect(suggestions.first.isValid, isFalse);
- expect(suggestions.first.toString(), equals('<null attr="blah"'));
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestRegexPropertyValueNoops() {
- final selector = new AttributeValueRegexSelector("foo");
-
- final suggestions = _evenInvalidSuggestions(selector);
- expect(suggestions.length, 1);
- expect(suggestions.first.isValid, isFalse);
- expect(suggestions.first.toString(),
- equals(new HtmlTagForSelector().toString()));
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestTagsFiltersInvalidResults() {
- final selector =
- new ClassSelector(new AngularElementImpl('class', 10, 5, null));
- expect(_evenInvalidSuggestions(selector), hasLength(1));
- expect(_evenInvalidSuggestions(selector).first.isValid, isFalse);
- expect(selector.suggestTags(), hasLength(0));
- }
-
- // ignore: non_constant_identifier_names
- void test_suggestWildcardProperty() {
- final selector = new AttributeContainsSelector(
- new AngularElementImpl('attr', 10, 5, null), "value");
-
- final suggestions = _evenInvalidSuggestions(selector);
- expect(suggestions.length, 1);
- expect(suggestions.first.isValid, isFalse);
- // [attr*=x] tells us they at LEAST want attr=x
- expect(suggestions.first.toString(), equals('<null attr="value"'));
- }
-
- /// [refineTagSuggestions] filters out invalid tags, but those are important
- /// for us to test sometimes. This will do the same thing, but keep invalid
- /// suggestions so we can inspect them.
- List<HtmlTagForSelector> _evenInvalidSuggestions(Selector selector) {
- final tags = <HtmlTagForSelector>[new HtmlTagForSelector()];
- return selector.refineTagSuggestions(tags);
- }
-}
-
-class _ElementViewMock extends Mock implements ElementView {}
-
-class _SelectorMock extends Mock implements Selector {
- final String text;
-
- _SelectorMock(this.text);
-
- @override
- String toString() => text;
-}
-
-class _SelectorTest {
- ElementView element = new _ElementViewMock();
- Template template = new _TemplateMock();
-
- List<ResolvedRange> resolvedRanges = <ResolvedRange>[];
-
- void setUp() {
- // TODO(mfairhurst): remove `as dynamic`. See https://github.com/dart-lang/sdk/issues/33934
- when(template.addRange(typed(any), typed(any)) as dynamic)
- .thenAnswer((invocation) {
- final range = invocation.positionalArguments[0] as SourceRange;
- final element = invocation.positionalArguments[1] as AngularElement;
- resolvedRanges.add(new ResolvedRange(range, element));
- });
- }
-
- void _assertRange(ResolvedRange resolvedRange, int offset, int length,
- AngularElement element) {
- final range = resolvedRange.range;
- expect(range.offset, offset);
- expect(range.length, length);
- expect(resolvedRange.element, element);
- }
-
- SourceRange _newStringSpan(int offset, String value) =>
- new SourceRange(offset, value.length);
-}
-
-class _SourceMock extends Mock implements Source {}
-
-class _TemplateMock extends Mock implements Template {}
diff --git a/angular_analyzer_plugin/test/test_all.dart b/angular_analyzer_plugin/test/test_all.dart
deleted file mode 100644
index 19d2e73..0000000
--- a/angular_analyzer_plugin/test/test_all.dart
+++ /dev/null
@@ -1,30 +0,0 @@
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'angular_driver_test.dart' as angular_driver_test;
-import 'ast_test.dart' as ast_test;
-import 'completion_contributor_test.dart' as completion_contributor_test;
-import 'file_tracker_test.dart' as file_tracker_test;
-import 'navigation_test.dart' as navigation_test;
-import 'occurrences_test.dart' as occurrences_test;
-import 'offsetting_constant_value_visitor_test.dart'
- as offsetting_constant_value_visitor_test;
-import 'plugin_test.dart' as plugin_test;
-import 'resolver_test.dart' as resolver_test;
-import 'selector_test.dart' as selector_test;
-
-/// Utility for manually running all tests.
-void main() {
- // ignore: unnecessary_lambdas
- defineReflectiveSuite(() {
- plugin_test.main();
- resolver_test.main();
- selector_test.main();
- angular_driver_test.main();
- ast_test.main();
- offsetting_constant_value_visitor_test.main();
- navigation_test.main();
- occurrences_test.main();
- completion_contributor_test.main();
- file_tracker_test.main();
- }, name: 'Angular Plugin tests');
-}
diff --git a/angular_analyzer_plugin/tools/analyzer_plugin/bin/plugin.dart b/angular_analyzer_plugin/tools/analyzer_plugin/bin/plugin.dart
deleted file mode 100644
index ef767c3..0000000
--- a/angular_analyzer_plugin/tools/analyzer_plugin/bin/plugin.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-import 'dart:isolate';
-
-import 'package:angular_analyzer_plugin/starter.dart';
-
-void main(List<String> args, SendPort sendPort) {
- start(args, sendPort);
-}
diff --git a/angular_analyzer_plugin/tools/analyzer_plugin/pubspec.yaml b/angular_analyzer_plugin/tools/analyzer_plugin/pubspec.yaml
deleted file mode 100644
index 9069190..0000000
--- a/angular_analyzer_plugin/tools/analyzer_plugin/pubspec.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-name: analyzed_angular_plugin_loader
-version: 0.0.0
-description: Self-loader of the plugin for people using an exact version.
-environment:
- sdk: '>=2.0.0-dev.0.0 < 3.0.0'
-dependencies:
- angular_analyzer_plugin: '0.0.17+4'
-dev_dependencies:
diff --git a/angular_analyzer_plugin/tools/analyzer_plugin/pubspec.yaml.defaults b/angular_analyzer_plugin/tools/analyzer_plugin/pubspec.yaml.defaults
deleted file mode 100644
index df76bbc..0000000
--- a/angular_analyzer_plugin/tools/analyzer_plugin/pubspec.yaml.defaults
+++ /dev/null
@@ -1,23 +0,0 @@
-name: analyzed_angular_plugin_loader
-version: 0.0.0
-description: Temp means of loading angular analysis into an angular project.
-environment:
- sdk: '>=1.24.0-dev.1.0'
-dependencies:
- angular_analyzer_plugin: '0.0.8'
-dev_dependencies:
-dependency_overrides:
- angular_analyzer_plugin:
- path: ABSOLUTE_PATH_TO_REPO/angular_analyzer_plugin
- analyzer:
- path: ABSOLUTE_PATH_TO_REPO/deps/sdk/pkg/analyzer
- front_end:
- path: ABSOLUTE_PATH_TO_REPO/deps/sdk/pkg/front_end
- analyzer_plugin:
- path: ABSOLUTE_PATH_TO_REPO/deps/sdk/pkg/analyzer_plugin
- kernel:
- path: ABSOLUTE_PATH_TO_REPO/deps/sdk/pkg/kernel
- angular_ast:
- git:
- url: https://github.com/dart-lang/angular_ast
- ref: master
diff --git a/assets/angular-dart-intellij-plugin-demo.gif b/assets/angular-dart-intellij-plugin-demo.gif
deleted file mode 100644
index 33a7c61..0000000
--- a/assets/angular-dart-intellij-plugin-demo.gif
+++ /dev/null
Binary files differ
diff --git a/codereview.settings b/codereview.settings
deleted file mode 100644
index 078f7ce..0000000
--- a/codereview.settings
+++ /dev/null
@@ -1,4 +0,0 @@
-# This file is used by gcl to get repository specific information.
-CODE_REVIEW_SERVER: http://codereview.chromium.org/
-VIEW_VC: https://github.com/dart-lang/angular2-dart-analyzer/commit/
-
diff --git a/deps/pubspec.yaml b/deps/pubspec.yaml
deleted file mode 100644
index 576aff2..0000000
--- a/deps/pubspec.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-name: non_sdk_deps
-version: 0.0.0
-description: What we need that the sdk doesn't provide
-dependencies:
- tuple: '^1.0.1'
- angular_ast: '^0.5.6'
-dev_dependencies:
- test_reflective_loader: '^0.1.8'
- test: '^1.2.0'
diff --git a/playground/.gitignore b/playground/.gitignore
deleted file mode 100644
index bff2d76..0000000
--- a/playground/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.iml
diff --git a/playground/README.md b/playground/README.md
deleted file mode 100644
index 34683fc..0000000
--- a/playground/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Angular Dart Playground
-
-This exercises most of the core features that the plugin can typecheck.
-
-It does not have a web directory (yet) so you can't actually run it (yet).
diff --git a/playground/analysis_options.yaml b/playground/analysis_options.yaml
deleted file mode 100644
index 8f39998..0000000
--- a/playground/analysis_options.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-analyzer:
- plugins:
- - angular_analyzer_plugin
diff --git a/playground/lib/bubbled_directive.dart b/playground/lib/bubbled_directive.dart
deleted file mode 100644
index c7315bf..0000000
--- a/playground/lib/bubbled_directive.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-import 'dart:async';
-import 'package:angular/angular.dart';
-
-@Directive(selector: "[bubbled]", exportAs: 'bubble')
-class BubbledDirective {
-
- @Input("BubbleWidth") int width;
- @Output() Stream popped;
-
-}
diff --git a/playground/lib/counter_component.dart b/playground/lib/counter_component.dart
deleted file mode 100644
index 64cbd2b..0000000
--- a/playground/lib/counter_component.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-import 'dart:async';
-import 'dart:html';
-import 'package:angular/angular.dart';
-
-const foo = 1;
-
-@Component(
- selector: 'my-counter',
- template: r'<button (click)="increment($event)">++</button> {{foo}}',
- exports: const [foo])
-class CounterComponent {
- @Input()
- int count;
- StreamController<int> _incrementedController;
- @Output()
- Stream<int> get incremented => _incrementedController.stream;
-
- increment(MouseEvent event) {
- count++;
- _incrementedController.add(count);
- }
-
- CounterComponent() {}
-}
diff --git a/playground/lib/overview_component.dart b/playground/lib/overview_component.dart
deleted file mode 100644
index c274018..0000000
--- a/playground/lib/overview_component.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-import 'package:angular/angular.dart';
-import 'counter_component.dart';
-import 'bubbled_directive.dart';
-
-@Component(
- selector: 'blah',
- directives: const [CounterComponent, NgFor, NgIf, BubbledDirective],
- templateUrl: 'overview_component.html')
-class OverviewComponent {
- String header;
- List<String> items;
-
- OtherComponent() {}
-}
diff --git a/playground/lib/overview_component.html b/playground/lib/overview_component.html
deleted file mode 100644
index 660fc63..0000000
--- a/playground/lib/overview_component.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<h1 #h1>Showing {{items.length}} items:</h1>
-
-<li *ngFor='let item of items; var x=index' [hidden]='item != null'>
- {{x}}: {{item}}
-</li>
-
-<button (click)="items.add('hey');" *ngIf="items.length == 0" bubbled #bubble="bubble">{{bubble.width}}</button>
-<button (click)="h1.hidden = !h1.hidden">Hide header</button>
-
-<my-counter [count]='4' (incremented)='items.add($event.toString())'></my-counter>
-
-<my-counter></my-counter>
diff --git a/playground/pubspec.yaml b/playground/pubspec.yaml
deleted file mode 100644
index 8d21258..0000000
--- a/playground/pubspec.yaml
+++ /dev/null
@@ -1,16 +0,0 @@
-name: angular2_quickstart
-description: QuickStart
-version: 0.0.1
-environment:
- sdk: '>=2.0.0-dev.35.0 <2.0.0'
-
-dependencies:
- angular: 5.0.0-alpha+9
- angular_forms: 2.0.0-alpha+1
-
-dev_dependencies:
- angular_analyzer_plugin: any
-
-dependency_overrides:
- angular_analyzer_plugin:
- path: ../angular_analyzer_plugin
diff --git a/tools/check_format.sh b/tools/check_format.sh
deleted file mode 100755
index 6a4477c..0000000
--- a/tools/check_format.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-# Fast fail the script on failures.
-set -e
-
-# Check whether we need to format any files.
-DARTFMT_OUT=$(dartfmt -n "$PACKAGE")
-if [[ ! -z "$DARTFMT_OUT" ]]; then
- printf "$PACKAGE has unformatted Dart files: \n$DARTFMT_OUT\n"
- printf "Run 'dartfmt -w $PACKAGE'"
- exit 1
-fi
diff --git a/tools/check_no_solo_tests.sh b/tools/check_no_solo_tests.sh
deleted file mode 100755
index 0d0a389..0000000
--- a/tools/check_no_solo_tests.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-# Fast fail the script on failures.
-set -e
-
-# Look for solo_test in test/*, and catch the "fast fail" error when no results
-GREP_OUT=$(egrep 'solo(T|_t)est' $PACKAGE/test -r || :)
-if [[ ! -z "$GREP_OUT" ]]; then
- printf "$PACKAGE is skipping tests due to solo_test(s): \n$GREP_OUT\n"
- exit 1
-fi
diff --git a/tools/get_deps.sh b/tools/get_deps.sh
deleted file mode 100755
index a054d67..0000000
--- a/tools/get_deps.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-cd deps
-
-echo Using depot tools to pull in the SDK
-gclient config https://github.com/dart-lang/sdk.git
-gclient sync
-echo done
-
-cd ..
-
-./tools/update_deps.sh
diff --git a/tools/travis.sh b/tools/travis.sh
deleted file mode 100755
index 97b8e96..0000000
--- a/tools/travis.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-
-# Fast fail the script on failures.
-set -e
-
-if [[ -z "$TRAVIS_BRANCH" ]]
-then
- TRAVIS_BRANCH="$(git branch)"
-fi
-
-# Go to the respective package directory
-cd $PACKAGE
-
-# Check if we should resolve pub dependencies, or use what was fetched from
-# depot tools.
-if [[ -z "$(echo $TRAVIS_BRANCH | grep 'SDK_AT_HEAD')" ]]
-then
- echo Using pub for the SDK dependencies.
- echo
- echo To test against the SDK at master, include SDK_AT_HEAD in your branch
- echo name. Otherwise, we will test with pub.
-
- pub get
-else
- echo Using depot_tools for the SDK dependencies.
- echo
- echo Because your branch name includes SDK_AT_HEAD, this will test against
- echo the latest SDK source instead of using pub.
-fi
-
-# Analyze the test first
-dartanalyzer lib test
-
-# Run the actual tests
-#dart --no-preview-dart-2 --checked test/test_all.dart # in dart 1 mode
-dart --enable-asserts test/test_all.dart # and dart 2 mode
-
diff --git a/tools/update_deps.sh b/tools/update_deps.sh
deleted file mode 100755
index 3e44b97..0000000
--- a/tools/update_deps.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-echo Updating pub deps
-cd deps
-pub get
-echo done
-echo
-
-echo Updating the sdk with depot_tools
-gclient sync
-cd sdk
-git checkout analyzer
-cd ..
-echo done
-echo
-
-cd ..
-
-echo Copying and transforming sdk .packages to be useful to this repo
-cat deps/sdk/.packages | grep -v '^typed_mock' | grep -v '^unittest' | grep -v '^test_reflective_loader' | sed 's/:/:deps\/sdk\//' > .packages
-echo done
-echo
-
-echo Copying pub .packages to be useful to this repo
-cat deps/.packages | grep '# Generated' >> .packages
-cat deps/.packages | grep 'angular_ast' >> .packages
-cat deps/.packages | grep 'test_reflective_loader' >> .packages
-cat deps/.packages | grep 'typed_mock' >> .packages
-cat deps/.packages | grep 'unittest' >> .packages
-cat deps/.packages | grep 'non_sdk_deps' >> .packages
-echo done
-echo
-
-echo Adding analyzer plugin to .packages
-echo 'angular_analyzer_plugin:angular_analyzer_plugin/lib' >> .packages
-echo done
-echo
-
-echo Updating new plugin architecture .packages file
-echo Adding self hosting plugin architecture .packages file
-cd angular_analyzer_plugin/tools/analyzer_plugin
-pub get
-cd ../../..
-echo done
-echo
-