Bug 481344 - JSDT should support the use of sourcevalidation extension point
JSDT is made to support "org.eclipse.wst.sse.ui.sourcevalidation" extention point for As-You-Type validation.
Change-Id: I89d8d24b34fba84fd219ccc2df945cbee01efed3
Signed-off-by: Victor Rubezhny <vrubezhny@exadel.com>
diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/esprima/EsprimaParser.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/esprima/EsprimaParser.java
index 6f1cab2..18e86b5 100644
--- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/esprima/EsprimaParser.java
+++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/esprima/EsprimaParser.java
@@ -236,6 +236,7 @@
String description = (String) error.getMember("description"); //$NON-NLS-1$
Number index = (Number) error.getMember("index"); //$NON-NLS-1$
Number line = (Number) error.getMember("lineNumber"); //$NON-NLS-1$
+ Number column = (Number) error.getMember("column"); //$NON-NLS-1$
char[] fileName = null;
if(unit != null){
@@ -248,10 +249,10 @@
0,
null,
ProblemSeverities.Error,
- 0,
- 0,
+ index.intValue(),
+ -1,
line.intValue(),
- index.intValue());
+ column.intValue());
return result;
}
diff --git a/bundles/org.eclipse.wst.jsdt.ui/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.jsdt.ui/META-INF/MANIFEST.MF
index 08c662b..9d326b1 100644
--- a/bundles/org.eclipse.wst.jsdt.ui/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.wst.jsdt.ui/META-INF/MANIFEST.MF
@@ -3,7 +3,13 @@
Bundle-Version: 2.0.0.qualifier
Bundle-Activator: org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin
Import-Package: com.ibm.icu.text,
- com.ibm.icu.util
+ com.ibm.icu.util,
+ org.eclipse.wst.sse.core.utils,
+ org.eclipse.wst.sse.ui.internal.reconcile.validator,
+ org.eclipse.wst.validation,
+ org.eclipse.wst.validation.internal.core,
+ org.eclipse.wst.validation.internal.operations,
+ org.eclipse.wst.validation.internal.provisional.core
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
@@ -128,7 +134,10 @@
org.eclipse.ui.forms;bundle-version="[3.4.0,4.0.0)",
org.eclipse.ui.navigator;bundle-version="[3.4.0,4.0.0)",
org.eclipse.ui.navigator.resources;bundle-version="[3.4.0,4.0.0)",
- org.eclipse.wst.jsdt.manipulation;bundle-version="[1.0.200,2.0.0)"
+ org.eclipse.wst.jsdt.manipulation;bundle-version="[1.0.200,2.0.0)",
+ org.eclipse.wst.sse.core;bundle-version="1.1.1000",
+ org.eclipse.wst.sse.ui;bundle-version="1.3.500",
+ org.eclipse.core.filebuffers
Eclipse-LazyStart: true
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-Localization: plugin
diff --git a/bundles/org.eclipse.wst.jsdt.ui/plugin.xml b/bundles/org.eclipse.wst.jsdt.ui/plugin.xml
index 5db8ccb..8c485ad 100644
--- a/bundles/org.eclipse.wst.jsdt.ui/plugin.xml
+++ b/bundles/org.eclipse.wst.jsdt.ui/plugin.xml
@@ -6012,4 +6012,22 @@
</stylesheet>
</extension>
+
+ <!--======================================================================================-->
+ <!-- As you type validation -->
+ <!--======================================================================================-->
+
+ <extension point="org.eclipse.wst.sse.ui.sourcevalidation">
+ <validator
+ scope="total"
+ class="org.eclipse.wst.jsdt.internal.validation.JSDTSourceValidator"
+ id="org.eclipse.wst.jsdt.ui.internal.validation.jsdtsyntaxvalidator">
+ <contentTypeIdentifier
+ id="org.eclipse.wst.jsdt.core.jsSource">
+ <partitionType id="__dftl_partition_content_type" />
+ <partitionType id="__java_string" />
+ </contentTypeIdentifier>
+ </validator>
+ </extension>
+
</plugin>
diff --git a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/JavaCompositeReconcilingStrategy.java b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/JavaCompositeReconcilingStrategy.java
index 009efdb..bb905f4 100644
--- a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/JavaCompositeReconcilingStrategy.java
+++ b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/JavaCompositeReconcilingStrategy.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
* 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
@@ -20,7 +20,8 @@
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
import org.eclipse.wst.jsdt.internal.ui.text.java.IProblemRequestorExtension;
-import org.eclipse.wst.jsdt.internal.ui.text.java.JavaReconcilingStrategy;
+//import org.eclipse.wst.jsdt.internal.ui.text.java.JavaReconcilingStrategy;
+import org.eclipse.wst.jsdt.internal.ui.text.java.JavascriptValidationStrategy;
import org.eclipse.wst.jsdt.internal.ui.text.spelling.JavaSpellingReconcileStrategy;
import org.eclipse.wst.jsdt.ui.text.IJavaScriptPartitions;
@@ -31,7 +32,8 @@
public class JavaCompositeReconcilingStrategy extends CompositeReconcilingStrategy {
private ITextEditor fEditor;
- private JavaReconcilingStrategy fJavaStrategy;
+// private JavaReconcilingStrategy fJavaStrategy;
+ private JavascriptValidationStrategy fJavascriptValidationStrategy;
/**
* Creates a new Java reconciling strategy.
@@ -42,9 +44,11 @@
*/
public JavaCompositeReconcilingStrategy(ISourceViewer viewer, ITextEditor editor, String documentPartitioning) {
fEditor= editor;
- fJavaStrategy= new JavaReconcilingStrategy(editor);
+// fJavaStrategy= new JavaReconcilingStrategy(editor);
+ fJavascriptValidationStrategy = new JavascriptValidationStrategy(viewer);
setReconcilingStrategies(new IReconcilingStrategy[] {
- fJavaStrategy,
+// fJavaStrategy,
+ fJavascriptValidationStrategy,
new JavaSpellingReconcileStrategy(viewer, EditorsUI.getSpellingService(), IJavaScriptPartitions.JAVA_PARTITIONING)
});
}
@@ -106,7 +110,7 @@
* @param notify <code>true</code> if listeners should be notified
*/
public void notifyListeners(boolean notify) {
- fJavaStrategy.notifyListeners(notify);
+// fJavaStrategy.notifyListeners(notify);
}
/*
@@ -132,7 +136,7 @@
*
*/
public void aboutToBeReconciled() {
- fJavaStrategy.aboutToBeReconciled();
-
+// fJavaStrategy.aboutToBeReconciled();
+ fJavascriptValidationStrategy.aboutToBeReconciled();
}
}
diff --git a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavascriptValidationStrategy.java b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavascriptValidationStrategy.java
new file mode 100644
index 0000000..877f140
--- /dev/null
+++ b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/ui/text/java/JavascriptValidationStrategy.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2016 RedHat, 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
+ *
+ * Contributors:
+ * RedHat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.ui.text.java;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.filebuffers.ITextFileBufferManager;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.content.IContentType;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.reconciler.DirtyRegion;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
+import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.wst.jsdt.internal.ui.JavaScriptPlugin;
+import org.eclipse.wst.jsdt.ui.JavaScriptUI;
+import org.eclipse.wst.jsdt.ui.text.IJavaScriptPartitions;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorBuilder;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorMetaData;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorStrategy;
+
+/**
+ * @author V.V. Rubezhny
+ *
+ */
+public class JavascriptValidationStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension {
+ private static final boolean DEBUG_VALIDATORS = Boolean.TRUE.toString().equalsIgnoreCase(Platform.getDebugOption("org.eclipse.wst.jsdt.ui/debug/reconcilerValidators")); //$NON-NLS-1$
+ private final String SSE_UI_ID = "org.eclipse.wst.sse.ui"; //$NON-NLS-1$
+
+ private IDocument fDocument;
+ private ValidatorStrategy fValidatorStrategy;
+ /**
+ * true if as you type validation is enabled,
+ * false otherwise
+ * @TODO: do we need a preference for this???
+ */
+ private boolean fValidationEnabled = true;
+ private ISourceViewer fSourceViewer;
+
+ /**
+ * @param editor
+ */
+ public JavascriptValidationStrategy(ISourceViewer viewer) {
+ this.fSourceViewer = viewer;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#setDocument(org.eclipse.jface.text.IDocument)
+ */
+ public void setDocument(IDocument document) {
+ this.fDocument = document;
+ if (getValidatorStrategy() != null) {
+ getValidatorStrategy().setDocument(document);
+ }
+ }
+
+ private IDocument getDocument() {
+ return fDocument;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion, org.eclipse.jface.text.IRegion)
+ */
+ public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
+ reconcile(dirtyRegion);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
+ */
+ public void reconcile(IRegion partition) {
+ ITypedRegion[] partitions = computePartitioning(partition);
+
+ // call the validator strategy once for each effected partition
+ DirtyRegion dirty = null;
+ for (int i = 0; i < partitions.length; i++) {
+ dirty = createDirtyRegion(partitions[i], DirtyRegion.INSERT);
+
+ // [source]validator (extension) for this partition
+ if (getValidatorStrategy() != null) {
+ getValidatorStrategy().reconcile(partitions[i], dirty);
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#setProgressMonitor(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ public void setProgressMonitor(IProgressMonitor monitor) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#initialReconcile()
+ */
+ public void initialReconcile() {
+ int length = getDocument().getLength();
+ reconcile(new Region(0, length));
+ }
+
+ /**
+ * Called before reconciling is started.
+ *
+ *
+ */
+ public void aboutToBeReconciled() {
+ if (getValidatorStrategy() != null) {
+ getValidatorStrategy().beginProcessing();
+ }
+ }
+
+ /**
+ * @param dirtyRegion
+ * @return
+ */
+ protected ITypedRegion[] computePartitioning(IRegion dirtyRegion) {
+ int drOffset = dirtyRegion.getOffset();
+ int drLength = dirtyRegion.getLength();
+
+ return computePartitioning(drOffset, drLength);
+ }
+
+
+ protected ITypedRegion[] computePartitioning(int drOffset, int drLength) {
+ ITypedRegion[] tr = new ITypedRegion[0];
+ IDocument doc = getDocument();
+ if (doc != null){
+ int docLength = doc.getLength();
+
+ if (drOffset > docLength) {
+ drOffset = docLength;
+ drLength = 0;
+ }
+ else if (drOffset + drLength > docLength) {
+ drLength = docLength - drOffset;
+ }
+
+ try {
+ // dirty region may span multiple partitions
+ tr = TextUtilities.computePartitioning(doc, getDocumentPartitioning(), drOffset, drLength, true);
+ }
+ catch (BadLocationException e) {
+ String info = "dr: [" + drOffset + ":" + drLength + "] doc: [" + docLength + "] "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ IStatus status= new Status(IStatus.ERROR, JavaScriptUI.ID_PLUGIN, IStatus.OK, info, e);
+ JavaScriptPlugin.getDefault().getLog().log(status);
+ tr = new ITypedRegion[0];
+ }
+ }
+ return tr;
+ }
+
+ protected DirtyRegion createDirtyRegion(IRegion region, String type) {
+ return createDirtyRegion(region.getOffset(), region.getLength(), type);
+ }
+
+ protected DirtyRegion createDirtyRegion(int offset, int length, String type) {
+ DirtyRegion durty = null;
+ IDocument doc = getDocument();
+
+ if (doc != null) {
+ // safety for BLE
+ int docLen = doc.getLength();
+ if (offset > docLen) {
+ offset = docLen;
+ length = 0;
+ }
+ else if (offset + length >= docLen)
+ length = docLen - offset;
+ try {
+ durty = new DirtyRegion(offset, length, type, doc.get(offset, length));
+ }
+ catch (BadLocationException e) {
+ String info = "dr: [" + offset + ":" + length + "] doc: [" + docLen + "] "; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ IStatus status= new Status(IStatus.ERROR, JavaScriptUI.ID_PLUGIN, IStatus.OK, info, e);
+ JavaScriptPlugin.getDefault().getLog().log(status);
+ }
+ }
+ return durty;
+ }
+
+ protected String getDocumentPartitioning() {
+ return IJavaScriptPartitions.JAVA_PARTITIONING;
+ }
+
+ protected ISourceViewer getTextViewer() {
+ return fSourceViewer;
+ }
+
+ /**
+ * @return Returns the ValidatorStrategy.
+ */
+ protected ValidatorStrategy getValidatorStrategy() {
+ ValidatorStrategy validatorStrategy = null;
+ if (fValidatorStrategy == null && fValidationEnabled) {
+ if (getTextViewer() instanceof ISourceViewer) {
+ ISourceViewer viewer = (ISourceViewer) getTextViewer();
+ String contentTypeId = getContentType();
+
+ if (contentTypeId != null) {
+ validatorStrategy = new ValidatorStrategy(viewer, contentTypeId);
+ ValidatorBuilder vBuilder = new ValidatorBuilder();
+ ValidatorMetaData[] vmds = vBuilder.getValidatorMetaData(SSE_UI_ID);
+ List enabledValidators = new ArrayList(1);
+ /* if any "must" handle this content type, just add them */
+ boolean foundSpecificContentTypeValidators = false;
+ for (int i = 0; i < vmds.length; i++) {
+ if (vmds[i].mustHandleContentType(contentTypeId)) {
+ if (DEBUG_VALIDATORS) {
+ String info = contentTypeId + " using specific validator " + vmds[i].getValidatorId(); //$NON-NLS-1$
+ IStatus status= new Status(IStatus.INFO, JavaScriptUI.ID_PLUGIN, info);
+ JavaScriptPlugin.getDefault().getLog().log(status);
+ }
+ foundSpecificContentTypeValidators = true;
+ enabledValidators.add(vmds[i]);
+ }
+ }
+ if (!foundSpecificContentTypeValidators) {
+ for (int i = 0; i < vmds.length; i++) {
+ if (vmds[i].canHandleContentType(contentTypeId)) {
+ if (DEBUG_VALIDATORS) {
+ String info = contentTypeId + " using inherited(?) validator " + vmds[i].getValidatorId(); //$NON-NLS-1$
+ IStatus status= new Status(IStatus.INFO, JavaScriptUI.ID_PLUGIN, info);
+ JavaScriptPlugin.getDefault().getLog().log(status);
+ }
+ enabledValidators.add(vmds[i]);
+ }
+ }
+ }
+ for (int i = 0; i < enabledValidators.size(); i++) {
+ validatorStrategy.addValidatorMetaData((ValidatorMetaData) enabledValidators.get(i));
+ }
+ }
+ }
+ fValidatorStrategy = validatorStrategy;
+ } else if(fValidatorStrategy != null && fValidationEnabled) {
+ validatorStrategy = fValidatorStrategy;
+ }
+ return validatorStrategy;
+ }
+
+ private String getContentType() {
+ IDocument doc = getDocument();
+ if (doc == null)
+ return null;
+
+ ITextFileBufferManager textFileBufferManager = FileBuffers.getTextFileBufferManager();
+ if (textFileBufferManager != null) {
+ ITextFileBuffer textFileBuffer = textFileBufferManager.getTextFileBuffer(doc);
+ if (textFileBuffer != null && textFileBuffer.getLocation() != null) {
+ try {
+ IContentType ct = textFileBuffer.getContentType();
+ if (ct != null)
+ return ct.getId();
+ } catch (CoreException e) {
+ // Ignore;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/validation/JSDTSourceValidator.java b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/validation/JSDTSourceValidator.java
new file mode 100644
index 0000000..7495366
--- /dev/null
+++ b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/validation/JSDTSourceValidator.java
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Copyright (c) 2016 RedHat, 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
+ *
+ * Contributors:
+ * RedHat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wst.jsdt.internal.validation;
+
+import java.util.Locale;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.wst.jsdt.core.compiler.CategorizedProblem;
+import org.eclipse.wst.jsdt.core.dom.AST;
+import org.eclipse.wst.jsdt.core.dom.ASTParser;
+import org.eclipse.wst.jsdt.core.dom.JavaScriptUnit;
+import org.eclipse.wst.jsdt.internal.compiler.problem.DefaultProblem;
+import org.eclipse.wst.jsdt.ui.JavaScriptUI;
+import org.eclipse.wst.sse.core.utils.StringUtils;
+import org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator;
+import org.eclipse.wst.validation.AbstractValidator;
+import org.eclipse.wst.validation.ValidationResult;
+import org.eclipse.wst.validation.internal.core.Message;
+import org.eclipse.wst.validation.internal.core.ValidationException;
+import org.eclipse.wst.validation.internal.operations.IWorkbenchContext;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
+import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
+import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob;
+
+/**
+ * @author V.V. Rubezhny
+ *
+ */
+public class JSDTSourceValidator extends AbstractValidator implements IValidatorJob, IExecutableExtension, ISourceValidator {
+ private static final ASTParser parser = ASTParser.newParser(AST.JLS3);
+
+ private String[] fAdditionalContentTypesIDs = null;
+ private IDocument fDocument;
+
+ static boolean shouldValidate(IFile file) {
+ IResource resource = file;
+ do {
+ if (resource.isDerived() || resource.isTeamPrivateMember() || !resource.isAccessible()
+ || (resource.getName().charAt(0) == '.' && resource.getType() == IResource.FOLDER)) {
+ return false;
+ }
+ resource = resource.getParent();
+ } while ((resource.getType() & IResource.PROJECT) == 0);
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.validation.internal.provisional.core.IValidator#cleanup(org.eclipse.wst.validation.internal.provisional.core.IReporter)
+ */
+ public void cleanup(IReporter reporter) {
+ // Nothing to do
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.validation.internal.provisional.core.IValidator#validate(org.eclipse.wst.validation.internal.provisional.core.IValidationContext, org.eclipse.wst.validation.internal.provisional.core.IReporter)
+ */
+ public void validate(IValidationContext helper, IReporter reporter) throws ValidationException {
+ if (helper == null)
+ return;
+ if ((reporter != null) && (reporter.isCancelled() == true)) {
+ throw new OperationCanceledException();
+ }
+ String[] deltaArray = helper.getURIs();
+ if (deltaArray != null && deltaArray.length > 0) {
+ validateDelta(helper, reporter);
+ } else {
+ validateFull(helper, reporter);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ fAdditionalContentTypesIDs = new String[0];
+ if (data instanceof String && data.toString().length() > 0) {
+ fAdditionalContentTypesIDs = StringUtils.unpack(data.toString());
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.validation.internal.provisional.core.IValidatorJob#validateInJob(org.eclipse.wst.validation.internal.provisional.core.IValidationContext, org.eclipse.wst.validation.internal.provisional.core.IReporter)
+ */
+ public IStatus validateInJob(IValidationContext helper, IReporter reporter) throws ValidationException {
+ IStatus status = Status.OK_STATUS;
+ validate(helper, reporter);
+ return status;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.validation.internal.provisional.core.IValidatorJob#getSchedulingRule(org.eclipse.wst.validation.internal.provisional.core.IValidationContext)
+ */
+ public ISchedulingRule getSchedulingRule(IValidationContext helper) {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator#connect(org.eclipse.jface.text.IDocument)
+ */
+ public void connect(IDocument document) {
+ fDocument = document;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator#disconnect(org.eclipse.jface.text.IDocument)
+ */
+ public void disconnect(IDocument document) {
+ fDocument = null;
+ }
+
+ /* (non-Javadoc)
+ *
+ * This validate call is for the ISourceValidator partial document validation approach
+ *
+ * @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator#validate(org.eclipse.jface.text.IRegion, org.eclipse.wst.validation.internal.provisional.core.IValidationContext, org.eclipse.wst.validation.internal.provisional.core.IReporter)
+ */
+ public void validate(IRegion dirtyRegion, IValidationContext helper, IReporter reporter) {
+ if (helper == null || fDocument == null)
+ return;
+
+ if ((reporter != null) && (reporter.isCancelled() == true)) {
+ throw new OperationCanceledException();
+ }
+
+ // TODO Do region validation here
+ }
+
+ /**
+ */
+ private void validateContainer(IValidationContext helper, IReporter reporter, IContainer container) {
+ try {
+ IResource[] resourceArray = container.members(false);
+ for (int i = 0; i < resourceArray.length; i++) {
+ IResource resource = resourceArray[i];
+ if (resource == null || reporter.isCancelled())
+ continue;
+
+ if (resource instanceof IFile) {
+ Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, resource.getFullPath().toString()
+ .substring(1));
+ reporter.displaySubtask(this, message);
+ validateFile(helper, reporter, (IFile) resource, null);
+ } else if (resource instanceof IContainer) {
+ validateContainer(helper, reporter, (IContainer) resource);
+ }
+ }
+ }
+ catch (CoreException ex) {
+ }
+ }
+
+ /**
+ */
+ private void validateDelta(IValidationContext helper, IReporter reporter) {
+ String[] deltaArray = helper.getURIs();
+ for (int i = 0; i < deltaArray.length; i++) {
+ String delta = deltaArray[i];
+ if (delta == null)
+ continue;
+
+ if (reporter != null) {
+ Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, delta.substring(1));
+ reporter.displaySubtask(this, message);
+ }
+
+ IResource resource = getResource(delta);
+ if (resource == null || !(resource instanceof IFile))
+ continue;
+ validateFile(helper, reporter, (IFile) resource, null);
+ }
+ }
+
+ /**
+ * @param result
+ */
+ private void validateFile(IValidationContext helper, IReporter reporter, IFile file, ValidationResult result) {
+ if ((reporter != null) && (reporter.isCancelled() == true)) {
+ throw new OperationCanceledException();
+ }
+ if (!shouldValidate(file)) {
+ return;
+ }
+
+ char[] source = fDocument.get().toCharArray();
+ if (source == null) {
+ return;
+ }
+
+ parser.setSource(source);
+ JavaScriptUnit unit = (JavaScriptUnit) parser.createAST(new NullProgressMonitor());
+ if(unit.getProblems().length > 0){
+ CategorizedProblem[] resourceProblems = (CategorizedProblem[]) unit.getProblems();
+ for (CategorizedProblem problem : resourceProblems) {
+
+ final String msg = problem.getMessage();
+ String[] arguments = problem.getArguments();
+ int severity = problem.isError() ? IMessage.HIGH_SEVERITY : IMessage.ERROR_AND_WARNING;
+ int lineNumber = problem.getSourceLineNumber();
+ int sourceStart = problem.getSourceStart();
+ int sourceEnd = problem.getSourceEnd();
+ int columnNumber = (problem instanceof DefaultProblem) ? ((DefaultProblem)problem).getSourceColumnNumber() : -1;
+
+ Message valMessage = new Message(JavaScriptUI.ID_PLUGIN, severity, JavaScriptUI.ID_PLUGIN + ".problem" ) {
+ /**
+ * @see IMessage#getText(Locale, ClassLoader)
+ */
+ public java.lang.String getText(Locale locale, ClassLoader classLoader) {
+ return msg;
+ }
+
+ };
+ Position position = sourceEnd == -1 ? calcPosition(source, sourceStart) : new Position(sourceStart, sourceEnd - sourceStart);
+
+ valMessage.setOffset(position.getOffset());
+ valMessage.setLength(position.getLength());
+ valMessage.setLineNo(lineNumber);
+// System.out.println(getClass().getName() + ": " + valMessage.getLineNumber() +
+// "[" + valMessage.getOffset() + ":" + valMessage.getLength() + "] : " +
+// valMessage.getText() +
+// "==>>>" + String.copyValueOf(source, position.getOffset(), position.getLength()) + "<<<==");
+ reporter.addMessage(this, valMessage);
+ }
+ }
+ }
+
+ private Position calcPosition(char[] source, int offset) {
+ int start = offset;
+ int end = offset;
+
+ // Search forward
+ while (source.length > end &&
+ (Character.isLetterOrDigit(source[end]) || source[end] == '_')) {
+ end++;
+ }
+ if (end == start) {
+ // search backward
+
+ // skip end of statement && spaces
+ boolean acceptSemiColon = true;
+ while (end > 0 &&
+ ((acceptSemiColon && source[end - 1] == ';') ||
+ Character.isWhitespace(source[end - 1]))) {
+ if (source[end - 1] == ';') {
+ acceptSemiColon = false;
+ }
+ end--;
+ }
+ start = end;
+ while (start > 0 &&
+ (Character.isLetterOrDigit(source[start - 1]) || source[start - 1] == '_')) {
+ start--;
+ }
+ }
+
+ return new Position(start, end - start);
+ }
+
+ /**
+ */
+ private void validateFull(IValidationContext helper, IReporter reporter) {
+ IProject project = null;
+ String[] fileDelta = helper.getURIs();
+ if (helper instanceof IWorkbenchContext) {
+ IWorkbenchContext wbHelper = (IWorkbenchContext) helper;
+ project = wbHelper.getProject();
+ } else if (fileDelta.length > 0) {
+ // won't work for project validation (b/c nothing in file delta)
+ project = getResource(fileDelta[0]).getProject();
+ }
+
+ if (project == null)
+ return;
+ validateContainer(helper, reporter, project);
+ }
+
+ /*
+ * added to get rid or dependency on IWorkbenchHelper
+ */
+ public IResource getResource(String delta) {
+ Path path = new Path(delta);
+ if (path.segmentCount() > 1)
+ return ResourcesPlugin.getWorkspace().getRoot().getFile(path);
+ if (path.segmentCount() == 1)
+ return ResourcesPlugin.getWorkspace().getRoot().getProject(delta);
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/validation/LocalizedMessage.java b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/validation/LocalizedMessage.java
new file mode 100644
index 0000000..a36f9cf
--- /dev/null
+++ b/bundles/org.eclipse.wst.jsdt.ui/src/org/eclipse/wst/jsdt/internal/validation/LocalizedMessage.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2016 RedHat, 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
+ *
+ * Contributors:
+ * RedHat, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.wst.jsdt.internal.validation;
+
+import java.util.Locale;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.wst.validation.internal.core.Message;
+
+/**
+ * copied from org.eclipse.wst.validation.internal.operations.LocalizedMessage
+ *
+ * This class is provided for validators which run only in Eclipse and whose messages, because they
+ * come from another tool, are already localized. LocalizedMessage cannot be used by any validator
+ * which needs to run in both WebSphere and Eclipse.
+ */
+public class LocalizedMessage extends Message {
+ private String _message = null;
+
+ public LocalizedMessage(int severity, String messageText) {
+ this(severity, messageText, null);
+ }
+
+ public LocalizedMessage(int severity, String messageText, IResource targetObject) {
+ this(severity, messageText, (Object) targetObject);
+ }
+
+ public LocalizedMessage(int severity, String messageText, Object targetObject) {
+ super(null, severity, null);
+ setLocalizedMessage(messageText);
+ setTargetObject(targetObject);
+ }
+
+ public void setLocalizedMessage(String message) {
+ _message = message;
+ }
+
+ public String getLocalizedMessage() {
+ return _message;
+ }
+
+ public String getText() {
+ return getLocalizedMessage();
+ }
+
+ public String getText(ClassLoader cl) {
+ return getLocalizedMessage();
+ }
+
+ public String getText(Locale l) {
+ return getLocalizedMessage();
+ }
+
+ public String getText(Locale l, ClassLoader cl) {
+ return getLocalizedMessage();
+ }
+}