Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Expose code inspection providers for the extensions. #5125

Merged
merged 1 commit into from
Sep 27, 2013
Merged

Expose code inspection providers for the extensions. #5125

merged 1 commit into from
Sep 27, 2013

Conversation

zaggino
Copy link
Contributor

@zaggino zaggino commented Sep 8, 2013

As mentioned in #4588 (comment)

API that fetches the active linting provider for a given file entry.

@zaggino
Copy link
Contributor Author

zaggino commented Sep 8, 2013

@peterflynn can you review? i choose rather not to modify the original run function

@ghost ghost assigned peterflynn Sep 9, 2013
@zaggino
Copy link
Contributor Author

zaggino commented Sep 13, 2013

@peterflynn could we do this for sprint 31 please? :)

var language = LanguageManager.getLanguageForPath(fileEntry.fullPath),
languageId = language && language.getId(),
provider = language && _providers[languageId];
return provider;
Copy link
Member

Choose a reason for hiding this comment

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

This duplicates code from run(), so I think you should modify run() to use this. I don't think it will be too disruptive to hoist out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

true, but you used language and languageId later, so you mean like return all three variables in object ?

@peterflynn
Copy link
Member

What would you think of changing the API to something like: inspectFile(fullPath), returning the provider result? This way the provider running code could evolve without clients of this API needing to replicate all those changes. This would also let CodeInspection take care of loading the file from disk (or reusing a Document if open already) instead of each client of the API having to do that.

