Fixed: [ Issue 70 ] Validation doesn't start until editing https://code.google.com/p/protobuf-dt/issues/detail?id=70 Validation now happens every time an editor is activated.
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java index 349492d..89845d8 100644 --- a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/ProtobufUiModule.java
@@ -12,6 +12,7 @@ import static org.eclipse.ui.PlatformUI.isWorkbenchRunning; import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; +import org.eclipse.ui.*; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.eclipse.ui.views.contentoutline.IContentOutlinePage; import org.eclipse.xtext.ui.LanguageSpecific; @@ -27,12 +28,14 @@ import com.google.eclipse.protobuf.ui.editor.hyperlinking.ProtobufHyperlinkDetector; import com.google.eclipse.protobuf.ui.editor.model.ProtobufDocumentProvider; import com.google.eclipse.protobuf.ui.editor.syntaxcoloring.ProtobufSemanticHighlightingCalculator; +import com.google.eclipse.protobuf.ui.internal.ProtobufActivator; import com.google.eclipse.protobuf.ui.outline.*; import com.google.eclipse.protobuf.ui.preferences.PreferenceStoreAccess; import com.google.eclipse.protobuf.ui.preferences.compiler.CompilerPreferenceStoreInitializer; import com.google.eclipse.protobuf.ui.preferences.paths.PathsPreferenceStoreInitializer; import com.google.eclipse.protobuf.ui.scoping.FileUriResolver; -import com.google.inject.Binder; +import com.google.eclipse.protobuf.ui.validation.ValidateOnActivation; +import com.google.inject.*; /** * Use this class to register components to be used within the IDE. @@ -42,9 +45,15 @@ public class ProtobufUiModule extends AbstractProtobufUiModule { public static final String PLUGIN_ID = "com.google.eclipse.protobuf.ui"; - + public ProtobufUiModule(AbstractUIPlugin plugin) { super(plugin); + setValidationTrigger(PlatformUI.getWorkbench().getActiveWorkbenchWindow(), plugin); + } + + private void setValidationTrigger(IWorkbenchWindow w, AbstractUIPlugin plugin) { + if (w == null || !(plugin instanceof ProtobufActivator)) return; + w.getPartService().addPartListener(new ValidateOnActivation()); } @Override public Class<? extends IContentOutlinePage> bindIContentOutlinePage() {
diff --git a/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateOnActivation.java b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateOnActivation.java new file mode 100644 index 0000000..f949ea3 --- /dev/null +++ b/com.google.eclipse.protobuf.ui/src/com/google/eclipse/protobuf/ui/validation/ValidateOnActivation.java
@@ -0,0 +1,106 @@ +/* + * Copyright (c) 2011 Google Inc. + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * + * http://www.eclipse.org/legal/epl-v10.html + */ +package com.google.eclipse.protobuf.ui.validation; + +import static com.google.eclipse.protobuf.protobuf.ProtobufPackage.Literals.IMPORT__IMPORT_URI; +import static org.eclipse.xtext.EcoreUtil2.getAllContentsOfType; + +import com.google.eclipse.protobuf.protobuf.Import; +import com.google.eclipse.protobuf.util.ModelNodes; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.ui.*; +import org.eclipse.ui.part.FileEditorInput; +import org.eclipse.xtext.nodemodel.INode; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.resource.impl.ListBasedDiagnosticConsumer; +import org.eclipse.xtext.ui.editor.XtextEditor; +import org.eclipse.xtext.ui.editor.model.*; +import org.eclipse.xtext.util.concurrent.IUnitOfWork; + +import java.util.List; + +/** + * Validates a .proto file when it is opened or activated. + * + * @author alruiz@google.com (Alex Ruiz) + */ +public class ValidateOnActivation implements IPartListener2 { + + private final ModelNodes nodes = new ModelNodes(); + + public void partActivated(IWorkbenchPartReference partRef) { + final XtextEditor editor = protoEditorFrom(partRef); + if (editor == null) return; + validate(editor); + } + + private XtextEditor protoEditorFrom(IWorkbenchPartReference partRef) { + XtextEditor editor = xtextEditorFrom(partRef); + if (editor == null) return null; + if (!"com.google.eclipse.protobuf.Protobuf".equals(editor.getLanguageName())) return null; + if (!(editor.getEditorInput() instanceof FileEditorInput)) return null; + return editor; + } + + private XtextEditor xtextEditorFrom(IWorkbenchPartReference partRef) { + IWorkbenchPage page = partRef.getPage(); + if (page == null) return null; + IEditorPart activeEditor = page.getActiveEditor(); + return (activeEditor instanceof XtextEditor) ? (XtextEditor) activeEditor : null; + } + + private void validate(XtextEditor editor) { + final IXtextDocument document = editor.getDocument(); + if (!(document instanceof XtextDocument)) return; + document.readOnly(new IUnitOfWork<Void, XtextResource>() { + public java.lang.Void exec(XtextResource resource) throws Exception { + EObject root = resource.getParseResult().getRootASTElement(); + resetImports(root); + resource.getLinker().linkModel(root, new ListBasedDiagnosticConsumer()); + ((XtextDocument) document).checkAndUpdateAnnotations(); + return null; + } + }); + } + + private void resetImports(EObject root) { + List<Import> imports = getAllContentsOfType(root, Import.class); + for (Import anImport : imports) resetUri(anImport); + } + + private void resetUri(Import anImport) { + String uri = uriAsEnteredInEditor(anImport); + if (uri == null) return; + anImport.setImportURI(uri); + } + + private String uriAsEnteredInEditor(Import anImport) { + INode node = nodes.firstNodeForFeature(anImport, IMPORT__IMPORT_URI); + if (node == null) return null; + String text = node.getText(); + if (text == null) return null; + return text.substring(1, text.length() - 1); + } + + public void partBroughtToTop(IWorkbenchPartReference partRef) {} + + public void partClosed(IWorkbenchPartReference partRef) {} + + public void partDeactivated(IWorkbenchPartReference partRef) {} + + public void partOpened(IWorkbenchPartReference partRef) {} + + public void partHidden(IWorkbenchPartReference partRef) {} + + public void partVisible(IWorkbenchPartReference partRef) {} + + public void partInputChanged(IWorkbenchPartReference partRef) {} +}