Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
This repository was archived by the owner on Feb 26, 2023. It is now read-only.

Generate classes even after validation errors#1978

Merged
WonderCsabo merged 6 commits into
androidannotations:developandroidannotations/androidannotations:developfrom
smaugho:1976_generate_classes_even_after_validation_errorssmaugho/androidannotations:1976_generate_classes_even_after_validation_errorsCopy head branch name to clipboard
Nov 4, 2017
Merged

Generate classes even after validation errors#1978
WonderCsabo merged 6 commits into
androidannotations:developandroidannotations/androidannotations:developfrom
smaugho:1976_generate_classes_even_after_validation_errorssmaugho/androidannotations:1976_generate_classes_even_after_validation_errorsCopy head branch name to clipboard

Conversation

@smaugho

@smaugho smaugho commented Mar 14, 2017

Copy link
Copy Markdown
Contributor

This PR includes changes applies by the PR 1977, plus some improvements.

see #1976

@smaugho smaugho force-pushed the 1976_generate_classes_even_after_validation_errors branch 3 times, most recently from 7f5eab9 to ce4702a Compare March 15, 2017 00:58
@smaugho

smaugho commented Mar 15, 2017

Copy link
Copy Markdown
Contributor Author

Hi, it seems the reason for the build fail it is that there's some Tests that requires that the process failed. Right now as explained in #1978 the process is failing in the last round... it seems this is not being detected...

I've run several tests in projects and it seams to be working fine.

Could you anyway please check why they are failing exactly?.. maybe it is something else.

Thanks

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

Thank you for testing and enhancing my PR. I'll try to test this on my project and check whats wrong with the tests as soon as possible. But currently I have a lot of projects for my job and in my free time. I hope I can get into it this weekend! :)

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

I just closed my version of this PR as we should not have two PR for the same issue. Please ensure that you have checked the Allow edits from maintainers. checkbox on the bottom of the right menu in this PR. so we can directly contribute to your PR to fix it.

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

Yes, the option is checked.. Didn't know it existed, sorry maybe I was able to work in your PR.

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

I think this option is fairly new. but you would not have been able to work in my PR as it requires write access to the androidannoations repo to get permission to write on PR branches when this option is checked.

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

It looks like the problems with the test are related to the Messager used in our MessagerAppender.

When its printMessage is called during processing it internally has a JavaFileObject as source that is used to set the required source field in the Diagnostic that is checked in ProcessorTestHelper to check if the error is present in the correct source file.

I'll see if i can find a way to keep this source state for the deffered adding of the erros that you implemented. But I'm afraid that this might limit our compiler support as the implementation of the Messager interface is part of the compiler used (in my test case it is com.sun.tools.javac.processing.JavacMessager of the javac compiler).

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

Ok, I guess sacrificing the tests is not an option neither... I simply didn't find a way to keep the compiler working at least that the report was done in that last round... not sure if making it in the prev-last round would make difference, but that would be hard to detect from within the framework.

I'm not sure of this, but isn't there a way to send information to the test from within the annotation processor?... of course that would require to change those tests...

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

The problem is that we not only break the tests with this behaviour but also e.g. eclipse would no longer be able to show the error on the annotation as it currently is as it is missing the information about the source file that has the error.

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

Making it like this for Android Studio only would work? The real problem that we are solving with this PR is exactly there.

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

Well, as soon as IntelliJ / Android Studio starts to show errors on the source/annotation it would not be able to do this for AndroidAnnotations as the required information here is missing. :(

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

Well, I guess if it is applied to Android Studio, it would be to IntellyJ in general.. not sure how to detect that exactly, but well, between eclipse and IntellyJ the biggest difference is the folder structure..

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

Mmm.. well, in that moment, this fixed is not needed anymore... right now IMHO, this is something serious, to be no able to detect the bugs, or have to make that process of watching the console, or going to the log file (I have it opened all the time in NotePad++ for instance) it is really annoying for programming... I really wouldn't like to omit this fix.. of course, maybe there's some other way to make it work..

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

Maybe not completely good idea, and it sounds more like a "patch" to this issue... but well, it can be created a Flag to pass as parameter to the framework which activates this behavior..

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

It is even an issue in CLI builds as the javac does not know the files where the error is added.

See this screenshot as an example. the blue line should be part of the MainActivity.java block. building on CLI looks the same.
image

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

Mmm.. well, in that moment, this fixed is not needed anymore...

well it would still be required as on bigger projects not generating source might again turn the whole project red and makes the source of the issue hard to find.

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

Yes that's right.. but this was something that I didn't understand, but now that you mention it, maybe there's a simple solution to it.. in the code, what was done, it is that the error is reported, by a mechanism in which I don't see the Element..

This is the original code (which I didn't modify):

for (Element annotatedElement : annotatedElements) {
	ElementValidation elementValidation = annotationHandler.validate(annotatedElement);

	AnnotationMirror annotationMirror = elementValidation.getAnnotationMirror();
	for (ElementValidation.Error error : elementValidation.getErrors()) {
		LOGGER.error(error.getMessage(), error.getElement(), annotationMirror);
	}

	for (String warning : elementValidation.getWarnings()) {
		LOGGER.warn(warning, elementValidation.getElement(), elementValidation.getAnnotationMirror());
	}

	if (elementValidation.isValid()) {
		validatedAnnotatedElements.add(annotatedElement);
	} else {
		LOGGER.warn("Element {} invalidated by {}", annotatedElement, annotationName);
	}
}

Maybe it would be enough if we instead of reporting all the errors separated and the warning separated, we could create a single String and reported in the last step with the major Level (so if there's Info and Warns, a Warn would be reported, if there's Error, then this is what would be reported).

I will try this I will let you know what happens then.

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

Mmm.. no, I see they are almost the same... the main difference is that the last one uses de annotated alement and a Warn, which is reported correctly...

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

Ok, I got it completely now.. there's no easy work around.. since the JavaFileObject exists only in that round, probably you cannot reference it in a different round...

But in general JavaFileObjects can be created and passed to other methods.. not sure if that could be a possible solution, I would have to see more of your research about it...

Well, a different approach it is to report all as a Warning and fail in the last round (this will solve what you point of the place the Error is being generate)..

But of course, it still doesn't solve what the Tests do....

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

Please note that I simply passed a reference to the Element and Annotation Mirror obtained in the first round, to the last one.... I'm just thinking if trying to create an an element in the last round pointing to the same place would make any difference...

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

I do not think that creating a Element or something is a solution as we are in java compiler (java/ecj/whatever) internal api where the relevant stuff happens... :(

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

I would have to see more of your research about it...

well there is not much to know. I found that the Messager is com.sun.tools.javac.processing.JavacMessager and it sets the related source in lines 98-105. and this source is required by ides and the test to know the file related to the warning/error.

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

unfortunately i haven't found a solution for this problem yet. :(

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

I got here some good result with something, I will let you know if I can get more improvements ;)

screenshot_1

@dodgex

dodgex commented Mar 16, 2017

Copy link
Copy Markdown
Member

What have you done to reach this? maybe I'll can try too

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

I'm still testing this... what I did was to get the elements from the TypeElement:

I use getElement to send the message

        private class Message {
		Kind kind;
		String message;
		AnnotationMirror annotationMirror;
		
		List <String> elements = new LinkedList<>();

		Message(Kind kind, String message, Element element,
				AnnotationMirror annotationMirror) {
			super();
			this.kind = kind;
			this.message = message;
			this.annotationMirror = annotationMirror;
			
			Element enclosingElement = element;
			do { 
				elements.add(0, enclosingElement.toString());
				enclosingElement = enclosingElement.getEnclosingElement();
			} while (!enclosingElement.getKind().equals(ElementKind.PACKAGE));
			
			System.out.println("ELEMENTS: " + elements);
		}

		public Element getElement() {
			Element element = processingEnv.getElementUtils().getTypeElement(elements.get(0));
			elements.remove(0);
			
			while (elements.size() > 0) {
				for (Element elem : element.getEnclosedElements()) {
					if (elem.toString().equals(elements.get(0))) {
						System.out.println("FOUND: " + elem);
						elements.remove(0);
						element = elem; 
						break;
					}
				}
			}
			
			return element;
		}

	}

@smaugho

smaugho commented Mar 16, 2017

Copy link
Copy Markdown
Contributor Author

The test is getting stuck.. I'm checking this:

ss 2017-03-16 at 09 21 19

To be honest I'm not sure why is needed the AnnotationMirror... well, I will try to generate it also from the element

@WonderCsabo

WonderCsabo commented Nov 1, 2017

Copy link
Copy Markdown
Member

I think we could tackle this quite easily. Where we are depending on generated code, we should introduce a new check, if the generating element is valid.
I think we can do this, because generating handlers are always running before the decorating handlers. So in the decorating handlers, we could check if the referenced element has any errors, and if yes, we signal an error on the decorated element as well.

I think we have to do this for @App, @Bean, @RestService and @Pref.

@smaugho

smaugho commented Nov 1, 2017

Copy link
Copy Markdown
Contributor Author

It is good idea, but I'm not sure to be honest if this will solve the initial problem better... I mean, if you make this validation this means that the activity will be not generated due to its dependency (a Bean) will not be generated. You could be using that Activity (or Fragment, or Service, or... ) from many other places, which will generate as well a chain of errors (this is what this PR was trying to reduce, the huge amount of errors generated while compiling)...

I'm not saying it is incorrect, just that it would be nice to weight what is more important here... once again, the PR was to reduce the amount of errors and let the programmer to focus in a few of them...

@WonderCsabo

Copy link
Copy Markdown
Member

@smaugho the Activity itself will be generated. The code which injects the bean into the activity will not be generated in it.

@WonderCsabo

WonderCsabo commented Nov 1, 2017

Copy link
Copy Markdown
Member

@smaugho again, if we introduce these checks, we do not leak error to the user, because the Activity will be generated. Only we do not generate the bean injection code inside. So there will be no MyActivity_ not found error.

@smaugho

smaugho commented Nov 1, 2017

Copy link
Copy Markdown
Contributor Author

yeap yeap, got it :).. sounds nice, just didn't see the first message... so basically the @bean will do nothing if the generating handler for the @ebean failed...

@WonderCsabo

Copy link
Copy Markdown
Member

Yep. I am wondering if there are other cases where on annotation is depending on the other?

@smaugho

smaugho commented Nov 1, 2017

Copy link
Copy Markdown
Contributor Author

From AA, I don't remember another...

@WonderCsabo are you implementing this already?

It would be good to invalidate @bean when the "linked" @ebean validation failed... but I don't find a way to know this at priori just in the validation phase... at least that you pass the "validatedAnnotatedElements" as parameter to the validations in the Annotation Handler...

Any better idea?

@WonderCsabo

Copy link
Copy Markdown
Member

I am experimenting with this, yeah.

@smaugho

smaugho commented Nov 1, 2017

Copy link
Copy Markdown
Contributor Author

Ok, I guess you have it cracked :)... probably enough getting the validated elements from the AndroidAnnotationEnvironment..

@WonderCsabo

Copy link
Copy Markdown
Member

@smaugho i think i managed to do it. Here is my branch. Can you reset your branch to mine?

Also @dodgex @smaugho please review my changes.

@dodgex

dodgex commented Nov 2, 2017

Copy link
Copy Markdown
Member

@WonderCsabo you should have write access to the branch of this PR.

@dodgex

dodgex commented Nov 2, 2017

Copy link
Copy Markdown
Member

@WonderCsabo Does your code work with incremental compilation?

@WonderCsabo WonderCsabo force-pushed the 1976_generate_classes_even_after_validation_errors branch from 563c6ea to 1e2932c Compare November 2, 2017 08:58
@WonderCsabo

Copy link
Copy Markdown
Member

@dodgex thanks, i did not know that, it is cool!

@WonderCsabo

Copy link
Copy Markdown
Member

@dodgex yes it works, i actually checked it, that is why i introduced the extractedModel into the AndroidAnnotationsEnvironment. (If you compile using IntelliJ "make" and not maven, it will use incremental).

return Kind.OTHER;
}

private class Message {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This class could be static.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

only if we pass the processingEnv as it is used in getElement()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Okay, leave it.

}
}

private class ElementDetails {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This class could be static.

return null;
}

private Element getElement() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a rather complicated method, should not we cache the result? Or this is called only once?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we should move this to an utility method, this logic is too much for a getter.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

As far as i can see it is only called once when the appender is closed in the last round.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what do you mean by move this to an utility method? If it is to much logic for a "getter" i'd just rename the method to something like findRelatedElement or so. :D

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Okay, we can leave this here.

@WonderCsabo

Copy link
Copy Markdown
Member

Did we update all licences? :)

@dodgex

dodgex commented Nov 2, 2017

Copy link
Copy Markdown
Member

I think all licenses are up to date. but I can check that when updating the PR. how to go with the getElement?

dodgex and others added 4 commits November 2, 2017 11:43
In some cases, error messages were not cleared during last round.
It is better to not use static fields to store these messages.
If some annotation depends on other generating annotations, we should
validate if the other annotations are ok, otherwise we will generate
not compilable code.
@dodgex dodgex force-pushed the 1976_generate_classes_even_after_validation_errors branch from 1e2932c to 0732dc3 Compare November 2, 2017 10:44
@dodgex

dodgex commented Nov 2, 2017

Copy link
Copy Markdown
Member

You missed to update the licenses but i fixed that. Also I made the ElementDetails static.

@dodgex dodgex added this to the 4.5 milestone Nov 3, 2017
@WonderCsabo WonderCsabo merged commit 05a2fc4 into androidannotations:develop Nov 4, 2017
@WonderCsabo

WonderCsabo commented Nov 4, 2017

Copy link
Copy Markdown
Member

Finally merged. Let's hope it will not introduce problems. Thanks for your work on this, @smaugho !

@smaugho

smaugho commented Nov 4, 2017

Copy link
Copy Markdown
Contributor Author

You're are welcome! Would like to be able to contribute much more to AA... lacking of time :'( ...

@smaugho smaugho deleted the 1976_generate_classes_even_after_validation_errors branch January 29, 2019 20:48
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.

3 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.