One thing I have in mind is the possibility of providers becoming async (#5137). An inspectFile() type API would be async right out of the box, so clients wouldn't break if async providers come along later.

@peterflynn
Copy link
Member

@zaggino Done reviewing. Just those two thoughts.

@zaggino
Copy link
Contributor Author

zaggino commented Sep 13, 2013

@peterflynn Take a look please what do you think. Haven't modified any of the original code yet but this inspectFile() implementation would work for me quite nicely.

.done(function (fileText) {
var perfTimerInspector = PerfUtils.markStart("CodeInspection '" + languageId + "':\t" + fileEntry.fullPath),
scanPromise = $.when(provider.scanFile(fileText, fileEntry.fullPath));
Async.withTimeout(scanPromise, SCAN_TIMEOUT)
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need to wrap this in a timeout -- we generally don't try to protect against bad/slow async extension code anywhere else

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I'll remove it then. Will finish this tomorrow, almost 3am already in Syd :)

@peterflynn
Copy link
Member

@zaggino This is looking like a good direction, yeah.

@zaggino
Copy link
Contributor Author

zaggino commented Sep 14, 2013

Done, with a bit of optimization. Original code was multiplying event handlers on the results table with every render. That should be solved now. Please review @peterflynn

@peterflynn
Copy link
Member

@zaggino I haven't been able to give the latest changes a close look yet -- hopefully tomorrow.

But from my quick glance, I'm a little concerned about possible race conditions in run(), e.g. if you switch files before the provider has returned results. Since we're getting close to the end of the sprint and thus a bit more risk-averse, I wonder if the best thing for now would be to take out the support for async providers. That makes it easier to land the API you need before the sprint ends -- and we could introduce async providers next sprint without breaking API compatibility. What do you think?

@zaggino
Copy link
Contributor Author

zaggino commented Sep 16, 2013

@peterflynn it's not very difficult to check if the checked document is still the current document when the async provider finishes it's work... but I can disable it in this one to be safe and put up another PR with async

@zaggino
Copy link
Contributor Author

zaggino commented Sep 16, 2013

and right now - unless someone installs an extension with async provider, it won't be used anyway...

@peterflynn
Copy link
Member

@zaggino There are other cases too, though -- you might modify & save the file a second time while the first linting is still running, or toggle the panel visibility, or disable linting... We probably shouldn't offer API support until we're sure it will work reliably.

@zaggino
Copy link
Contributor Author

zaggino commented Sep 17, 2013

ok @peterflynn , i'll remove the async parts to keep this simple for now

@zaggino
Copy link
Contributor Author

zaggino commented Sep 17, 2013

Done, inspectFile is still async for cases when the fileEntry is not found in the DocumentManager.getOpenDocumentForPath. Do you think that this is also a problem?

@zaggino
Copy link
Contributor Author

zaggino commented Sep 23, 2013

@peterflynn Can we merge now? I see Sprint 32 in the master.


/**
* Gets a provider for given fileEntry, if one is available
*/
Copy link
Member

Choose a reason for hiding this comment

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

Needs type annotations for argument & return values. Ditto for inspectFile() below -- every public API (at minimum) should have these docs.

Copy link
Member

Choose a reason for hiding this comment

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

Also, nit: the double spacing after the * is inconsistent with how the rest of the file is formatted.

@peterflynn
Copy link
Member

@zaggino Looking good -- just a few minor comments.

@peterflynn
Copy link
Member

Actually two other thoughts:

  • Should we pass in FileEntry objects, or just string fullPaths? Although I sorta like the semi-type-safetiness of using FileEntry, I think most of our APIs right now just take paths. @gruehle any opinion on which is more future-proof? ;-)
  • getProvider() should be suffixed, e.g. getProviderForPath() or ...ForFile() depending on which we choose above.

@zaggino
Copy link
Contributor Author

zaggino commented Sep 25, 2013

Fixed the comments. About the FileEntry vs FullPath thing, currently in my extension I have this piece of code to call the method, so fullPath would be easier in my situation but might not be better for others. return CodeInspection.inspectFile(new NativeFileSystem.FileEntry(Main.getProjectRoot() + filename));

@peterflynn
Copy link
Member

Oops, actually one more thing, now that I've been running on this branch: the built-in JSLint provider returns null anytime there are no errors, so the console winds up littered with warnings. I wonder if we should actually get rid of the warning and just continue to allow null as a return value? Now that run() uses getProvider() as a helper, we don't really need non-null results to help disambiguate no-provider vs. no-errors...

@zaggino
Copy link
Contributor Author

zaggino commented Sep 25, 2013

Ok, I've removed the warning.

@peterflynn
Copy link
Member

Great! I'll wait until tomorrow morning to see if @gruehle has any thoughts on the FileEntry vs. fullPath question, but personally I'm leaning toward the path. It's easy to call that form whether you have a FileEntry wrapper or not, which is nice. (And then we should rename the API accordingly).

Also had one other suggestion, if we're going to make one more commit anyway: I think the docs for inspectFile() should mention that it will reflect any unsaved changes present in the file, if it's currently open. Might also be worth clarifying that it just computes the results headlessly & doesn't update the UI -- or at least changing the phrasing to avoid using the word "Runs" which could be confused with the runs() function.

@zaggino
Copy link
Contributor Author

zaggino commented Sep 25, 2013

Ok, will fix that comments ... also I can squash these commits into one before merging, so the history of the main repo is not polluted unnecessarily with too many commits.

@gruehle
Copy link
Member

gruehle commented Sep 25, 2013

Yeah, I prefer using a pathname for getProvider(), but sticking with a FileEntry for inspectFile().

I had another thought: why not store the code inspection provider on the language object? This way you can just use getLanguageForPath().inspectionProvider. We already store the providers by the language ID anyway...

@zaggino
Copy link
Contributor Author

zaggino commented Sep 25, 2013

Did the getProvider() change, can also do the language object thing if desired.

One more thought, currently there is only one possible file inspector for one language but in the future, there might be desired feature to support multiple code inspectors who check for different things. Like I can use jshint on my JavaScript files but I also want an extension that checks for patterns that are forbidden in a specific framework like dojo or yui.

@peterflynn
Copy link
Member

@zaggino Very good point. So, what's the use case for getProvider() at this point? The motivation for inspectFile() originally was to help insulate callers from dealing with the provider directly, so ideally if we've done out job getProvider() is unneeded. If we offered a simpler hasProvider() API instead (in combination with inspectFile()), would that be good enough?

@peterflynn
Copy link
Member

@gruehle We have other things that are language-specific too, like code hint providers, Quick Open providers, etc. and we don't hang those directly off the Language object. We could stuff them all into the Language, but it starts to feel a little iicky to me in a separation-of-concerns sense... feels nicer to have each of those subsystems own its own data.

@zaggino
Copy link
Contributor Author

zaggino commented Sep 26, 2013

I've removed getProvider from exports as I too don't see much use for it. Currently from outside you can call inspectFile with any provider you want or leave Brackets to use the default provider which seems fine to me.

Currently if there's no default provider for the given file type, inspectFile returns null. I'm not sure we need to publish hasProvider because this doesn't say much to anyone since from true / false one can't really know, what the provider does.

@gruehle
Copy link
Member

gruehle commented Sep 26, 2013

@peterflynn Good point about the other language-specific features. I agree that it doesn't make sense to clutter up Language like that.

Making getProvider() private is an even better way the solve the problem 😄

@peterflynn
Copy link
Member

@zaggino Looks good to go! Did you still want to make a squashed version?

First go at inspectFile method.

Removed Async.withTimeout from inspectFile()

Separated getProvider and inspectFile logic, added usage of DocumentManager.getOpenDocumentForPath to inspectFile

Modified run() to use new methods.

Moved $problemsPanelTable event handlers from run() to htmlReady() for optimization.

Fix the case when getCurrentDocument returns null.

Check if current document hasn't changed while inspectFile was running

remove async handling of provider.scanFile

Refactored according to comments.

Made provider response nullable again, removed the warning.

Refactored getProvider to getProviderForPath and updated docs.

Remove getProvider from exports.
@zaggino
Copy link
Contributor Author

zaggino commented Sep 26, 2013

Yes, that'll be better. Squashed now.

@zaggino
Copy link
Contributor Author

zaggino commented Sep 27, 2013

@peterflynn ready to go, but this will certainly create merge problems with #5235

@peterflynn
Copy link
Member

Looks good -- thanks for being patient! #5235 is just starting review, so there's plenty of time to sort out the conflicts over there. I think this one is ready to land now.

peterflynn added a commit that referenced this pull request Sep 27, 2013
Expose API to run code inspection as a headless one-off on an arbitrary file
@peterflynn peterflynn merged commit c06e73d into adobe:master Sep 27, 2013
@zaggino zaggino deleted the codeInspectionApi branch September 29, 2013 02:35
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants