diff --git a/api_analysis/lib/r4/shape-format.md b/api_analysis/lib/r4/shape-format.md index 4d367723..e4445ce5 100644 --- a/api_analysis/lib/r4/shape-format.md +++ b/api_analysis/lib/r4/shape-format.md @@ -1,6 +1,6 @@ # Proposal for package shape format -Idea: +## Idea * Use lists of stuff, let the index in the list act as an ID number. Then we can just reference the ID number when we reference the thing. * Include: @@ -11,10 +11,224 @@ Idea: * Exclude: * Return types and argument types (maybe we add this later?) -Undecided: (added in draft 2) - * Imports - * "extends" and "mixin" - * "implements" +## Undecided +### Imports +See draft 1 -> draft 2. + +### `extends` and `mixin` +See draft 1 -> draft 2. + +### `implements` +See draft 1 -> draft 2. + +### Top-level member list +We could collect all the member shapes (defined across all libraries), and store them all together in one list. We could then refer to the members exported in a given library by their indexes in this list. + +This can also allow us to no longer store `.identifiers` of shapes defined and exported in the same package, but note that we still need to record identifiers of any exported external top-level members, since we cannot produce summaries of them. + +#### Example + +In this example, we encode the member index as a tuple, where the first element is 0 if the member being exported has been defined in this package, and 1 if it is an external member. + +Alternatively, we can use one integer as an index, rolling over the count from `.members` into `.externalIdentifiers` (for example, in this case, the index of "Bar" would be 1, because `.members` contains 1 element). + +
+Full example + +```js +{ + "verison": 1, + "package": "foo", + "version": "1.0.0", + // Shapes of top-level members defined in any library in this package. + "members": [ + // This is the 0th top-level member defined in this package. + { + "name": "Foo", + "kind": "class", + "members": [ + { + "name": "sayHello", + "kind": "method", + "params": [ + { + "name": ..., + "kind": "positional" | "named", + "required": true | false, + }, + ... + ], + }, + ... + ], + }, + ... + ], + // Identifiers of top-level members which are defined in a different package, + // but exported in this one. + "externalIdentifiers": [ + // This is the 0th external top-level member. + "Bar" + ], + "libraries": [ + // library 0: + { + "uri": "package:foo/foo.dart", + // Propogated exports, with this we can easily compute the set of exported + // members. + "exports": [ + { + "library": 1, // library 1 is "package:foo/src/bar.dart" + "show": [ + [1, 0], // the 0th external member is "Bar" + ], + }, + { + "library": 2, // library 2 is "package:bar/bar.dart" + "hide": [ + [0, 0], // the 0th member defined in this package is "Foo" + ], + } + ], + }, + // library 1: + { + "uri": "package:foo/src/bar.dart", + "exports": [ + { + "id": 0, // library 0 is "package:foo/foo.dart" + "hide": [ + [0, 0], // the 0th member defined in this package is "Foo" + ], + }, + ], + }, + // library 2: + { + // TODO: Is this a good way to do external libraries? + "uri": "package:bar/bar.dart", + // We know nothing about external libraries, so there no data here. + // We have an entry in "libraries" such that they have an identifier. + }, + ], +} +``` +
+ +
+Diff from draft 1 + +```diff + { + "verison": 1, + "package": "foo", + "version": "1.0.0", +- "identifiers": [ +- "Foo", // 0 +- "sayHello", // 1 +- "Bar", // 2 ++ // Shapes of top-level members defined in any library in this package. ++ "members": [ ++ // This is the 0th top-level member defined in this package. ++ { ++ "name": "Foo", ++ "kind": "class", ++ "members": [ ++ { ++ "name": "sayHello", ++ "kind": "method", ++ "params": [ ++ { ++ "name": ..., ++ "kind": "positional" | "named", ++ "required": true | false, ++ }, ++ ... ++ ], ++ }, ++ ... ++ ], ++ }, ++ ... ++ ], ++ // Identifiers of top-level members which are defined in a different package, ++ // but exported in this one. ++ "externalIdentifiers": [ ++ // This is the 0th external top-level member. ++ "Bar" + ], + "libraries": [ + // library 0: + { + "uri": "package:foo/foo.dart", + // Propogated exports, with this we can easily compute the set of exported + // members. + "exports": [ + { + "library": 1, // library 1 is "package:foo/src/bar.dart" +- "show": [ +- 2, // identifier 2 is "Bar" ++ "show": [ ++ [1, 0], // the 0th external member is "Bar" + ], + }, + { + "library": 2, // library 2 is "package:bar/bar.dart" + "hide": [ +- 0, // identifier 0 is "Foo" ++ [0, 0], // the 0th member defined in this package is "Foo" + ], + } + ], +- // Top-level things defined in the library +- // Not everything exported, this can be easily computed by using the +- // "exports" maps. +- "members": [ +- { +- "name": 0 // identifier 0 is "Foo" +- "kind": "class", +- "members": [ +- { +- "name": 1, // identifier 1 is "sayHello" +- "kind": "method", +- "params": [ +- { +- "name": ..., +- "kind": "positional" | "named", +- "required": true | false, +- }, +- ... +- ], +- }, +- ... +- ], +- }, +- ], + }, + // library 1: + { + "uri": "package:foo/src/bar.dart", + "exports": [ + { + "id": 0, // library 0 is "package:foo/foo.dart" + "hide": [ +- 0, // identifier 0 is "Foo" ++ [0, 0], // the 0th member defined in this package is "Foo" + ], + }, + ], + }, + // library 2: + { + // TODO: Is this a good way to do external libraries? + "uri": "package:bar/bar.dart", + // We know nothing about external libraries, so there no data here. + // We have an entry in "libraries" such that they have an identifier. + }, + ], + } +``` +
## Draft 1