
org.codehaus.mevenide.hints.errors.SearchClassDependencyInRepo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of maven-hints Show documentation
Show all versions of maven-hints Show documentation
Providing Hints set for common mistakes and best practices
The newest version!
/*
* Copyright 2008 Mevenide Team.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* under the License.
*/
package org.codehaus.mevenide.hints.errors;
import com.sun.source.tree.ArrayTypeTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.lang.model.element.Name;
import org.apache.maven.model.Dependency;
import org.apache.maven.project.MavenProject;
import org.codehaus.mevenide.hints.ui.SearchDependencyUI;
import org.codehaus.mevenide.indexer.api.NBVersionInfo;
import org.codehaus.mevenide.indexer.api.RepositoryQueries;
import org.codehaus.mevenide.netbeans.NbMavenProject;
import org.codehaus.mevenide.netbeans.api.ModelUtils;
import org.codehaus.mevenide.netbeans.api.ProjectURLWatcher;
import org.netbeans.api.java.lexer.JavaTokenId;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.lexer.Token;
import org.netbeans.api.lexer.TokenHierarchy;
import org.netbeans.api.lexer.TokenSequence;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.netbeans.modules.java.hints.spi.ErrorRule;
import org.netbeans.modules.java.hints.spi.ErrorRule.Data;
import org.netbeans.spi.editor.hints.ChangeInfo;
import org.netbeans.spi.editor.hints.EnhancedFix;
import org.netbeans.spi.editor.hints.Fix;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;
/**
*
* @author Anuradha G
*/
public class SearchClassDependencyInRepo implements ErrorRule {
private AtomicBoolean cancel=new AtomicBoolean(false);
public SearchClassDependencyInRepo() {
}
public Set getCodes() {
return new HashSet(Arrays.asList(
"compiler.err.cant.resolve",//NOI18N
"compiler.err.cant.resolve.location",//NOI18N
"compiler.err.doesnt.exist",//NOI18N
"compiler.err.not.stmt"));//NOI18N
}
public List run(final CompilationInfo info, String diagnosticKey,
final int offset, TreePath treePath, Data data) {
cancel.set(false);
if (!SearchClassDependencyHint.isHintEnabled()) {
return Collections.emptyList();
}
//copyed from ImportClass
int errorPosition = offset + 1; //TODO: +1 required to work OK, rethink
if (errorPosition == (-1)) {
return Collections.emptyList();
}
//copyed from ImportClass-end
FileObject fileObject = info.getFileObject();
Project project = FileOwnerQuery.getOwner(fileObject);
if (project == null) {
return Collections.emptyList();
}
NbMavenProject mavProj = project.getLookup().lookup(NbMavenProject.class);
if (mavProj == null) {
return Collections.emptyList();
}
//copyed from ImportClass
TreePath path = info.getTreeUtilities().pathFor(errorPosition);
if (path.getParentPath() != null && path.getParentPath().getLeaf().getKind() == Kind.METHOD_INVOCATION) {
//#86313:
//if the error is in the type parameter, import should be proposed:
MethodInvocationTree mit = (MethodInvocationTree) path.getParentPath().getLeaf();
if (!mit.getTypeArguments().contains(path.getLeaf())) {
return Collections.emptyList();
}
}
if(cancel.get()) return Collections.emptyList();
if (path.getParentPath() != null) {
Tree leaf = path.getParentPath().getLeaf();
switch(leaf.getKind()){
//genaric handling
case PARAMETERIZED_TYPE:{
leaf=path.getParentPath().getParentPath().getLeaf();
}
break;
case ARRAY_TYPE:{
leaf=path.getParentPath().getParentPath().getLeaf();
}
break;
}
switch (leaf.getKind()) {
case VARIABLE:
{
Name typeName = null;
VariableTree variableTree = (VariableTree) leaf;
if (variableTree.getType() != null) {
switch (variableTree.getType().getKind()) {
case IDENTIFIER:
{
typeName = ((IdentifierTree) variableTree.getType()).getName();
}
break;
case PARAMETERIZED_TYPE:
{
ParameterizedTypeTree ptt = ((ParameterizedTypeTree) variableTree.getType());
if (ptt.getType() != null && ptt.getType().getKind() == Kind.IDENTIFIER) {
typeName = ((IdentifierTree) ptt.getType()).getName();
}
}
break;
case ARRAY_TYPE:
{
ArrayTypeTree ptt = ((ArrayTypeTree) variableTree.getType());
if (ptt.getType() != null && ptt.getType().getKind() == Kind.IDENTIFIER) {
typeName = ((IdentifierTree) ptt.getType()).getName();
}
}
break;
}
}
ExpressionTree initializer = variableTree.getInitializer();
if (typeName != null && initializer != null) {
Name itName = null;
switch (initializer.getKind()) {
case NEW_CLASS:
{
ExpressionTree identifier = null;
NewClassTree classTree = (NewClassTree) initializer;
identifier = classTree.getIdentifier();
if (identifier != null) {
switch (identifier.getKind()) {
case IDENTIFIER:
itName = ((IdentifierTree) identifier).getName();
break;
case PARAMETERIZED_TYPE:
{
ParameterizedTypeTree ptt = ((ParameterizedTypeTree) identifier);
if (ptt.getType() != null && ptt.getType().getKind() == Kind.IDENTIFIER) {
itName = ((IdentifierTree) ptt.getType()).getName();
}
}
break;
}
}
}
break;
case NEW_ARRAY: {
NewArrayTree arrayTree = (NewArrayTree) initializer;
Tree type = arrayTree.getType();
itName = ((IdentifierTree) type).getName();
}
break;
}
if (typeName.equals(itName)) {
return Collections.emptyList();
}
}
}
break;
}
}
Token ident = null;
try {
ident = findUnresolvedElementToken(info, offset);
} catch (IOException e) {
Exceptions.printStackTrace(e);
}
if (ident == null) {
return Collections.emptyList();
}
String simpleName = ident.text().toString();
//copyed from ImportClass-end
if(cancel.get()) return Collections.emptyList();
boolean isTestSource = false;
MavenProject mp = mavProj.getOriginalMavenProject();
String testSourceDirectory = mp.getBuild().getTestSourceDirectory();
File testdir = new File(testSourceDirectory);
FileObject fo = FileUtil.toFileObject(testdir);
//need check null because Test Dir may null
if (fo != null) {
isTestSource = FileUtil.isParentOf(fo, fileObject);
}
List fixes = new ArrayList();
if (SearchClassDependencyHint.isSearchDialog()) {
fixes.add(new MavenSearchFix(mavProj, simpleName, isTestSource));
} else {
//mkleint: this option is has rather serious performance impact.
// we need to work on performance before we enable it..
Collection findVersionsByClass = filter(mavProj,
RepositoryQueries.findVersionsByClass(simpleName), isTestSource);
for (NBVersionInfo nbvi : findVersionsByClass) {
fixes.add(new MavenFixImport(mavProj, nbvi, isTestSource));
}
}
return fixes;
}
private Collection filter(NbMavenProject mavProj, List nbvis, boolean test) {
Map items = new HashMap();
//check dependency already added
List dependencies = new ArrayList();
MavenProject prj = mavProj.getOriginalMavenProject();
if (test) {
dependencies.addAll(prj.getTestDependencies());
} else {
dependencies.addAll(prj.getDependencies());
}
for (NBVersionInfo info : nbvis) {
String key = info.getGroupId() + ":" + info.getArtifactId();
boolean b = items.containsKey(key);
if (!b) {
items.put(key, info);
}
for (Dependency dependency : dependencies) {
//check group id and ArtifactId and Scope even
if (dependency.getGroupId() != null && dependency.getGroupId().equals(info.getGroupId())) {
if (dependency.getArtifactId() != null && dependency.getArtifactId().equals(info.getArtifactId())) {
if (!test && dependency.getScope() != null && ("compile".equals(dependency.getScope()))) {//NOI18N
return Collections.emptyList();
}
}
}
}
}
List filterd = new ArrayList(items.values());
return filterd;
}
//copyed from ImportClass
public static Token findUnresolvedElementToken(CompilationInfo info, int offset) throws IOException {
TokenHierarchy> th = info.getTokenHierarchy();
TokenSequence ts = th.tokenSequence(JavaTokenId.language());
if (ts == null) {
return null;
}
ts.move(offset);
if (ts.moveNext()) {
Token t = ts.token();
if (t.id() == JavaTokenId.DOT) {
ts.moveNext();
t = ts.token();
} else {
if (t.id() == JavaTokenId.LT) {
ts.moveNext();
t = ts.token();
} else {
if (t.id() == JavaTokenId.NEW) {
boolean cont = ts.moveNext();
while (cont && ts.token().id() == JavaTokenId.WHITESPACE) {
cont = ts.moveNext();
}
if (!cont) {
return null;
}
t = ts.token();
}
}
}
if (t.id() == JavaTokenId.IDENTIFIER) {
return ts.offsetToken();
}
}
return null;
}
public String getId() {
return "MAVEN_MISSING_CLASS";//NOI18N
}
public String getDisplayName() {
return NbBundle.getMessage(SearchClassDependencyInRepo.class, "LBL_Class_Search_DisplayName");
}
public void cancel() {
//cancel task
cancel.set(true);
}
static final class MavenFixImport implements EnhancedFix {
private NbMavenProject mavProj;
private NBVersionInfo nbvi;
private boolean test;
public MavenFixImport(NbMavenProject mavProj, NBVersionInfo nbvi, boolean test) {
this.mavProj = mavProj;
this.nbvi = nbvi;
this.test = test;
}
public CharSequence getSortText() {
return getText();
}
public String getText() {
return NbBundle.getMessage(SearchClassDependencyInRepo.class,
"LBL_Class_Search_Fix", nbvi.getGroupId() + " : " + nbvi.getArtifactId() + " : " + nbvi.getVersion());
}
public ChangeInfo implement() throws Exception {
ModelUtils.addDependency(mavProj.getProjectDirectory().getFileObject("pom.xml"), nbvi.getGroupId(), nbvi.getArtifactId(),
nbvi.getVersion(), nbvi.getType(), test ? "test" : null, null, true);//NOI18N
RequestProcessor.getDefault().post(new Runnable() {
public void run() {
mavProj.getLookup().lookup(ProjectURLWatcher.class).triggerDependencyDownload();
}
});
return null;
}
}
static final class MavenSearchFix implements EnhancedFix {
private NbMavenProject mavProj;
private String clazz;
private boolean test;
public MavenSearchFix(NbMavenProject mavProj, String clazz, boolean test) {
this.mavProj = mavProj;
this.clazz = clazz;
this.test = test;
}
public CharSequence getSortText() {
return getText();
}
public String getText() {
return org.openide.util.NbBundle.getMessage(SearchClassDependencyInRepo.class, "LBL_Class_Search_ALL_Fix", clazz);
}
public ChangeInfo implement() throws Exception {
NBVersionInfo nbvi = null;
SearchDependencyUI dependencyUI = new SearchDependencyUI(clazz, mavProj);
DialogDescriptor dd = new DialogDescriptor(dependencyUI,
org.openide.util.NbBundle.getMessage(SearchClassDependencyInRepo.class, "LBL_Search_Repo"));
dd.setClosingOptions(new Object[]{
dependencyUI.getAddButton(),
DialogDescriptor.CANCEL_OPTION
});
dd.setOptions(new Object[]{
dependencyUI.getAddButton(),
DialogDescriptor.CANCEL_OPTION
});
Object ret = DialogDisplayer.getDefault().notify(dd);
if (dependencyUI.getAddButton() == ret) {
nbvi = dependencyUI.getSelectedVersion();
}
if (nbvi != null) {
ModelUtils.addDependency(mavProj.getProjectDirectory().getFileObject("pom.xml"), nbvi.getGroupId(), nbvi.getArtifactId(),
nbvi.getVersion(), nbvi.getType(), test ? "test" : null, null, true);//NOI18N
RequestProcessor.getDefault().post(new Runnable() {
public void run() {
mavProj.getLookup().lookup(ProjectURLWatcher.class).triggerDependencyDownload();
}
});
}
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy