/** * Copyright (c) 2013-2016 Angelo ZERR. * 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: * Angelo Zerr <angelo.zerr@gmail.com> - initial API and implementation */ package tern.eclipse.ide.linter.internal.core.validation; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.wst.validation.AbstractValidator; import org.eclipse.wst.validation.ValidationResult; import org.eclipse.wst.validation.ValidationState; import org.eclipse.wst.validation.internal.core.ValidationException; 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; import tern.TernResourcesManager; import tern.eclipse.ide.core.IIDETernProject; import tern.eclipse.ide.core.IIDETernScriptPathReporter; import tern.eclipse.ide.core.IScopeContext; import tern.eclipse.ide.core.TernCorePlugin; import tern.eclipse.ide.linter.core.validation.TernValidationHelper; import tern.eclipse.ide.linter.internal.core.Trace; /** * WTP Tern Validator V2 to validate JavaScript (HTML, JSP, JS etc files). This * validator can be called when project is Build or Validate at hand (with * Validate context menu). * */ public class TernValidator extends AbstractValidator implements IValidatorJob { private static final String TERN_VALIDATOR_CONTEXT = "tern.eclipse.ide.linter.core.validatorContext"; //$NON-NLS-1$ /** * Perform the validation using version 2 of the validation framework. */ @Override public ValidationResult validate(IResource resource, int kind, ValidationState state, IProgressMonitor monitor) { ValidationResult result = new ValidationResult(); TernValidatorContext context = getTernContext(state, false); if (context != null) { // It's a tern project IIDETernProject ternProject = context.getTernProject(); if (isInScope(resource, ternProject, context)) { IReporter reporter = result.getReporter(monitor); // Validate is called for each file, the synchronization of tern // file must be done for : // 1) the first JavaScript file which must be validated. // 2) for any HTML file because it is deleted from the tern // server. boolean jsFile = TernResourcesManager.isJSFile(resource); boolean synch = !jsFile || context.isSynch(); TernValidationHelper.validate(resource, ternProject, true, synch, false, reporter, this); if (jsFile) { context.setSynch(false); } } } return result; } private boolean isInScope(IResource resource, IIDETernProject ternProject, IScopeContext context) { boolean inScope = ternProject.isInScope(resource, context); IIDETernScriptPathReporter reporter = ternProject.getScriptPathReporter(); if (reporter != null) { reporter.validate(resource.getFullPath(), inScope); } return inScope; } @Override public void validationStarting(IProject project, ValidationState state, IProgressMonitor monitor) { if (project != null && TernCorePlugin.hasTernNature(project)) { try { IIDETernProject ternProject = TernCorePlugin.getTernProject(project, false); if (ternProject.getLinters().length > 0) { TernValidatorContext context = getTernContext(state, true); setupValidation(context, ternProject); state.put(TERN_VALIDATOR_CONTEXT, context); super.validationStarting(project, state, monitor); } } catch (CoreException e) { Trace.trace(Trace.SEVERE, "Error while tern start validation.", e); } } } @Override public void validationFinishing(IProject project, ValidationState state, IProgressMonitor monitor) { if (project != null && TernCorePlugin.hasTernNature(project)) { super.validationFinishing(project, state, monitor); TernValidatorContext context = getTernContext(state, false); if (context != null) { state.put(TERN_VALIDATOR_CONTEXT, null); } } } @Override public void cleanup(IReporter reporter) { // do nothing } @Override public void validate(IValidationContext context, IReporter reporter) throws ValidationException { // It seems that it is never called? } @Override public ISchedulingRule getSchedulingRule(IValidationContext context) { return null; } @Override public IStatus validateInJob(IValidationContext helper, IReporter reporter) throws ValidationException { IStatus status = Status.OK_STATUS; validate(helper, reporter); return status; } protected void setupValidation(TernValidatorContext context, IIDETernProject ternProject) { context.setTernProject(ternProject); } /** * Get the nested validation context. * * @param state * the validation state. * @param create * when true, a new context will be created if one is not found * @return the nested validation context. */ protected TernValidatorContext getTernContext(ValidationState state, boolean create) { TernValidatorContext context = (TernValidatorContext) state.get(TERN_VALIDATOR_CONTEXT); if (context != null) { return context; } if (create) { return new TernValidatorContext(); } return null; } }