Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Several improvements to typings #8884

Merged
merged 14 commits into from
May 30, 2020

Conversation

thw0rted
Copy link
Contributor

@thw0rted thw0rted commented May 29, 2020

Note up front, I had to change the command in the gulpfile from a relative path to npx. I think this is more or less universally supported now across platforms but I haven't researched it fully.

  • The biggest change (by volume, certainly) is moving a lot of options-argument definitions out into named interfaces with @typedef. Most of these are called ClassName.ConstructorOptions, with a couple of .LoadOptions for DataSources that have common options for a load method.

  • One or two commits are dedicated to converting Event to take a generic parameter specifying the callback signature. This lets you type events as e.g. Event<Function(int, bool)>, which means that in viewer.fooEvent.addEventListener((num, flag) => { .... }), the arguments are typed correctly. I only added types for the few events that I personally use but I could pretty easily fix the rest of them if you like this approach.

    • I couldn't get @template to work very well so I wound up adding a hack to the gulpfile. I'm going to try to find a few minutes today to put together a tiny repro and open an issue with tsd-jsdoc to see if I am missing something. It's also possible that there just isn't any support for generic parameter defaults (Event<Listener extends Function = Function>), which is super important in this case, which would probably mean keeping the hack in place anyway.
  • The Resource class got a couple @typedefs that more precisely define what kind of object can be used as a queryParameter.

  • A couple of the changes are just for correctness -- arguments or properties that are allowed to be undefined or false, etc.

  • Unanswered questions are marked with *** TODO ***: a couple of properties whose shapes aren't fully documented on Entity, and one option for PolylineGraphics that can probably be a Property but I wanted to double check before making the change.

    • Document shape of two properties on Entity
    • Validate that PolylineGraphics#ArcType can be a Property

PS: I just noticed that I accidentally committed deleting .vscode/tasks.json, but the good news is that actually everybody should do that, because the tasks that were previously in there should now be picked up automatically via NPM integration, unless for some reason you're stuck on a year-plus-old build of VSCode.

@cesium-concierge
Copy link

Thank you so much for the pull request @thw0rted! I noticed this is your first pull request and I wanted to say welcome to the Cesium community!

The Pull Request Guidelines is a handy reference for making sure your PR gets accepted quickly, so make sure to skim that.

  • ❌ Missing CONTRIBUTORS.md entry.
  • ❌ Missing CLA.
  • ❔ Unit tests were not updated.
    • Make sure you've updated tests to reflect your changes, added tests for any new code, and ran the code coverage tool.

Reviewers, don't forget to make sure that:

  • Cesium Viewer works.
  • Works in 2D/CV.
  • Works (or fails gracefully) in IE11.

@thw0rted
Copy link
Contributor Author

I thought I'd done the CLA before but I probably forgot. (There was a whole thing about 2 years ago about having my company sign since I'm doing the work on the clock, but I finally got cleared by Legal to just sign the individual one instead.) It's done now.

@thw0rted
Copy link
Contributor Author

This new commit converts exportKml to an overloaded function that returns the correct type based on the value of options.kmz. It does result in two different entries in globals.html in the docs, but I made sure the description was attached to the first entry and both have their own @example.

@mramato
Copy link
Contributor

mramato commented May 29, 2020

Yeah, I definitely thought you were a contributor already as well, either way thanks for the PR. I'm going to review now and would love to get this into Monday's release so that TS starts with it's best foot forward.

@mramato
Copy link
Contributor

mramato commented May 29, 2020

Note up front, I had to change the command in the gulpfile from a relative path to npx.

Why? I'm not a fan of npx as a concept but if there's a good technical reason for using it here instead of just calling the script directly, I'm willing to entertain the idea. Unless something has changed in node, bin scripts are guaranteed to be in the location we were using them.

@OmarShehata
Copy link
Contributor

Can confirm we've received your individual CLA @thw0rted .

@mramato
Copy link
Contributor

mramato commented May 29, 2020

I just noticed that I accidentally committed deleting .vscode/tasks.json, but the good news is that actually everybody should do that, because the tasks that were previously in there should now be picked up automatically via NPM integration, unless for some reason you're stuck on a year-plus-old build of VSCode.

Sounds good to me, I verified that the npm scripts in VS Code picks everything up.

@thw0rted
Copy link
Contributor Author

re: npx, maybe it's something I did wrong with Gulp? When I ran it, it would error that it couldn't find node_modules/.bin/tsc or whatever, and my initial assumption that it was some kind of platform-specific thing with backslash vs frontslash, etc. -- I run git-bash as my shell in this environment, not sure what yours is.

I made the change because npx works for both of us, and seemed to express intent better to me. I'm really not partial, though.

@mramato
Copy link
Contributor

mramato commented May 29, 2020

Thanks, just to debug further, were you running npm run build-ts? or were you using a global installed version of gulp cli and doing gulp build-ts? What OS are you on?

@thw0rted
Copy link
Contributor Author

thw0rted commented May 29, 2020

npm run build-ts, no global gulp, Windows 10 but in git-bash, as I said. I just tested and it looks like execSync(".\\node_modules\\.bin\\jsdoc") works directly from the node REPL, so that strongly suggests a platform separator issue. Which means either you can use path.resolve or just stick with npx.

ETA: honest question, I don't know if npx ships with all modern Node distros like npm or if I installed it myself at some point. I thought the former, but if you told me it's the latter I wouldn't be that surprised. If you know one way or another, great, but if not I guess at least everybody can use path.resolve without incident.

@mramato
Copy link
Contributor

mramato commented May 29, 2020

@thw0rted I believe npx ships with node/npm these days. I'll confirm of course. I was asking mainly so I could reproduce on my end. Also, we have other parts of gulpfile where we do the same thing so ultimately we should make them consistent. Assuming npx is always available, I'm not going to bikeshed it any further and will just look into it as a followup PR. Thanks.

* Initialization options for the Resource constructor
*
* @property {String} url The url of the resource.
* @property {Resource.QueryParameters} [queryParameters] An object containing query parameters that will be sent when retrieving the resource.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QueryParameters is not showing up properly in the doc, hopefully an easy fix.

image

Copy link
Contributor Author

@thw0rted thw0rted May 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great point. Since this is a type alias, basically for Object<string, string|num|bool|(string|num|bool)[]|undefined>, there's really nothing to print in the template. I should have put some text description in there, at least.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went ahead and added a one-liner so it's not blank, at least. If you want to flesh it out feel free.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's going to be really confusing for non TS users reading the doc to understand what they are supposed to pass here. What is the fundamental issue you are trying to prevent here, people passing an object that has more than just primitive values? Technically users can pass anything that has a toString function, right? So wouldn't Object still be the best option here no matter what?

