Add markers against lines that contain missing elements

This commit is contained in:
konsoletyper 2014-09-15 21:21:25 +04:00
parent 465c7626ce
commit f204c8cc4a
4 changed files with 104 additions and 9 deletions

View File

@ -235,7 +235,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
if (method != null) { if (method != null) {
tasks.add(new Runnable() { tasks.add(new Runnable() {
@Override public void run() { @Override public void run() {
linkMethod(method.getReference(), stack); linkMethod(method.getReference(), stack).use();
} }
}); });
} }

View File

@ -67,4 +67,12 @@
<run class="org.teavm.eclipse.TeaVMBuilder"/> <run class="org.teavm.eclipse.TeaVMBuilder"/>
</builder> </builder>
</extension> </extension>
<extension id="dependencyMarker" point="org.eclipse.core.resources.markers" name="TeaVM dependency problem">
<super type="org.eclipse.core.resources.problemmarker"/>
<persistent value="false"/>
<attribute name="severity"/>
<attribute name="message"/>
<attribute name="lineNumber"/>
</extension>
</plugin> </plugin>

View File

@ -10,9 +10,10 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.variables.VariablesPlugin; import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.*;
import org.eclipse.jdt.core.IJavaProject; import org.teavm.dependency.*;
import org.eclipse.jdt.core.JavaCore; import org.teavm.model.InstructionLocation;
import org.teavm.model.MethodReference;
import org.teavm.tooling.RuntimeCopyOperation; import org.teavm.tooling.RuntimeCopyOperation;
import org.teavm.tooling.TeaVMTool; import org.teavm.tooling.TeaVMTool;
import org.teavm.tooling.TeaVMToolException; import org.teavm.tooling.TeaVMToolException;
@ -22,6 +23,9 @@ import org.teavm.tooling.TeaVMToolException;
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public class TeaVMBuilder extends IncrementalProjectBuilder { public class TeaVMBuilder extends IncrementalProjectBuilder {
private URL[] classPath;
private IContainer[] sourceContainers;
@Override @Override
protected IProject[] build(int kind, Map<String, String> args, IProgressMonitor monitor) throws CoreException { protected IProject[] build(int kind, Map<String, String> args, IProgressMonitor monitor) throws CoreException {
TeaVMProjectSettings projectSettings = getProjectSettings(); TeaVMProjectSettings projectSettings = getProjectSettings();
@ -39,28 +43,93 @@ public class TeaVMBuilder extends IncrementalProjectBuilder {
tool.setProgressListener(new TeaVMEclipseProgressListener(monitor)); tool.setProgressListener(new TeaVMEclipseProgressListener(monitor));
try { try {
tool.generate(); tool.generate();
tool.checkForMissingItems(); removeMarkers();
if (tool.getDependencyViolations().hasMissingItems()) {
putMarkers(tool.getDependencyViolations());
}
} catch (TeaVMToolException e) { } catch (TeaVMToolException e) {
throw new CoreException(TeaVMEclipsePlugin.makeError(e)); throw new CoreException(TeaVMEclipsePlugin.makeError(e));
} }
return null; return null;
} }
private void removeMarkers() throws CoreException {
getProject().deleteMarkers(TeaVMEclipsePlugin.DEPENDENCY_MARKER_ID, true, IResource.DEPTH_INFINITE);
}
private void putMarkers(DependencyViolations violations) throws CoreException {
for (ClassDependencyInfo dep : violations.getMissingClasses()) {
putMarker("Missing class " + dep.getClassName(), dep.getStack());
}
for (FieldDependencyInfo dep : violations.getMissingFields()) {
putMarker("Missing field " + dep.getReference().toString(), dep.getStack());
}
for (MethodDependencyInfo dep : violations.getMissingMethods()) {
putMarker("Missing method " + dep.getReference().toString(), dep.getStack());
}
}
private void putMarker(String message, DependencyStack stack) throws CoreException {
while (stack != DependencyStack.ROOT) {
putMarker(message, stack.getLocation(), stack.getMethod());
stack = stack.getCause();
}
}
private void putMarker(String message, InstructionLocation location, MethodReference methodRef)
throws CoreException {
IResource resource = null;
if (location != null) {
String resourceName = location.getFileName();
for (IContainer container : sourceContainers) {
resource = container.findMember(resourceName);
if (resource != null) {
break;
}
}
}
if (resource == null) {
String resourceName = methodRef.getClassName().replace('.', '/') + ".java";
for (IContainer container : sourceContainers) {
resource = container.findMember(resourceName);
if (resource != null) {
break;
}
}
}
if (resource != null) {
IMarker marker = resource.createMarker(TeaVMEclipsePlugin.DEPENDENCY_MARKER_ID);
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
marker.setAttribute(IMarker.MESSAGE, message);
if (location != null) {
marker.setAttribute(IMarker.LINE_NUMBER, location.getLine());
} else {
ICompilationUnit unit = (ICompilationUnit)JavaCore.create(resource);
IType type = unit.getType(methodRef.getClassName());
// TODO: find method declaration location and put marker there
}
}
}
private TeaVMProjectSettings getProjectSettings() { private TeaVMProjectSettings getProjectSettings() {
return TeaVMEclipsePlugin.getDefault().getSettings(getProject()); return TeaVMEclipsePlugin.getDefault().getSettings(getProject());
} }
private ClassLoader prepareClassLoader() throws CoreException { private ClassLoader prepareClassLoader() throws CoreException {
return new URLClassLoader(prepareClassPath(), Thread.currentThread().getContextClassLoader()); prepareClassPath();
return new URLClassLoader(classPath, TeaVMBuilder.class.getClassLoader());
} }
private URL[] prepareClassPath() throws CoreException { private void prepareClassPath() throws CoreException {
classPath = new URL[0];
sourceContainers = new IContainer[0];
IProject project = getProject(); IProject project = getProject();
if (!project.hasNature(JavaCore.NATURE_ID)) { if (!project.hasNature(JavaCore.NATURE_ID)) {
return new URL[0]; return;
} }
IJavaProject javaProject = JavaCore.create(project); IJavaProject javaProject = JavaCore.create(project);
PathCollector collector = new PathCollector(); PathCollector collector = new PathCollector();
SourcePathCollector srcCollector = new SourcePathCollector();
IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot(); IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot();
try { try {
collector.addPath(workspaceRoot.findMember(javaProject.getOutputLocation()).getLocation()); collector.addPath(workspaceRoot.findMember(javaProject.getOutputLocation()).getLocation());
@ -85,6 +154,7 @@ public class TeaVMBuilder extends IncrementalProjectBuilder {
TeaVMEclipsePlugin.logError(e); TeaVMEclipsePlugin.logError(e);
} }
} }
srcCollector.addContainer((IContainer)workspaceRoot.findMember(entry.getPath()));
break; break;
case IClasspathEntry.CPE_PROJECT: { case IClasspathEntry.CPE_PROJECT: {
IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(entry.getPath()); IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(entry.getPath());
@ -105,7 +175,8 @@ public class TeaVMBuilder extends IncrementalProjectBuilder {
} }
} }
} }
return collector.getUrls(); classPath = collector.getUrls();
sourceContainers = srcCollector.getContainers();
} }
static class PathCollector { static class PathCollector {
@ -132,4 +203,19 @@ public class TeaVMBuilder extends IncrementalProjectBuilder {
return urls.toArray(new URL[urls.size()]); return urls.toArray(new URL[urls.size()]);
} }
} }
static class SourcePathCollector {
private Set<IContainer> containerSet = new HashSet<>();
private List<IContainer> containers = new ArrayList<>();
public void addContainer(IContainer container) {
if (containerSet.add(container)) {
containers.add(container);
}
}
public IContainer[] getContainers() {
return containers.toArray(new IContainer[containers.size()]);
}
}
} }

View File

@ -38,6 +38,7 @@ public class TeaVMEclipsePlugin extends AbstractUIPlugin {
public static final String NATURE_ID = ID + ".nature"; public static final String NATURE_ID = ID + ".nature";
public static final String BUILDER_ID = ID + ".builder"; public static final String BUILDER_ID = ID + ".builder";
public static final String MAIN_METHOD_DIALOG_ID = ID + ".dialogs.mainMethod"; public static final String MAIN_METHOD_DIALOG_ID = ID + ".dialogs.mainMethod";
public static final String DEPENDENCY_MARKER_ID = ID + ".dependencyMarker";
private static TeaVMEclipsePlugin defaultInstance; private static TeaVMEclipsePlugin defaultInstance;
private ConcurrentMap<IProject, TeaVMProjectSettings> settingsMap = new ConcurrentHashMap<>(); private ConcurrentMap<IProject, TeaVMProjectSettings> settingsMap = new ConcurrentHashMap<>();