Eclipse : disabling the warning only on the folder [duplicate] - java

I'm using a parser generator that creates somewhat ugly code. As a result my Eclipse project has several dozen warnings emanating from generated source files. I know I can use the #SuppressWarning annotation to suppress particular warnings in particular elements, but any annotations I add by hand will be lost when the parser generator runs again. Is there a way to configure Eclipse to suppress warnings for a particular file or directory?

Starting with version 3.8 M6, Eclipse (to be exact: the JDT) has built-in functionality for this. It is configurable through a project's build path: Project properties > Java Build Path > Compiler > Source
Announced here: Eclipse 3.8 and 4.2 M6 - New and Noteworthy, called Selectively ignore errors/warnings from source folders. That's also where the screenshot is from. This is the new feature developed on the previously linked Bug 220928.

There is a ticket for this, Bug 220928, that has since been completed for Eclipse 3.8. Please see this answer for details.
If you're stuck with Eclipse 3.7 or lower: The user "Marc" commenting on that ticket created (or at least links to) a plugin called 'warningcleaner' in comment 35. I'm using that with a lot of success while waiting for this feature to be integrated into Eclipse.
It's really quite simple:
Install plugin.
Right-click project and select "Add/remove generated code nature".
Open the project settings (right-click and select "properties").
Open the tab 'Warning Cleaner'.
Select the source folders you want to ignore the warnings from.

I solved this by using the maven regexp replace plugin - it does not solve the cause, but heals the pain:
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>maven-replacer-plugin</artifactId>
<version>1.3.2</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>target/generated-sources/antlr/**/*.java</include>
</includes>
<regex>true</regex>
<regexFlags>
<regexFlag>MULTILINE</regexFlag>
</regexFlags>
<replacements>
<replacement>
<token>^public class</token>
<value>#SuppressWarnings("all") public class</value>
</replacement>
</replacements>
</configuration>
</plugin>
Note that I did not manage to get the ** notation to work, so you might have to specify path exactly.
See comment below for an improvement on how not to generate duplicate #SupressWarnings

I think the best you can do is enable project specific settings for displaying warnings.
Window -> Preferences -> Java -> Compiler -> Errors/Warnings
On the top of the form is a link for configuring project specific settings.

User #Jorn hinted at Ant code to do this. Here's what I have
<echo>Adding #SuppressWarnings("all") to ANTLR generated parser/lexer *.java</echo>
<echo> in ${project.build.directory}/generated-sources/antlr/</echo>
<replace dir="${project.build.directory}/generated-sources/antlr/"
summary="true"
includes="**/*.java"
token="public class"
value='#SuppressWarnings("all") public class' />
Note that Ant's <replace> does text replacement, not regular expression replacement,
so it cannot use the ^ meta-character in the token to match beginning of line as the maven regexp replace plugin does.
I'm doing this at the same time that I run Antlr from maven-antrun-plugin in my Maven pom, because the ANTLR maven plugin did not play well with the Cobertura maven plugin.
(I realize this is not an answer to the original question, but I can't format Ant code in a comment/reply to another answer, only in an answer)

I don't think Eclipse inherently provides a way to do this at the directory level (but I'm not sure).
You could have the generated files go into a separate Java project, and control warnings for that specific project.
I generally prefer to place automatically-generated code in a separate project anyway.

You can only suppress warnings at the project level. However, you can configure your problems tab to suppress warnings from files or packages. Go into the Configure Contents menu and work with the "On working set:" scope.

This small python script "patches" the M2E-generated .classpath files and adds the required XML tag to all source folders starting with target/generated-sources. You can just run it from you project's root folder. Obviously you need to re-run it when the Eclipse project information is re-generated from M2E. And all at your own risk, obviously ;-)
#!/usr/bin/env python
from xml.dom.minidom import parse
import glob
import os
print('Reading .classpath files...')
for root, dirs, files in os.walk('.'):
for name in files:
if (name == '.classpath'):
classpathFile = os.path.join(root, name)
print('Patching file:' + classpathFile)
classpathDOM = parse(classpathFile)
classPathEntries = classpathDOM.getElementsByTagName('classpathentry')
for classPathEntry in classPathEntries:
if classPathEntry.attributes["path"].value.startswith('target/generated-sources'):
# ensure that the <attributes> tag exists
attributesNode = None;
for attributes in classPathEntry.childNodes:
if (attributes.nodeName == 'attributes'):
attributesNode = attributes
if (attributesNode == None):
attributesNode = classpathDOM.createElement('attributes')
classPathEntry.appendChild(attributesNode)
# search if the 'ignore_optional_problems' entry exists
hasBeenSet = 0
for node in attributesNode.childNodes:
if (node.nodeName == 'attribute' and node.getAttribute('name') == 'ignore_optional_problems'):
# it exists, make sure its value is true
node.setAttribute('value','true')
#print(node.getAttribute('name'))
hasBeenSet = 1
if (not(hasBeenSet)):
# it does not exist, add it
x = classpathDOM.createElement("attribute")
x.setAttribute('name','ignore_optional_problems')
x.setAttribute('value','true')
attributesNode.appendChild(x)
try:
f = open(classpathFile, "w")
classpathDOM.writexml(f)
print('Writing file:' + classpathFile)
finally:
f.close()
print('Done.')

I'm doing this to a few ANTLR grammars, which generate a Java parser using Ant. The Ant build script adds the #SuppressWarnings("all") to one Java file, and #Override to a few methods in another.
I can look up how it's done exactly, if you're interested.

In the case of ANTLR 2, it is possible to suppress warnings in generated code by appenidng #SuppressWarnings before the class declaration in the grammar file, e.g.
{#SuppressWarnings("all")} class MyBaseParser extends Parser;

This can be done by excluding certain directories from the build path (The following example is given using Eclipse 3.5)
[1] Bring up the Java Build Path
Click on the projectin Package Explorer
Right click, properties
Select Java Build Path
[2] Add directories to exclude
The Source tab should contain details of the project source folders
Expand the source folder and locate the 'Excluded:' property
Select 'Excluded:' and click Edit
Add folders into the Exclusion patterns using the Add/Add Multiple options
Click Finish, then ok for Eclipse to rebuild.

It's been a while since I have released the warning-cleaner plugin, and now that I am using Eclipse 3.8, I have no need for it anymore.
However, for those who still need this plugin, I have released it on github with the update site on bintray.
If you are still using Eclipse 3.7 or before, this could be useful.
Check this site for installation details.

If the eclipse project is generated from gradle using Eclipse plugin's eclipse command the Selectively ignore errors/warnings from source folders option can be set by adding this on the top level of you build.gradle file:
eclipse.classpath.file {
whenMerged { classpath ->
classpath.entries.each { entry ->
if (entry.path.contains('build/generated/parser')) {
entry.entryAttributes['ignore_optional_problems'] = true
}
}
}
}
This assumes that generated sources are in build/generated/parser folder.

Related

Question about groovy scripts recognition by IntelliJ IDEA

I guess by asking this I might sound a bit illegible, but I'm still unsure as to how to approach the problem.
In my spring project (not really my, work stuff) I've got some groovy scripts which are initially treated as resources, yet in reality they are rather the "source code" which is compiled not during the gradle assembly of the project but during the runtime by the application itself. And everything's fine with that.
The problem is that the IDE doesn't treat the groovy file properly. Dumb example to somehow describe what I mean:
import myproject.example.blabla
import groovy.transform.CompileStatic
#CompileStatic
class SomeClass1 implements SomeClass2 {
private final SomeClass2 someName1
SomeClass1() {
someName1 = new something
}
#Override
String getSmth() {
return someName1.getSmth()
}
}
The problems:
when I make "command + left_click" on SomeClass2, it says Cannot find declaration to go to, but when I press "command + O" it finds the file because it actually exists
.getSmth() is red, because Cannot resolve symbol
So it seems that I need to somehow show the dependencies via gradle to IDE only. Like, somehow specify the dependencies explicitly for IntelliJ IDEA so that it would understand that it is a source code as well and stop underlining everything with red.
Such files must be located in the module's Source Root directory for the IDE to recognize them as sources and so that navigation would also work.
In a Gradle-based project IDE configures Source Roots automatically based on the Gradle's Source Sets configuration. For each Gradle source set IDE creates a module with one Source Root directory.
So you must configure Gradle to create source set for the directories where these files are located: add them into default sources sets or create a custom source set for them.

How can I disable warnings on package level in Eclipse?

I have a folder of source files (say src/main/java), which contains two super-packages:
com.blah.generated
com.blah.software
The com.blah.generated code is generated by a tool which cannot be run at every compilation and is checked in to version control. We never change it, it is occasionally re-generated when there's a new dependency on a new release.
The generated code has 100s of warnings, which I want to get rid of. I don't have access to the generator code, nor can I relocate the package to a different folder.
Obviously I have a source folder pointing to src/main/java. I tried to exclude the com.blah.generated package, but then the com.blah.software using it fails to compile.
I tried adding a second source folder pointing to the same folder, and excluding com.blah.software so that I can turn on "Ignore optional compile problems", but Eclipse complains (however there's no overlapping between the two folders):
Build path contains duplicate entry: 'src/main/java' for project 'blah'
I also tried filtering the Problems view to
Include selected element and its children EXCEPT the com.blah.generated.
but there's no such option.
IIUC, Eclipse Juno introduced such a capability:
http://help.eclipse.org/juno/topic/org.eclipse.jdt.doc.user/whatsNew/jdt_whatsnew.html#JavaCompiler
Still, to remover all Unused warnings on Eclipse, go to (for Eclipse Helios):
Window Menu > Preferences.
Select Java > Compiler > Errors/Warnings.
In Generic types, change to Ignore the option "Unchecked generic type operacion".

Maven - synch "main" folder with "tests" folder

I'm just starting to use Maven with my project. All of my production code is of course inside the main directory. As I add unit tests to my tests directory, is there a way to synchronize the main dir with my tests dir?
For example, say I add a new package org.bio.mynewpackage. I have to go in my main folder and add the same package name... this is rather annoying.
Any ideas?
Here is a Groovy Script embedded in a GMaven plugin execution. It does exactly what you are asking for.
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>mirror-folder-structure</id>
<phase>generate-test-sources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
<![CDATA[
static void createShadow(File base, File shadow){
if(base.exists()&&!shadow.exists())shadow.mkdirs();
base.eachDir { createShadow(it, new File(shadow, it.name))};
}
createShadow(pom.build.sourceDirectory,pom.build.testSourceDirectory);
]]>
</source>
</configuration>
</execution>
</executions>
</plugin>
The problem is: it won't run automatically. I have bound it to the phase generate-test-sources, but you can choose any other phase. You will however have to execute that phase manually, e.g. mvn generate-test-sources.
If you would however consider using Eclipse with the m2eclipse plugin, m2eclipse lets you define lifecycle phases that it runs automatically when you have saved a file, so that would be easier.
I don't know if I get your problem right: usually, by convention, maven will detect all class files in main/java and all class files in test/java. You don't have to declare the package names.
So if you add an new package an classes to "main", they will be compiled and packaged, if you add some new tests to "test", the will be autodiscovered and executed in the test phase.
Typically I would rely on the IDE to do this when I create tests.
Eg:
I create a new class org.bio.mynewpackage.MyNewClass in main/.
Now when I create a test org.bio.mynewpackage.MyNewClassTest, the IDE should automatically create the necessary directory tree.
I don't know if you were looking for something specific regards how maven might help you do this. Still i've always used rsync to match to target folders.
Something along the lines of:
rsync -Crit ./source ./target
where C ignores versioning
files/folders such as .svn
r is recursion i is information output.
t is timestamp. i've always put this
to ensure differences in files are
based on time stamp.
Add 'n' to run in test mode, it will output what will change rather than actually do it. Always do this first as rsync can totally mess things up if you don't have it right.
You can also add pattern matching rules, either in a file in each directory or once in the command line.
I don't know of any plugin that does this, but it should be pretty easy to write one. It could possibly even be done with some simple Groovy scripting using gmaven-plugin or the like.
Alternatively, this shell command should do what you want:
# ! -wholename '*/.*' excludes hidden dirs like .svn
$( cd src/main/java/ && find -type d ! -wholename '*/.*' -exec mkdir -p ../../test/java/{} \; )
EDIT:
Here's a simple Maven plugin (this plugin sorts entries of eclipse .classpath files by name) that should give you a quick start into Maven plugin development.

How to suppress Java warnings for specific directories or files such as generated code

I'm using a parser generator that creates somewhat ugly code. As a result my Eclipse project has several dozen warnings emanating from generated source files. I know I can use the #SuppressWarning annotation to suppress particular warnings in particular elements, but any annotations I add by hand will be lost when the parser generator runs again. Is there a way to configure Eclipse to suppress warnings for a particular file or directory?
Starting with version 3.8 M6, Eclipse (to be exact: the JDT) has built-in functionality for this. It is configurable through a project's build path: Project properties > Java Build Path > Compiler > Source
Announced here: Eclipse 3.8 and 4.2 M6 - New and Noteworthy, called Selectively ignore errors/warnings from source folders. That's also where the screenshot is from. This is the new feature developed on the previously linked Bug 220928.
There is a ticket for this, Bug 220928, that has since been completed for Eclipse 3.8. Please see this answer for details.
If you're stuck with Eclipse 3.7 or lower: The user "Marc" commenting on that ticket created (or at least links to) a plugin called 'warningcleaner' in comment 35. I'm using that with a lot of success while waiting for this feature to be integrated into Eclipse.
It's really quite simple:
Install plugin.
Right-click project and select "Add/remove generated code nature".
Open the project settings (right-click and select "properties").
Open the tab 'Warning Cleaner'.
Select the source folders you want to ignore the warnings from.
I solved this by using the maven regexp replace plugin - it does not solve the cause, but heals the pain:
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>maven-replacer-plugin</artifactId>
<version>1.3.2</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<include>target/generated-sources/antlr/**/*.java</include>
</includes>
<regex>true</regex>
<regexFlags>
<regexFlag>MULTILINE</regexFlag>
</regexFlags>
<replacements>
<replacement>
<token>^public class</token>
<value>#SuppressWarnings("all") public class</value>
</replacement>
</replacements>
</configuration>
</plugin>
Note that I did not manage to get the ** notation to work, so you might have to specify path exactly.
See comment below for an improvement on how not to generate duplicate #SupressWarnings
I think the best you can do is enable project specific settings for displaying warnings.
Window -> Preferences -> Java -> Compiler -> Errors/Warnings
On the top of the form is a link for configuring project specific settings.
User #Jorn hinted at Ant code to do this. Here's what I have
<echo>Adding #SuppressWarnings("all") to ANTLR generated parser/lexer *.java</echo>
<echo> in ${project.build.directory}/generated-sources/antlr/</echo>
<replace dir="${project.build.directory}/generated-sources/antlr/"
summary="true"
includes="**/*.java"
token="public class"
value='#SuppressWarnings("all") public class' />
Note that Ant's <replace> does text replacement, not regular expression replacement,
so it cannot use the ^ meta-character in the token to match beginning of line as the maven regexp replace plugin does.
I'm doing this at the same time that I run Antlr from maven-antrun-plugin in my Maven pom, because the ANTLR maven plugin did not play well with the Cobertura maven plugin.
(I realize this is not an answer to the original question, but I can't format Ant code in a comment/reply to another answer, only in an answer)
I don't think Eclipse inherently provides a way to do this at the directory level (but I'm not sure).
You could have the generated files go into a separate Java project, and control warnings for that specific project.
I generally prefer to place automatically-generated code in a separate project anyway.
You can only suppress warnings at the project level. However, you can configure your problems tab to suppress warnings from files or packages. Go into the Configure Contents menu and work with the "On working set:" scope.
This small python script "patches" the M2E-generated .classpath files and adds the required XML tag to all source folders starting with target/generated-sources. You can just run it from you project's root folder. Obviously you need to re-run it when the Eclipse project information is re-generated from M2E. And all at your own risk, obviously ;-)
#!/usr/bin/env python
from xml.dom.minidom import parse
import glob
import os
print('Reading .classpath files...')
for root, dirs, files in os.walk('.'):
for name in files:
if (name == '.classpath'):
classpathFile = os.path.join(root, name)
print('Patching file:' + classpathFile)
classpathDOM = parse(classpathFile)
classPathEntries = classpathDOM.getElementsByTagName('classpathentry')
for classPathEntry in classPathEntries:
if classPathEntry.attributes["path"].value.startswith('target/generated-sources'):
# ensure that the <attributes> tag exists
attributesNode = None;
for attributes in classPathEntry.childNodes:
if (attributes.nodeName == 'attributes'):
attributesNode = attributes
if (attributesNode == None):
attributesNode = classpathDOM.createElement('attributes')
classPathEntry.appendChild(attributesNode)
# search if the 'ignore_optional_problems' entry exists
hasBeenSet = 0
for node in attributesNode.childNodes:
if (node.nodeName == 'attribute' and node.getAttribute('name') == 'ignore_optional_problems'):
# it exists, make sure its value is true
node.setAttribute('value','true')
#print(node.getAttribute('name'))
hasBeenSet = 1
if (not(hasBeenSet)):
# it does not exist, add it
x = classpathDOM.createElement("attribute")
x.setAttribute('name','ignore_optional_problems')
x.setAttribute('value','true')
attributesNode.appendChild(x)
try:
f = open(classpathFile, "w")
classpathDOM.writexml(f)
print('Writing file:' + classpathFile)
finally:
f.close()
print('Done.')
I'm doing this to a few ANTLR grammars, which generate a Java parser using Ant. The Ant build script adds the #SuppressWarnings("all") to one Java file, and #Override to a few methods in another.
I can look up how it's done exactly, if you're interested.
In the case of ANTLR 2, it is possible to suppress warnings in generated code by appenidng #SuppressWarnings before the class declaration in the grammar file, e.g.
{#SuppressWarnings("all")} class MyBaseParser extends Parser;
This can be done by excluding certain directories from the build path (The following example is given using Eclipse 3.5)
[1] Bring up the Java Build Path
Click on the projectin Package Explorer
Right click, properties
Select Java Build Path
[2] Add directories to exclude
The Source tab should contain details of the project source folders
Expand the source folder and locate the 'Excluded:' property
Select 'Excluded:' and click Edit
Add folders into the Exclusion patterns using the Add/Add Multiple options
Click Finish, then ok for Eclipse to rebuild.
It's been a while since I have released the warning-cleaner plugin, and now that I am using Eclipse 3.8, I have no need for it anymore.
However, for those who still need this plugin, I have released it on github with the update site on bintray.
If you are still using Eclipse 3.7 or before, this could be useful.
Check this site for installation details.
If the eclipse project is generated from gradle using Eclipse plugin's eclipse command the Selectively ignore errors/warnings from source folders option can be set by adding this on the top level of you build.gradle file:
eclipse.classpath.file {
whenMerged { classpath ->
classpath.entries.each { entry ->
if (entry.path.contains('build/generated/parser')) {
entry.entryAttributes['ignore_optional_problems'] = true
}
}
}
}
This assumes that generated sources are in build/generated/parser folder.

Injecting current git commit id into Java webapp

We have a git repository which contains source for a few related Java WARs and JARs. It would be nice if the Java code could somehow:
System.err.println("I was built from git commit " + commitID);
(Obviously real code might be putting this into an HTTP header, logging it on startup, or whatever, that's not important right now)
We are using Ant to build (at least for production builds, it seems some programmers do their testing from inside Eclipse which I know even less about) binaries.
Is there a canonical way to get the commit id for the current git checkout into our Java at build time? If not, can people using Ant to build suggest how they'd do it and we'll see if a canonical solution emerges? I'm sure I can invent something myself entirely from whole cloth, but this seems like a re-usable building block, so I'd rather not.
You can get the last commit SHA with
git rev-parse HEAD
but it's generally a lot more useful to use
git describe
which will give you something that looks like this:
v0.7.0-185-g83e38c7
This works if you have tags - it will tell you how many commits from the last valid tag your current checkout is at plus a partial SHA for that commit, so you can use it to base a checkout off of later. You can use this identifier just like a SHA in most circumstances, but it's much more human readable.
I don't know if there are any Ant task for git (I googled a bit without success), anyway Ant can update a properties file with Piotr's option (git rev-parse HEAD) and then in runtime use that properties to get the revision number. This is cleaner and IDE friendly than having Ant generating a .java file.
If it helps for someone else. I know yours is ANT
For MAVEN build, you could probably use git-commit-id-plugin in your pom.xml file
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>2.2.0</version>
<executions>
<execution>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
</configuration>
</plugin>
Please go through :
1. http://www.baeldung.com/spring-git-information &
2. https://github.com/ktoso/maven-git-commit-id-plugin for more info.
I wrote an Ant task to get the buildnumber using JGit API (without git command line app), see jgit-buildnumber-ant-task. Then you can store this buildnumber inside MANIFEST.MF file and get it from the classpath on runtime.
git rev-parse HEAD will print what you probably want (e.g. id of HEAD commit).
You can make ant generate a simple Java class with this id as a static constant.
First, you can use ident gitattribute with $Id$ keyword (although it is not probably what you want; it is hash of file contents, and has nothing to do with current project version).
Second, you can do it the way Linux kernel and Git itself do it: in Makefile (in your case: in Ant file) there is rule which replaces some placeholder, usually '##VERSION##' (but in case of Perl it is '++VERSION++') by result of GIT-VERSION-GEN, which in turn uses "git describe". But for that to be useful you have to tag your releases (using annotated / signed tags).

Categories