@@ -46,7 +47,7 @@ Object.defineProperties(Event.prototype, {
* An optional scope can be provided to serve as the <code>this</code> pointer
* in which the function will execute.
*
* @param {Function} listener The function to be executed when the event is raised.
* @param {Listener} listener The function to be executed when the event is raised.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ends up creating a non-existent Listener entry in the doc:

image

I started to dig into template/generics a little on the JSDoc and I agree they don't appear to work at first glance. I'll see what I can find. I want to be careful about trying to do too much too fast since we want to use generics in more places (like Property) but I don't want to get too crazy with workaround either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally forgot to link you to englercj/tsd-jsdoc#134 -- it looks like @template is flat-out broken, but also there isn't consensus about how to provide a default value for a type parameter. Sadly that probably means the ugly hack in the gulpfile will be required for the foreseeable future if you're going to use generics.

@@ -429,7 +427,6 @@ CesiumMath.DEGREES_PER_RADIAN = 180.0 / Math.PI;
*
* @type {Number}
* @constant
* @default {@link CesiumMath.RADIANS_PER_DEGREE} / 3600.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with these changes, but it made me realize there's a bug with Math/CesiumMath in my PR, so thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not positive this would work even without the Math error, because I can't find anything saying that an expression (not a literal) for @default is supposed to be supported.

*/
errorEvent: {
get: DeveloperError.throwInstantiationError,
},
/**
* Gets an event that will be raised when the value of isLoading changes.
* @memberof DataSource.prototype
* @type {Event}
* @type {Event<function(this, boolean)>}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was worried about how JSDoc would handle this, but I think this is okay, assuming we can get Event as a template working a little better.:

image

However, I'm pretty sure this breaks duct typing because CustomDataSource/CzmlDataSource/KmlDataSource/GeoJsonDataSource don't have the same signatures.

I'm not sure if the best course of action is to update the signatures, or pull out the Event related changes in a separate PR for more discussion. I'll finish up the rest of the review and think about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I have lines like

let src: DataSource;
...
src = new KmlDataSource(...)

in my code and it didn't break when compiling against this branch's typings. I can see where you'd be concerned, though, so I understand if you want to hold off. (If there's no rush, I could always fix all uses of Event on Monday, it's not actually that many.)

* @property {Boolean} [show] A boolean value indicating if the entity and its children are displayed.
* @property {Property | string} [description] A string Property specifying an HTML description for this entity.
* @property {PositionProperty | CallbackProperty | Cartesian3} [position] A Property specifying the entity position.
* **** TODO ****
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are these TODOs for? Also, CallbackProperty is officially supported here. The object needs to conform to the PositionProperty signature to work in all cases. Please write up a separate issue so that we can either add a CallbackPositionProperty or something similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, it's asking about the type of orientation and viewFrom. Are they Matrix4? Cartesian3? The docs aren't much help, as they just use the term to define itself ("Gets or sets the orientation" -- gee, thanks :D )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re CallbackProperty, was that isn't officially supported? I've been using it for a while but if that's wrong, we can remove it from the typing here and I'll just any-cast and cross my fingers until official support gets added.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

viewFrom is a Cartesian3. Orientation is a Quaternion

There are places where we call PositionProperty.getValueInReferenceFrame, such as path visualization and exportKml. So CallbackProperty is technically incorrect for now. Turns out we have an issue for this already: #5534 so let's revert for now and maybe we can fix for 1.71.

@@ -963,7 +963,8 @@ EntityCluster.prototype.destroy = function () {
* @callback EntityCluster.newClusterCallback
*
* @param {Entity[]} clusteredEntities An array of the entities contained in the cluster.
* @param {Object} cluster An object containing billboard, label, and point properties. The values are the same as
* @param {{billboard: Billboard, label: Label, point: PointPrimitive}} cluster An object
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the intent here but this just ends up being an any in the type definition either way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally didn't notice that. Was I right about the actual shape of the object? I can fix it to use the correct @param syntax, I'm just spoiled by the shorthand TS lets you use.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the shape is correct.

* @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to draw the polyline.
* @property {MaterialProperty | Color} [depthFailMaterial] A property specifying the material used to draw the polyline when it is below the terrain.
*
* **** TODO **** this was originally only ArcType, not a Property (!) -- pretty sure that was wrong?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, it's definitely a Property in the code, so you can remove this todo and keep your change. Thanks!

*
* @param {Object} [value] An object, containing key-value mapping of property names to properties.
* @param {Function} [createPropertyCallback] A function that will be called when the value of any of the properties in value are not a Property.
* @typedef {PropertyBagType}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks JSDoc HTML output completely.

@@ -221,6 +221,33 @@ IdManager.prototype.get = function (id) {

return id.toString() + "-" + ++ids[id];
};
/**
* @variation 2 KML return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes in this file break exportKml JSDoc output completely.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well this is weird. The version I'm looking at right now is not what I committed. I saw that there's some kind of commit hook to run a prettifier -- could that be the culprit? It's important to have

/**
 * Body of documentation
 *
 * @variation 1
 * @param ...
 * @example (for variation 1)
 *//**
 * @variation 2
 * @param ...
 * @example (for variation 2)
 */

Exactly thus, with no spaces between the closing tag for the first block and the opening tag for the second. That's part of the JSDoc spec, apparently, though ironically documentation about the spec is a bit dodgy in my experience. Is it possible to exempt a section or a whole file from being "massaged" by the prettifier?

Copy link
Contributor Author

@thw0rted thw0rted May 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the blocks aligned correctly, you get this:

image

Each overload gets its own entry in globals.html but I only put a body in one of them, so it seems pretty clear IMHO. If you'd rather keep one body then we're probably stuck with the union return.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would rather stick with the union return for now. This type of decision may affect the API elsewhere and our main goal is keeping the API consistent. I would just revert the file for now. Feel free to open a separate PR for further discussion.

@@ -128,8 +128,8 @@ function configureCameraFrustum(widget) {
* @param {Clock} [options.clock=new Clock()] The clock to use to control current time.
* @param {ImageryProvider} [options.imageryProvider=createWorldImagery()] The imagery provider to serve as the base layer. If set to <code>false</code>, no imagery provider will be added.
* @param {TerrainProvider} [options.terrainProvider=new EllipsoidTerrainProvider] The terrain provider.
* @param {SkyBox} [options.skyBox] The skybox used to render the stars. When <code>undefined</code>, the default stars are used. If set to <code>false</code>, no skyBox, Sun, or Moon will be added.
* @param {SkyAtmosphere} [options.skyAtmosphere] Blue sky, and the glow around the Earth's limb. Set to <code>false</code> to turn it off.
* @param {SkyBox| false} [options.skyBox] The skybox used to render the stars. When <code>undefined</code>, the default stars are used. If set to <code>false</code>, no skyBox, Sun, or Moon will be added.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're changing this here, we should change it for the other params in this signature as well, such as ImageryProvider

@mramato
Copy link
Contributor

mramato commented May 29, 2020

@thw0rted thanks again for the PR! The Entity and GraphicsXXX changes are all fine with me.

The ImageryProvider changes are okay as well, but we really should do them all for consistency. Some are still using the "old" documentation strategy, such as TileMapServiceImageryProvider, IonImageryProvider, etc.. It's easy to check them all by going down the @see list in ImageryProvider.js. If you are up for this, great. Otherwise I can take care of it after we merge this since they are mostly compatible.

The main thing stopping me from merging this is the broken JSDoc and Event and PropertyBag changes. I would recommend backing them out and opening a separate PR. I don't care about cleaning up the commit history, so this should be trivial to do. We may still be able to get them in 1.70, I just want to get as much as we can into the primary PR ASAP.

Since we want to get this into 1.70, I'm also okay with taking this PR over if you are unable to work on it until Monday. Just let me know.

Thanks again, now you'll go down in history as the first community member to contribute to our official TS definitions!

@thw0rted
Copy link
Contributor Author

Please go ahead and back out the things you're not comfortable with. It's quittin' time here in Europe for today, and while I might put in a few hours over the weekend, I don't want to commit to it ahead of time or hold up your release.

@mramato
Copy link
Contributor

mramato commented May 29, 2020

Thanks @thw0rted. I'm not sure why I thought you were in the states, enjoy your weekend.

mramato added a commit that referenced this pull request May 29, 2020
@mramato
Copy link
Contributor

mramato commented May 30, 2020

Thanks @thw0rted!

I submitted some clean-up and backed out some changes that we need to think about more, but I parked them on a branch, thw0rted-bonus, and definitely plan on revisiting them ASAP.

@mramato mramato merged commit adc772c into CesiumGS:typescript-definitions May 30, 2020
thw0rted pushed a commit to thw0rted/cesium that referenced this pull request Jun 1, 2020
thw0rted pushed a commit to thw0rted/cesium that referenced this pull request Jun 2, 2020
thw0rted pushed a commit to thw0rted/cesium that referenced this pull request Jun 3, 2020
thw0rted pushed a commit to thw0rted/cesium that referenced this pull request Jun 5, 2020
thw0rted pushed a commit to thw0rted/cesium that referenced this pull request Sep 21, 2020
thw0rted pushed a commit to thw0rted/cesium that referenced this pull request Nov 6, 2020
thw0rted pushed a commit to thw0rted/cesium that referenced this pull request Nov 6, 2020
thw0rted pushed a commit to thw0rted/cesium that referenced this pull request Jul 20, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants