aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorszarnekow2009-03-09 10:57:33 (EDT)
committersefftinge2009-03-09 10:57:33 (EDT)
commita64b60316c5a233005d6f90153b1630d8b705500 (patch)
treeeb39bce5acd878aac6130e96055c3395c0cc2b73
parent178112adb586a0db1d379a8053d3f5c9ccea3295 (diff)
downloadorg.eclipse.xtext-a64b60316c5a233005d6f90153b1630d8b705500.zip
org.eclipse.xtext-a64b60316c5a233005d6f90153b1630d8b705500.tar.gz
org.eclipse.xtext-a64b60316c5a233005d6f90153b1630d8b705500.tar.bz2
Feature: More validation for the Xtext grammar itself
Feature: XtextEditor can be opened with IStorageEditorInput, too. Fix: XtextDocument is not parsed twice, when opened
-rw-r--r--plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java4
-rw-r--r--plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextResourceChecker.java35
-rw-r--r--plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/model/XtextDocument.java81
-rw-r--r--plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/model/XtextDocumentProvider.java11
-rw-r--r--plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/reconciler/XtextReconciler.java17
-rw-r--r--plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/utils/ValidationJob.java20
6 files changed, 82 insertions, 86 deletions
diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java
index 5b1db54..136f9c4 100644
--- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java
+++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java
@@ -20,7 +20,6 @@ import org.eclipse.jface.text.source.projection.ProjectionViewer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
-import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.editors.text.TextEditor;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
@@ -81,9 +80,6 @@ public class XtextEditor extends TextEditor {
if (log.isDebugEnabled())
log.debug("init:" + input);
- if (!(input instanceof IURIEditorInput))
- throw new IllegalArgumentException("Can only handle IURIEditorInputs");
-
// do document provider setup
setDocumentProvider(documentProvider.get());
diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextResourceChecker.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextResourceChecker.java
index 72021da..793e0d6 100644
--- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextResourceChecker.java
+++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextResourceChecker.java
@@ -130,14 +130,20 @@ public class XtextResourceChecker {
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(ele, context);
if (!diagnostic.getChildren().isEmpty()) {
for (Diagnostic childDiagnostic : diagnostic.getChildren()) {
- markers.add(markerFromEValidatorDiagnostic(childDiagnostic));
+ Map<String, Object> marker = markerFromEValidatorDiagnostic(childDiagnostic);
+ if (marker != null) {
+ markers.add(marker);
+ if (markers.size() > MAX_ERRORS)
+ return markers;
+ }
+ }
+ } else {
+ Map<String, Object> marker = markerFromEValidatorDiagnostic(diagnostic);
+ if (marker != null) {
+ markers.add(marker);
if (markers.size() > MAX_ERRORS)
return markers;
}
- } else {
- markers.add(markerFromEValidatorDiagnostic(diagnostic));
- if (markers.size() > MAX_ERRORS)
- return markers;
}
} catch (RuntimeException e) {
log.error(e.getMessage(), e);
@@ -173,16 +179,17 @@ public class XtextResourceChecker {
}
private static Map<String, Object> markerFromEValidatorDiagnostic(Diagnostic diagnostic) {
+ if (diagnostic.getSeverity() == Diagnostic.OK)
+ return null;
Map<String, Object> map = new HashMap<String, Object>();
int sever = IMarker.SEVERITY_ERROR;
switch (diagnostic.getSeverity()) {
- case Diagnostic.WARNING:
- sever = IMarker.SEVERITY_WARNING;
- break;
- case Diagnostic.OK:
- case Diagnostic.INFO:
- sever = IMarker.SEVERITY_INFO;
- break;
+ case Diagnostic.WARNING:
+ sever = IMarker.SEVERITY_WARNING;
+ break;
+ case Diagnostic.INFO:
+ sever = IMarker.SEVERITY_INFO;
+ break;
}
map.put(IMarker.SEVERITY, sever);
Iterator<?> data = diagnostic.getData().iterator();
@@ -191,10 +198,10 @@ public class XtextResourceChecker {
if (causer instanceof EObject) {
EObject ele = (EObject) causer;
NodeAdapter nodeAdapter = NodeUtil.getNodeAdapter(ele);
- if (nodeAdapter != null && data.hasNext()) {
+ if (nodeAdapter != null) {
AbstractNode parserNode = nodeAdapter.getParserNode();
// feature is the second element see Diagnostician.getData
- Object feature = data.next();
+ Object feature = data.hasNext() ? data.next() : null;
EStructuralFeature structuralFeature = resolveStructuralFeature(ele, feature);
if (structuralFeature != null) {
List<AbstractNode> nodes = NodeUtil.findNodesForFeature(ele, structuralFeature);
diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/model/XtextDocument.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/model/XtextDocument.java
index 74af418..caeab92 100644
--- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/model/XtextDocument.java
+++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/model/XtextDocument.java
@@ -8,7 +8,6 @@
*******************************************************************************/
package org.eclipse.xtext.ui.core.editor.model;
-import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
@@ -19,6 +18,7 @@ import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Path;
@@ -30,13 +30,13 @@ import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.text.Document;
import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.ide.ResourceUtil;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.resource.XtextResourceSet;
import org.eclipse.xtext.ui.core.editor.model.IXtextDocumentContentObserver.Processor;
import org.eclipse.xtext.ui.core.editor.utils.ValidationJob;
import org.eclipse.xtext.ui.core.util.JdtClasspathUriResolver;
-import org.eclipse.xtext.util.StringInputStream;
import org.eclipse.xtext.validator.CheckMode;
import com.google.inject.Inject;
@@ -45,42 +45,50 @@ import com.google.inject.Provider;
public class XtextDocument extends Document implements IXtextDocument {
private XtextResourceSet resourceSet = null;
+
private XtextResource resource = null;
- private IEditorInput editorInput;
+
private IFile file;
+ private final ListenerList modelListeners = new ListenerList(ListenerList.IDENTITY);
+
+ private final ListenerList xtextDocumentObservers = new ListenerList(ListenerList.IDENTITY);
+
@Inject
private Provider<XtextResourceSet> resourceSetProvider;
public void setInput(IEditorInput editorInput) {
file = ResourceUtil.getFile(editorInput);
- Assert.isTrue(file != null && this.editorInput == null || this.editorInput.equals(editorInput));
- if (this.editorInput != null)
- return;
- this.editorInput = editorInput;
- resourceSet = resourceSetProvider.get();
- IJavaProject javaProject = getIJavaProject(file);
- if (javaProject != null) {
- resourceSet.setClasspathUriResolver(new JdtClasspathUriResolver());
- resourceSet.setClasspathURIContext(javaProject);
+ resourceSet = resourceSetProvider.get();
+ if (file != null) {
+ // TODO find a way to identify a project for an IStorageEditorInput
+ IJavaProject javaProject = getIJavaProject(file);
+ if (javaProject != null) {
+ resourceSet.setClasspathUriResolver(new JdtClasspathUriResolver());
+ resourceSet.setClasspathURIContext(javaProject);
+ }
}
- IPath path = file.getFullPath();
- Resource aResource = resourceSet.createResource(URI.createPlatformResourceURI(path.toString(), true));
- if (!(aResource instanceof XtextResource))
- throw new IllegalStateException("The resource factory registered for " + path
- + " is not an XtextResourceFactory. Make sure the right resource factory has been registered.");
- resource = (XtextResource) aResource;
- if (!resource.isLoaded()) {
+ IPath path = null;
+ if (file != null) {
+ path = file.getFullPath();
+ } else {
+ IStorageEditorInput storageInput = (IStorageEditorInput) editorInput;
try {
- String string = get();
- resource.load(new StringInputStream(string), null);
+ // TODO get the FQN of the resource
+ path = storageInput.getStorage().getFullPath();
}
- catch (IOException e) {
+ catch (CoreException e) {
throw new WrappedException(e);
}
}
+ Resource aResource = resourceSet.createResource(URI.createPlatformResourceURI(path.toString(), true));
+ if (!(aResource instanceof XtextResource))
+ throw new IllegalStateException("The resource factory registered for " + path
+ + " is not an XtextResourceFactory. Make sure the right resource factory has been registered.");
+ resource = (XtextResource) aResource;
+ resource.setValidationDisabled(file == null);
}
public boolean isReferenced(IResource anIResource) {
@@ -98,8 +106,8 @@ public class XtextDocument extends Document implements IXtextDocument {
return uriToRes.containsKey(anIResource.getFullPath().lastSegment());
}
- private IJavaProject getIJavaProject(IFile file) {
- IJavaProject create = JavaCore.create(file.getProject());
+ private IJavaProject getIJavaProject(IResource resource) {
+ IJavaProject create = JavaCore.create(resource.getProject());
if (create.exists())
return create;
return null;
@@ -116,14 +124,11 @@ public class XtextDocument extends Document implements IXtextDocument {
T exec = work.exec(resource);
ensureThatStateIsNotReturned(exec, work);
return exec;
- }
- catch (RuntimeException e) {
+ } catch (RuntimeException e) {
throw e;
- }
- catch (Exception e) {
+ } catch (Exception e) {
throw new WrappedException(e);
- }
- finally {
+ } finally {
readLock.unlock();
}
}
@@ -136,14 +141,11 @@ public class XtextDocument extends Document implements IXtextDocument {
notifyModelListeners(resource);
// TODO track modifications and serialize back to the text buffer
return exec;
- }
- catch (RuntimeException e) {
+ } catch (RuntimeException e) {
throw e;
- }
- catch (Exception e) {
+ } catch (Exception e) {
throw new WrappedException(e);
- }
- finally {
+ } finally {
writeLock.unlock();
checkAndUpdateMarkers();
}
@@ -161,8 +163,6 @@ public class XtextDocument extends Document implements IXtextDocument {
// }
}
- ListenerList modelListeners = new ListenerList(ListenerList.IDENTITY);
-
public void addModelListener(IXtextModelListener listener) {
Assert.isNotNull(listener);
modelListeners.add(listener);
@@ -180,8 +180,6 @@ public class XtextDocument extends Document implements IXtextDocument {
}
}
- private final ListenerList xtextDocumentObservers = new ListenerList(ListenerList.IDENTITY);
-
public void addXtextDocumentContentObserver(IXtextDocumentContentObserver observer) {
addDocumentListener(observer);
xtextDocumentObservers.add(observer);
@@ -208,8 +206,7 @@ public class XtextDocument extends Document implements IXtextDocument {
writeLock.lock();
try {
return modify(transaction);
- }
- finally {
+ } finally {
readLock.lock();
writeLock.unlock();
}
diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/model/XtextDocumentProvider.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/model/XtextDocumentProvider.java
index 638315d..c36d49e 100644
--- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/model/XtextDocumentProvider.java
+++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/model/XtextDocumentProvider.java
@@ -27,7 +27,7 @@ import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.jface.text.IDocument;
-import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.xtext.resource.XtextResource;
@@ -161,13 +161,8 @@ public class XtextDocumentProvider extends FileDocumentProvider {
}
@Override
- public IDocument getDocument(Object element) {
- final XtextDocument document = (XtextDocument) super.getDocument(element);
- if (!(element instanceof IFileEditorInput))
- throw new IllegalArgumentException("Can only handle instances of " + IFileEditorInput.class.getSimpleName()
- + " as input.");
- document.setInput((IFileEditorInput) element);
- return document;
+ protected void setupDocument(Object element, IDocument document) {
+ ((XtextDocument) document).setInput((IEditorInput) element);
}
@Override
diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/reconciler/XtextReconciler.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/reconciler/XtextReconciler.java
index 8adf988..d8a09d2 100644
--- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/reconciler/XtextReconciler.java
+++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/reconciler/XtextReconciler.java
@@ -32,9 +32,9 @@ import org.eclipse.xtext.ui.core.editor.model.XtextDocumentUtil;
* performed for each DR in the queue. We overcome this situation by writing our
* own reconciler that only creates ReplaceRegions which can always be merged,
* such that we have to call the partial parser only once.
- *
+ *
* Additionally, we simplify the reconciler by using the Job API.
- *
+ *
* @author Jan Köhnlein - Initial contribution and API
*/
public class XtextReconciler extends Job implements IReconciler {
@@ -44,9 +44,9 @@ public class XtextReconciler extends Job implements IReconciler {
private boolean isInstalled;
private ITextViewer textViewer;
private TextInputListener textInputListener;
- private DocumentListener documentListener;
+ private final DocumentListener documentListener;
private ReplaceRegion pendingReplaceRegion;
- private Object pendingReplaceRegionLock;
+ private final Object pendingReplaceRegionLock;
private int delay;
private IReconcilingStrategy strategy;
@@ -59,7 +59,7 @@ public class XtextReconciler extends Job implements IReconciler {
public void documentChanged(DocumentEvent event) {
handleDocumentChanged(event);
}
-
+
public void performNecessaryUpdates(Processor processor) {
final IXtextDocument document = XtextDocumentUtil.get(textViewer);
if (document != null) {
@@ -176,8 +176,7 @@ public class XtextReconciler extends Job implements IReconciler {
if (log.isDebugEnabled()) {
log.debug("Preparing reconciliation.");
}
-
- IStatus result = null;
+
final IXtextDocument document = XtextDocumentUtil.get(textViewer);
if (document != null) {
final ReplaceRegion replaceRegionToBeProcessed = getAndResetReplaceRegion();
@@ -186,8 +185,8 @@ public class XtextReconciler extends Job implements IReconciler {
}
}
if (log.isDebugEnabled())
- log.debug("Reconciliation finished. Time required: " + (System.currentTimeMillis() - start));
- return (result != null) ? result : Status.OK_STATUS;
+ log.debug("Reconciliation finished. Time required: " + (System.currentTimeMillis() - start));
+ return Status.OK_STATUS;
}
private ReplaceRegion getAndResetReplaceRegion() {
diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/utils/ValidationJob.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/utils/ValidationJob.java
index 542b7e5..142b82e 100644
--- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/utils/ValidationJob.java
+++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/utils/ValidationJob.java
@@ -26,9 +26,9 @@ import org.eclipse.xtext.ui.core.editor.model.UnitOfWork;
import org.eclipse.xtext.validator.CheckMode;
/**
- *
+ *
* @author Dennis Hübner - Initial contribution and API
- *
+ *
*/
public final class ValidationJob extends Job {
private static final Logger log = Logger.getLogger(ValidationJob.class);
@@ -39,27 +39,25 @@ public final class ValidationJob extends Job {
/**
* Constructs a ValidationJob with a specified {@link CheckMode}
- *
+ *
* @param xtextEditor
* @param checkMode
*/
public ValidationJob(XtextEditor xtextEditor, CheckMode checkMode) {
- this(xtextEditor.getDocument(), (IFile) (IFile.class.isInstance(xtextEditor.getResource()) ? xtextEditor
- .getResource() : null), checkMode);
+ this(xtextEditor.getDocument(), (IFile) (IFile.class.isInstance(xtextEditor.getResource()) ?
+ xtextEditor.getResource() : null), checkMode);
}
/**
* Constructs a ValidationJob with a specified {@link CheckMode}
- *
+ *
* @param xtextDocument
* @param iFile
* @param checkMode
*/
public ValidationJob(IXtextDocument xtextDocument, IFile iFile, CheckMode checkMode) {
super("Xtext validation");
- if (iFile == null) {
- throw new IllegalStateException("IFile should not be null");
- }
+
this.xtextDocument = xtextDocument;
this.iFile = iFile;
this.checkMode = checkMode;
@@ -68,6 +66,10 @@ public final class ValidationJob extends Job {
@Override
protected IStatus run(IProgressMonitor monitor) {
log.debug("Starting Xtext Validation with CheckMode: " + checkMode);
+ if (iFile == null) { // file may be null, if it was opend from an IStorageEditorInput
+ log.debug("Aborting Xtext Validation with CheckMode: " + checkMode + " because file does not exist.");
+ return Status.OK_STATUS;
+ }
final List<Map<String, Object>> issues = xtextDocument.readOnly(new UnitOfWork<List<Map<String, Object>>>() {
public List<Map<String, Object>> exec(XtextResource resource) throws Exception {
return XtextResourceChecker.check(resource, Collections.singletonMap(CheckMode.KEY, checkMode));