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

[Experimental] First attempt at replacing AST traversal with Maybe<T> #180

Merged
merged 5 commits into from
Dec 25, 2016

Conversation

ghsyeung
Copy link
Contributor

@ghsyeung ghsyeung commented Dec 7, 2016

Prototyping of Maybe monad in AST traversal

This is intended to further discuss whether/how Maybe monad would be a good fit in

  • writing internal AST traversal
  • jQuery style helpers for Rules development

src/angular/metadataReader.ts seems to be a good target to start. Most of the work goes into extracting AST traversal code into astQuery and ngQuery.

A few realizations so far

  • Maybe monad introduces a bit a learning curve, but the structure makes the intent easier to understand (e.g. decoratorArgument)
  • There are a few wrinkles getting the proper type returned, but type guard helps (e.g. callExpression)

@mgechev
Copy link
Owner

mgechev commented Dec 7, 2016

Looks hot, happy to see your suggestion in action! Will take a look at it in the next a couple of days and give you feedback. Thanks!

@ghsyeung
Copy link
Contributor Author

ghsyeung commented Dec 7, 2016

Had some more thoughts about refactor experience so far.

Can codelyzer develop against a different TS than the runtime TS? I have a feeling you can, but if not, it harder to write compatible type-friendly code as a lot of useful features like 'control flow based type analysis' and 'dot name type guards' landed only in TS 2.0

More refactoring can be done in src/angular/metadataReader.ts, but that likely require adding a 'seam' to urlResolver and fileResolver to make it Maybe friendly.

Also there may be a few minor bugs, I'll highlight them below.

}

export function isSimpleTemplateString(expr: ts.Expression): expr is (ts.StringLiteral | ts.NoSubstitutionTemplateLiteral) {
return expr && expr.kind === kinds.StringLiteral || expr.kind === kinds.NoSubstitutionTemplateLiteral;
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 believe https://github.com/mgechev/codelyzer/blob/master/src/util/utils.ts#L29 should use kinds.NoSubstitutionTemplateLiteral instead.

I was using astExplorer and find it odd that it maps to FirstTemplateToken as well.

return url;
};
const code = `
try {
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 think we need to wrap with try/finally or the spy would leak when a test fails.

const metadata = this.readDirectiveMetadata(d, dec);
const result = new ComponentMetadata();
result.selector = metadata.selector;
result.controller = metadata.controller;
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 notice that decorator is not copied to result. Is that intentional?

Copy link
Owner

Choose a reason for hiding this comment

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

Seems like an issue.

@ghsyeung
Copy link
Contributor Author

Added Walker builder (a builder approach and a functional approach) in attempt to make Rule definition easier.


read(d: ts.ClassDeclaration): DirectiveMetadata {
let componentMetadata = unwrapFirst(
(d.decorators || ([] as ts.Decorator[])).map((dec: ts.Decorator) => {
Copy link
Owner

Choose a reason for hiding this comment

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

Looks beautiful!

const inlineStyles_M = getInlineStyle(dec)
.fmap(inlineStyles => {
return inlineStyles.elements.map((inlineStyle: ts.Expression) => {
if (isSimpleTemplateString(inlineStyle)) {
Copy link
Owner

Choose a reason for hiding this comment

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

Maybe we can first apply filter and after that map it, so we can drop the ugly if condition?

}

export function all<T>(...preds: F1<T, boolean>[]): F1<T, boolean> {
return (t: T) => !preds.find(p => !p(t));
Copy link
Owner

Choose a reason for hiding this comment

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

Maybe some can do the trick since it returns boolean anyway.

return (t: T) => !preds.find(p => !p(t));
}
export function any<T>(...preds: F1<T, boolean>[]): F1<T, boolean> {
return (t: T) => !!preds.find(p => p(t));
Copy link
Owner

Choose a reason for hiding this comment

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

Maybe some can do the trick since it returns boolean anyway.

@mgechev
Copy link
Owner

mgechev commented Dec 19, 2016

I left some comments. In general I like the direction that you took! The build is failing:

src/componentClassSuffixRule.ts(15,31): error TS2304: Cannot find name 'suffix'.
src/componentClassSuffixRule.ts(25,32): error TS2334: 'this' cannot be referenced in a static property initializer.
src/componentClassSuffixRule.ts(25,37): error TS2339: Property 'getOptions' does not exist on type 'typeof Rule'.
src/componentClassSuffixRule.ts(25,63): error TS2334: 'this' cannot be referenced in a static property initializer.
src/componentClassSuffixRule.ts(25,68): error TS2339: Property 'getOptions' does not exist on type 'typeof Rule'.
src/componentClassSuffixRule.ts(26,61): error TS2346: Supplied parameters do not match any signature of call target.

@ghsyeung
Copy link
Contributor Author

Nothing new yet, just fixed the above error resulted from merging master.

@mgechev
Copy link
Owner

mgechev commented Dec 21, 2016

Awesome! I just published beta.4, we can introduce this new AST traversal mechanism in beta.5.

@mgechev mgechev merged commit fe42a37 into mgechev:master Dec 25, 2016
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.

2 participants