Commit Graph

88 Commits

Author SHA1 Message Date
Charles Lyding 0119f46daf fix(core): set migration schematic versions to valid semver versions (#32991)
PR Close #32991
2019-10-04 13:54:39 -07:00
Charles Lyding f8eca840ee fix(core): update migration descriptions with links to AIO documentation (#32991)
PR Close #32991
2019-10-04 13:54:39 -07:00
Kristiyan Kostadinov 7f6429d802 refactor: re-enable dynamic queries migration (#32992)
Re-enables the dynamic queries migration, now that we have all of the necessary framework changes in place.

Also moves the logic that identifies static queries out of the compiler and into the static queries migration, because that's the only place left that's using it.

PR Close #32992
2019-10-04 13:54:09 -07:00
Alan 01677b21b6 refactor(core): add `createMigrationCompilerHost` (#32827)
Current we need to create and override certain compiler host methods in every schematic because schematics use a virtual fs. We this change we extract this logic to a common util.

PR Close #32827
2019-10-04 11:45:35 -07:00
Keen Yee Liau adb562bca6 fix(language-service): create StaticReflector once only (#32543)
The creation of StaticReflector in createMetadataResolver() is a very expensive operation because it involves numerous module resolutions.
To make matter worse, since the API of the Reflector does not provide the ability to invalidate its internal caches, it has to be destroyed and recreated on *every* program change.
This has a HUGE impact on performance.
This PR fixes this problem by carefully invalidating all StaticSymbols in a file that has changed, thereby reducing the overhead of recomputation on program change.

PR Close #32543
2019-10-03 15:02:03 -07:00
Paul Gschwendtner 6f5f481fda refactor(core): undecorated-classes-with-di migration should ignore referenced resources (#32953)
Currently the undecorated-classes-with-di migration leverages NGC in order
to work with metadata resolution. Since NGC by default tries to resolve referenced
resources on initialization of the underlying TS program, it can result in unexpected
migration failures due to missing resource files.

This is especially an issue since the CLI wraps the `AngularCompilerProgram` with
special logic (i.e. to support SCSS preprocessing etc.). We don't have all of this since
we instantiate a vanilla NGC program.

The solution to the problem is to simply treat resource requests as valid, and returning
a fake content. The migration is not dependent on templates or stylesheets.. so it's the
simplest and most robust solution.

Fixes #32826

PR Close #32953
2019-10-02 14:54:33 -07:00
Paul Gschwendtner 90dda5873a test(core): remove "enableIvy" compiler option from migration tests (#32954)
ec4381d explicitly set `enableIvy: false` for all migrations inside
the core package. This actually hides migration issues because the
migration itself should ensure that it instantiates the right
compiler program if it relies on `@angular/compiler-cli`.

We should remove these options from all migration tests to
ensure that we catch issues with migrations running in version
9 where Ivy is enabled by default.

e.g. e5636a322c
was accidentally hidden due to the `enableIvy: false` option.

PR Close #32954
2019-10-02 14:53:41 -07:00
Paul Gschwendtner 7503e3540d refactor(core): static-queries migration should never use ngtsc (#32954)
ec4381d enabled Ivy by default. This is problematic as migrations
like `static-queries` depend on the `AngularCompilerProgram` (NGC)
in order to perform the migration from version 7 to version 8.

In order to ensure that the migration always runs with NGC
(and doesn't get the `NgtscProgram`), we need to explicitly disable
ivy when creating the `@angular/compiler-cli` program for the migration.

This code is still relevant even though the update from version 7
to version 8 landed. Developers can run `ng update` from version 7
and immediately get to version 9 where Ivy is enabled by default (and in
that case we need to ensure that ngtsc is not accidentally used).

Similar to
e5636a322c.

PR Close #32954
2019-10-02 14:53:41 -07:00
crisbeto 39bc6f7bea build: temporarily disable dynamic queries migration (#32837)
Disables the dynamic queries migration until we can land the relevant framework changes (#32686 and #32720).

PR Close #32837
2019-09-24 17:57:15 -07:00
crisbeto f5982fd746 feat(core): add dynamic queries schematic (#32231)
Adds a schematic that will remove the explicit `static: false` flag from dynamic queries. E.g.

```ts
import { Directive, ViewChild, ContentChild, ElementRef } from '@angular/core';

@Directive()
export class MyDirective {
  @ViewChild('child', { static: false }) child: any;
  @ViewChild('secondChild', { read: ElementRef, static: false }) secondChild: ElementRef;
  @ContentChild('thirdChild', { static: false }) thirdChild: any;
}
```

```ts
import { Directive, ViewChild, ContentChild, ElementRef } from '@angular/core';

@Directive()
export class MyDirective {
  @ViewChild('child') child: any;
  @ViewChild('secondChild', { read: ElementRef }) secondChild: ElementRef;
  @ContentChild('thirdChild') thirdChild: any;
}
```

PR Close #32231
2019-09-11 19:14:03 -04:00
Paul Gschwendtner bf15d3eea8 test: switch away from deprecated "runSchematic" function (#32557)
Switches away from the deprecated "runSchematic" function to
the "runSchematicAsync" function.

Similar to 99c9bcab03.

PR Close #32557
2019-09-09 12:22:37 -04:00
Paul Gschwendtner c56c2416a9 refactor(core): undecorated-classes-with-decorated-fields migration commits empty updates (#32391)
Commit 904a2018e0 introduced a new migration for
undecorated classes with decorated Angular class members. Currently the migration
always calls `tree.beginUpdate` and `tree.commitUpdate` (even if there are no changes).

This causes unnecessary updates to be reported to developers running `ng update`. Once
an update is commited, the CLI will report the update regardless of whether any changes were
made or not.

This behavior can be observed in the `ng_update_migrations` integration test. See:
https://circleci.com/gh/angular/angular/438470#tests/containers/3. Notice how all
source files are denoted as `UPDATED` (even though there are no changes).

PR Close #32391
2019-08-30 12:46:01 -07:00
Paul Gschwendtner 3af99a7b4a refactor(core): wire up missing-injectable migration for ng-update (#32349)
Initially the `missing-injectable` migration was only being used
in google3. Wiring the migration up in the CLI migrations was
planned to be done in a follow-up.

PR Close #32349
2019-08-29 12:34:43 -07:00
Paul Gschwendtner 60a056d5dc refactor(core): undecorated classes migration should not decorate classes if not needed (#32319)
Currently the undecorated classes migration decorates base classes if no
explicit constructor is defined on all classes in the inheritance chain.

We only want to decorate base classes which define a constructor that is
inherited. Additionally for best practice, all classes in between the class
that inherits the constructor and the one that defines it are also decorated.

PR Close #32319
2019-08-28 17:11:36 -07:00
Paul Gschwendtner 543631f2b3 refactor(core): undecorated-classes migration should properly construct object literal from metadata (#32319)
The `undecorated-classes-with-di` migration currently creates invalid object literals from parsed
NGC metadata files if there are object literal properties with keys that contain special characters.

e.g. consider a decorated base class with a host binding using `[class.X]`. Currently the migration
parses and converts the metadata to TypeScript code but incorrectly uses `[class.X]` unquoted as
identifier.

PR Close #32319
2019-08-28 17:11:36 -07:00
Paul Gschwendtner d0f3539e6e test(core): cleanup bazel target names for schematic tests (#32318)
Apparently the names of the bazel test targets in the schematics are
incorrect. This commit updates the target names to match their bazel
package name.

PR Close #32318
2019-08-28 17:11:04 -07:00
Paul Gschwendtner e5636a322c refactor(core): undecorated-classes-with-di migration should never use ngtsc (#32318)
ec4381dd40 enabled Ivy by default. This is
problematic as migrations like `undecorated-classes-with-di` depend on the
`AngularCompilerProgram` (NGC) in order to perform the migration from
version 8 to version 9. In order to ensure that the migration always runs
with NGC (and doesn't get the `NgtscProgram`), we need to explicitly disable
ivy when creating the `@angular/compiler-cli` program for the migration.

PR Close #32318
2019-08-28 17:11:04 -07:00
Kristiyan Kostadinov 904a2018e0 feat(core): add undecorated classes with decorated fields schematic (#32130)
Adds a schematic that adds a `Directive` decorator to undecorated classes that have fields that use Angular decorators.

PR Close #32130
2019-08-22 10:05:38 -07:00
Alex Rickabaugh ec4381dd40 feat: make the Ivy compiler the default for ngc (#32219)
This commit switches the default value of the enableIvy flag to true.
Applications that run ngc will now by default receive an Ivy build!

This does not affect the way Bazel builds in the Angular repo work, since
those are still switched based on the value of the --define=compile flag.
Additionally, projects using @angular/bazel still use View Engine builds
by default.

Since most of the Angular repo tests are still written against View Engine
(particularly because we still publish VE packages to NPM), this switch
also requires lots of `enableIvy: false` flags in tsconfigs throughout the
repo.

Congrats to the team for reaching this milestone!

PR Close #32219
2019-08-20 16:41:08 -07:00
Paul Gschwendtner 639b732024 refactor(core): remove disabled injectable-pipe migration (#32184)
Initially the plan was to have a migration that adds `@Injectable()` to
all pipes in a CLI project so that the pipes can be injected in Ivy
similarly to how it worked in view engine.

Due to the planned refactorings which ensure that `@Directive`, `@Component`
and `@Pipe` also have a factory definition, this migration is no longer
needed for Ivy. Additionally since it is already disabled (due to
572b54967c) and we have a more generic
migration (known as `missing-injectable)` that could do the same as
`injectable-pipe`, we remove the migration from the code-base.

PR Close #32184
2019-08-19 15:44:02 -07:00
Paul Gschwendtner 024c31da25 feat(core): add undecorated classes migration schematic (#31650)
Introduces a new migration schematic that follows the given
migration plan: https://hackmd.io/@alx/S1XKqMZeS.

First case: The schematic detects decorated directives which
inherit a constructor. The migration ensures that all base
classes until the class with the explicit constructor are
properly decorated with "@Directive()" or "@Component". In
case one of these classes is not decorated, the schematic
adds the abstract "@Directive()" decorator automatically.

Second case: The schematic detects undecorated declarations
and copies the inherited "@Directive()", "@Component" or
"@Pipe" decorator to the undecorated derived class. This
involves non-trivial import rewriting, identifier aliasing
and AOT metadata serializing
(as decorators are not always part of source files)

PR Close #31650
2019-08-13 14:40:52 -07:00
Paul Gschwendtner e4d5102b17 build: ensure schematics are built with typescript strict flag (#31967)
Follow-up to #30993 where we build all Angular packages with
the TypeScript `--strict` flag. The flag improves overall code
health and also helps us catch issues easier.

PR Close #31967
2019-08-13 11:39:00 -07:00
Paul Gschwendtner 9896d438c0 refactor(core): move renderer2 migration lint rule into google3 folder (#31817)
Moves the `renderer_to_renderer2` migration google3 tslint rule
into the new `google3` directory. This is done for consistency
as we recently moved all google3 migration rules into a new
`google3` folder (see: f69e4e6f77).

PR Close #31817
2019-08-09 10:46:45 -07:00
Paul Gschwendtner 684579b338 build: create google3 migration tests bazel target (#31817)
Creates a separate bazel target for the google3 migration
tests. The benefit is that it's faster to run tests for
public migrations in development. Google3 lint rules are
usually another story/implementation and the tests are quite
slow due to how TSLint applies replacements.

Additionally if something changes in the google3 tslint rules,
the tests which aren't affected re-run unnecessarily.

PR Close #31817
2019-08-09 10:46:45 -07:00
Paul Gschwendtner f69e4e6f77 refactor(core): move google3 migration rules into single directory (#30956)
Moves all google3 migration tslint rules into a single directory.
This makes it easier to wire up multiple migration rules in
google3 without having to update the rule directories each time
a new migration is available.

PR Close #30956
2019-07-23 15:52:40 -07:00
Paul Gschwendtner 9f2ae5d6ff feat(ivy): introduce missing-injectable migration for google3 (#30956)
Introduces a new migration schematic for adding the "@Injectable()"
decorator to provider classes which are currently not migrated. Previously
in ViewEngine, classes which are declared as providers sometimes don't
require the "@Injectable()" decorator
(e.g. https://stackblitz.com/edit/angular-hpo7gw)

With Ivy, provider classes need to be explicitly decorated with
the "@Injectable()" decorator if they are declared as providers
of a given module. This commit introduces a migration schematic
which automatically adds the explicit decorator to places where
the decorator is currently missing.

The migration logic is designed in a CLI devkit and TSlint agnostic
way so that we can also have this migration run as part of a public
CLI migration w/ `ng update`. This will be handled as part of a follow-up to reiterate on console output etc.

Resolves FW-1371

PR Close #30956
2019-07-23 15:52:40 -07:00
crisbeto c0955975f4 feat(core): add automatic migration from Renderer to Renderer2 (#30936)
Adds a schematic and tslint rule that automatically migrate the consumer from `Renderer` to `Renderer2`. Supports:
* Renaming imports.
* Renaming property and method argument types.
* Casting to `Renderer`.
* Mapping all of the methods from the `Renderer` to `Renderer2`.

Note that some of the `Renderer` methods don't map cleanly between renderers. In these cases the migration adds a helper function at the bottom of the file which ensures that we generate valid code with the same return value as before. E.g. here's what the migration for `createText` looks like.

Before:
```
class SomeComponent {
  createAndAddText() {
    const node = this._renderer.createText(this._element.nativeElement, 'hello');
    node.textContent += ' world';
  }
}
```

After:
```
class SomeComponent {
  createAndAddText() {
    const node = __rendererCreateTextHelper(this._renderer, this._element.nativeElement, 'hello');
    node.textContent += ' world';
  }
}

function __rendererCreateTextHelper(renderer: any, parent: any, value: any) {
  const node = renderer.createText(value);
  if (parent) {
    renderer.appendChild(parent, node);
  }
  return node;
}
```

This PR resolves FW-1344.

PR Close #30936
2019-07-03 09:03:37 -07:00
Greg Magolan 361109d80f build: update to rules_nodejs 0.32.2 (#31325)
Brings in ts_library fixes required to get angular/angular building after 0.32.0:
typescript: exclude typescript lib declarations in node_module_library transitive_declarations
typescript: remove override of @bazel/tsetse (+1 squashed commit)

@npm//node_modules/foobar:foobar.js labels changed to @npm//:node_modules/foobar/foobar.js with fix for bazelbuild/rules_nodejs#802

also updates to rules_rass commit compatible with rules_nodejs 0.32.0

PR Close #31325
2019-07-01 14:16:42 -07:00
Alex Rickabaugh 660800ca4e Revert "build: update to rules_nodejs 0.32.2 (#31019)" (#31267)
This reverts commit a38433f36b.

Reason: this causes failures in g3 with i18n extraction. See #31267.

PR Close #31267
2019-06-25 14:36:00 -07:00
Greg Magolan a38433f36b build: update to rules_nodejs 0.32.2 (#31019)
Brings in ts_library fixes required to get angular/angular building after 0.32.0:
typescript: exclude typescript lib declarations in node_module_library transitive_declarations
typescript: remove override of @bazel/tsetse (+1 squashed commit)

@npm//node_modules/foobar:foobar.js labels changed to @npm//:node_modules/foobar/foobar.js with fix for bazelbuild/rules_nodejs#802

also updates to rules_rass commit compatible with rules_nodejs 0.32.0

PR Close #31019
2019-06-25 10:21:07 -07:00
Paul Gschwendtner 70ad91ed8b refactor(compiler): recursive ast expression visitor not passing context (#31085)
Currently the `RecursiveAstVisitor` that is part of the template expression
parser does not _always_ properly pass through the context that can be
specified when visting a given expression. Only a handful of AST types
pass through the context while others are accidentally left out. This causes
unexpected and inconsistent behavior and basically makes the `context`
parameter not usable if the type of template expression is not known.

e.g. the template variable assignment migration currently depends on
the `RecursiveAstVisitor` but sometimes breaks if developers use
things like conditionals in their template variable assignments.

Fixes #31043

PR Close #31085
2019-06-20 11:12:16 -07:00
Andrew Kushnir e0c36620c1 test: resotre "async" around tests where "await" is used (#30762)
The "async" around a couple tests was removed because of the merge conflict in one of the previous commits (80394ce08b). This change restores missing "async"s.

PR Close #30762
2019-05-30 23:14:16 -07:00
Alan Agius 80394ce08b fix(core): TypeScript related migrations should cater for BOM (#30719)
fix(@schematics/angular): TypeScript related migrations should cater for BOM

In the CLI `UpdateRecorder` methods such as `insertLeft`, `remove` etc.. accepts positions which are not offset by a BOM. This is because when a file has a BOM a different recorder will be used https://github.com/angular/angular-cli/blob/master/packages/angular_devkit/schematics/src/tree/recorder.ts#L72 which caters for an addition offset/delta.

The main reason for this is that when a developer is writing a schematic they shouldn't need to compute the offset based if a file has a BOM or not and is handled out of the box.

Example
```ts
recorder.insertLeft(5, 'true');
```

However this is unfortunate in the case if a ts SourceFile is used and one uses `getWidth` and `getStart` method they will already be offset by 1, which at the end it results in a double offset and hence the problem.

Fixes #30713

PR Close #30719
2019-05-30 20:48:45 -07:00
crisbeto 99c9bcab03 test: move away from deprecated testing method (#30747)
Switches all of the tests away from the `runSchematic` method which was deprecated in 8.0 (see https://github.com/angular/angular-cli/pull/14412). Along the same lines as https://github.com/angular/components/pull/16150.

PR Close #30747
2019-05-30 20:46:48 -07:00
Paul Gschwendtner d72479b628 docs(core): template-var-assignment schematic should link to deprecation guide (#30702)
Instead of linking to a markdown file explaining what the migration warnings
are about, we should link to the deprecation guide which now also contains
an entry for that schematic. This makes the deprecation explanations
consistent and more centralized.

PR Close #30702
2019-05-29 13:50:34 -04:00
Paul Gschwendtner 6bf5ec241d docs(core): static-query migration should use permalink for migration guide (#30649)
8479cb4233 updated the static-query migration
to refer to the new guide on AIO. Unfortunately these URLs are currently not
valid as the guide is only available on `next.angular.io` right now. In order to
make the link work permanently (e.g. if we eventually remove the guide in future
major versions), we use the permalink from the `v8` subdomain.

PR Close #30649
2019-05-24 10:08:16 -05:00
Kara Erickson 8479cb4233 docs(core): update static query schematic with guide link (#30646)
PR Close #30646
2019-05-23 22:14:49 -07:00
Paul Gschwendtner 132c61dfd4 refactor(core): static-query migration should warn about syntax failures (#30628)
Currently if a project has source-files with syntax failures and the migration
has been started on a broken project, we silently migrate *as much as possible*,
but never notify the developer that the project was in a broken state and that
he can re-run the migration after the failures are fixed.

Additionally the template strategy does not need to exit gracefully if it detects
Angular semantic diagnostics on generated files (template type checking). These
diagnostics are not relevant for the query timing analysis.

PR Close #30628
2019-05-23 10:31:48 -07:00
Paul Gschwendtner 5640cedc82 refactor(core): static-query migration should always use template strategy (#30628)
We are removing the prompt for the `static-query` migration and make the
template strategy the migration strategy for the migration. The usage
strategy is good for best-practices, but for now we want to ensure that
the migration is a seamless as possible and that is only achievable my
re-using the same logic that View Engine uses for determining the
timing of a query.

PR Close #30628
2019-05-23 10:31:48 -07:00
Paul Gschwendtner f74e0fd825 refactor(core): migrations should parse cli workspace config as json5 (#30582)
Currently we try to parse CLI workspace configurations gracefully by
using the native `JSON.parse()` method. This means that the CLI workspace
configuration needs to follow the strict JSON specification because otherwise
the migrations would not be able to find TypeScript configurations in the CLI
project where JSON5 workspace configurations are supported.

In order to handle such workspace configurations, we leverage the JSON
parsing logicfrom the `@angular-devkit/core` which is also used by the CLI.

PR Close #30582
2019-05-21 17:26:22 -07:00
Paul Gschwendtner 9e5377a2e3 refactor(core): improve messages for static-query migrations (#30458)
Slightly improves the messages for the static-query migration in order
to make the terminal output less verbose but more helpful. Unfortunately
we are limited in what we can print due to the devkit not providing much
utilities for printing good messages from a migration schematic.

PR Close #30458
2019-05-14 14:04:44 -07:00
Paul Gschwendtner 0cdf5980e2 fix(core): static-query migration should not fallback to test strategy (#30458)
Currently if something fails in the selected strategy (e.g. AOT failures),
the migration currently accidentally falls back to the test strategy. This
is not helpful as we want to give developers the possibility to re-run
the migration after fixing potential AOT failures.

PR Close #30458
2019-05-14 14:04:43 -07:00
Paul Gschwendtner 6ceb9034dc fix(core): static-query migration errors not printed properly (#30458)
Apparently the devkit logger is not able to properly print
out error objects, so we need to convert them to a string
before in order to make the error visible to the user.

This is not testable without an e2e test that validates the CLI
terminal output.

PR Close #30458
2019-05-14 14:04:43 -07:00
Alex Eagle 06efc340b6 build: update rules_nodejs and clean up bazel warnings (#30370)
Preserve compatibility with rollup_bundle rule.
Add missing npm dependencies, which are now enforced by the strict_deps plugin in tsc_wrapped

PR Close #30370
2019-05-14 10:08:45 -07:00
Paul Gschwendtner 8d3365e4fc fix(core): static-query usage migration strategy should detect ambiguous query usage (#30215)
Currently we always just set the timing to `false` if we aren't
able to analyze a given call expression or new expression. e.g.

```ts
ngOnInit() {
  thirdPartyCallSync(() => this.query.doSomething())
}
```

In that case the `thirdPartyCallSync` function comes from the `node_modules`
and is only defined through types while there is no code for the
actual function logic that can be analyzed. This makes it impossible
to tell whether the given call expression actually causes the specified
arrow function to be executed synchronously or not. In order to be able
to make this better, we now peek into the passed arrow function and
check for a synchronous query usage. If so, we set the query timing to
static and mark it as ambiguous. This ensures that the usage strategy is
less "magical" and more correct with third-party code.

Additionally since functions like `setTimeout` are not analyzable but known
to be asynchronous, there is a hard-coded list of known functions which
shouldn't be marked as ambiguous.

Resolves FW-1214. As planned within https://hackmd.io/hPiLWpPlQ4uynC1luIBdfQ

PR Close #30215
2019-05-09 14:39:06 -07:00
Paul Gschwendtner 0ffdb48f62 fix(core): static-query migration should handle queries on accessors (#30327)
Currently the static-query migration ignores queries declared on getters
or setters as these are not part of a `PropertyDeclaration`. We need to
handle these queries in order to cover all queries within a given project.

The usage strategy is not able to detect timing for queries on accessors,
so we add a TODO and print a message. The template strategy is able
to detect the proper timing for such queries because it's not dependent
on detecting the usage of the query.

Resolves FW-1215

PR Close #30327
2019-05-09 11:22:37 -07:00
Paul Gschwendtner 509352fc36 fix(core): static-query migration should gracefully exit if AOT compiler throws (#30269)
The static-query template strategy leverages the AOT compiler
in order to determine the query timing. Unfortunately the AOT
compiler has open bugs that can cause unexpected failures which
make the template strategy unusable in rare cases. These rare
exceptions need to be handled gracefully in order to avoid confusion
and to provide a more smooth migration.

Additionally migration strategy setup failures are now reported with
stack traces as the `ng update` command does not print stack traces.
This makes it easier to reproduce and report migration issues.

PR Close #30269
2019-05-08 11:54:33 -07:00
Paul Gschwendtner 349935a434 fix(core): migrations not always migrating all files (#30269)
In an Angular CLI project scenario where projects only reference
top-level source-files through the `tsconfig` `files` option, we currently
do not migrate referenced source-files. This can be fixed checking all
referenced source-files which aren't coming from an external library.

This is similar to how `tslint` determines project source-files.

PR Close #30269
2019-05-08 11:54:33 -07:00
Paul Gschwendtner 6357d4a0d3 fix(core): static-query migration fails with default parameter values (#30269)
Currently when someone has a call expression within the `ngOnInit` call
and we try to peek into that function with respect to the current function
context, the schematic errors because a call expression argument is
undefined. This is valid because the target function declaration defines
that parameter with a default value. In order to fix this, we need to
respect parameter default values.

PR Close #30269
2019-05-08 11:54:33 -07:00
Paul Gschwendtner f094bb54a7 test(core): run schematic tests with public migration collection (#30198)
572b54967c changed how the schematic
tests are executed. Tests no longer use the schematic collection
that is also used by the CLI `ng update` command and therefore
the migration collection could  technically be invalid.

In order to ensure that the public migration collection is guaranteed
to work and to avoid duplication within two schematic collections, the
changes are partially reverted and only the disabled `injectable-pipe`
schematic has its own collection.

PR Close #30198
2019-05-08 09:23:28 -07:00