Java tutorial
/* * Copyright (C) 2012 NS Solutions Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.htmlhifive.tools.jslint.parse; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.script.ScriptException; import org.apache.commons.lang.StringUtils; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Status; import com.htmlhifive.tools.jslint.JSLintPlugin; import com.htmlhifive.tools.jslint.JSLintPluginConstant; import com.htmlhifive.tools.jslint.configure.ConfigBean; import com.htmlhifive.tools.jslint.configure.FilterBean; import com.htmlhifive.tools.jslint.configure.FilterBean.FilterLevel; import com.htmlhifive.tools.jslint.configure.JSLintConfigManager; import com.htmlhifive.tools.jslint.engine.JSChecker; import com.htmlhifive.tools.jslint.engine.JSCheckerErrorBean; import com.htmlhifive.tools.jslint.engine.JSCheckerFactory; import com.htmlhifive.tools.jslint.engine.JSCheckerResult; import com.htmlhifive.tools.jslint.engine.option.CheckOption; import com.htmlhifive.tools.jslint.engine.option.CheckOptionFileWrapper; import com.htmlhifive.tools.jslint.engine.option.CheckOptionFileWrapperFactory; import com.htmlhifive.tools.jslint.engine.option.Engine; import com.htmlhifive.tools.jslint.engine.option.JSHintDefaultOptions; import com.htmlhifive.tools.jslint.logger.JSLintPluginLogger; import com.htmlhifive.tools.jslint.logger.JSLintPluginLoggerFactory; import com.htmlhifive.tools.jslint.messages.Messages; import com.htmlhifive.tools.jslint.util.ConfigBeanUtil; import com.htmlhifive.tools.jslint.util.PluginResourceUtils; /** * JSlint??????. * * @author NS Solutions Corporation * */ public class JsParser implements Parser { /** * . */ private static JSLintPluginLogger logger = JSLintPluginLoggerFactory.getLogger(JsParser.class); /** * js???. */ private static final int TASK_PARSE_JS = 1000; /** * ???. */ private static final int TASK_MARK_VIEW = 600; /** * JS???. */ private static final int TASK_SERCH_JS = 50; /** * JSLint.js????. */ private static final int TASK_LOAD_JSLINT = 50; /** * ???. */ private static final int TASK_ALL = TASK_PARSE_JS + TASK_MARK_VIEW + TASK_SERCH_JS + TASK_LOAD_JSLINT; /** * ?. */ private IProgressMonitor monitor = null; /** * ??(???). */ private IResource resource; /** * ???. */ private ConfigBean bean; /** * ???. */ private int maxerr = 50; /** * . * * @param resource ??. * @param monitor */ public JsParser(IResource resource) { this.resource = resource; IProject project = resource.getProject(); ConfigBean configBean = JSLintConfigManager.getConfigBean(project); if (configBean.isUseOtherProject()) { bean = JSLintConfigManager.getConfigBean( (IProject) PluginResourceUtils.pathToContainer(configBean.getOtherProjectPath())); bean.setExternalLibPathList(configBean.getExternalLibPathList()); bean.setInternalLibPathList(configBean.getInternalLibPathList()); } else { bean = configBean; } logger.debug("use project path : " + bean.getOtherProjectPath()); } @Override public synchronized JsParseResult parse(IProgressMonitor monitor) throws CoreException, InterruptedException { try { ParserManager.replaceCurrentParser(this); this.monitor = monitor; // ? String[] errorMessages = ConfigBeanUtil.checkProperty(bean); if (errorMessages.length > 0) { throwCoreException(IStatus.WARNING, errorMessages); } checkCancel(); monitor.beginTask(Messages.T0000.getText(), TASK_ALL); monitor.subTask(Messages.T0001.getText()); monitor.worked(TASK_SERCH_JS); monitor.subTask(Messages.T0002.getText()); logger.debug("prop file is " + bean.getOptionFilePath()); checkCancel(); // ??,?. checkCancel(); IFile jslintFile = (IFile) ResourcesPlugin.getWorkspace().getRoot().findMember(bean.getJsLintPath()); long parseStart = System.currentTimeMillis(); // ??. checkCancel(); Engine engine = getEngine(jslintFile); // ?? CheckOptionFileWrapper option = null; CheckOption[] newOptions = null; if (StringUtils.isNotEmpty(bean.getOptionFilePath())) { IFile propFile = (IFile) ResourcesPlugin.getWorkspace().getRoot() .findMember(bean.getOptionFilePath()); option = CheckOptionFileWrapperFactory.createCheckOptionFileWrapper(propFile); if (option.getOptions(engine).length != 0) { // ?. String maxerrStr = option.getOption("maxerr", engine.getKey()).getValue(); if (maxerrStr != null) { maxerr = Integer.parseInt(maxerrStr); } CheckOption[] options = option.getEnableOptions(engine); newOptions = handleMaxerr(options); } } logger.debug("jslint file is " + bean.getJsLintPath()); checkCancel(); JSChecker jsLint = JSCheckerFactory.createJSChecker(jslintFile, newOptions); logger.debug("create checker time" + String.valueOf(System.currentTimeMillis() - parseStart)); monitor.worked(TASK_LOAD_JSLINT); monitor.setTaskName(Messages.T0003.getText()); long getLibStart = System.currentTimeMillis(); // ??. JsFileInfo libStr = getLibrary(); logger.debug("get lib time " + String.valueOf(System.currentTimeMillis() - getLibStart)); checkCancel(); // ??. IFile[] jsFiles = getJsFile(); beforeCheck(); // ??. List<JsMarkingSupport> markList = new ArrayList<JsMarkingSupport>(); for (IFile iFile : jsFiles) { checkCancel(); monitor.subTask(Messages.T0006.format(iFile.getName())); logger.debug("targetFile : " + iFile.getName()); JsFileInfo target = null; JsFileInfo fileInfo = new JsFileInfo(iFile); JSCheckerResult result = null; if (libStr != null) { target = libStr.clone(); target.append(fileInfo); } else { target = fileInfo.clone(); } beforeCheckAtFile(iFile); checkCancel(); long parseAtFileStart = System.currentTimeMillis(); result = jsLint.lint(target.getSourceStr()); logger.debug("parse at file time" + String.valueOf(System.currentTimeMillis() - parseAtFileStart)); addMakingList(markList, iFile, result.getErrors(), libStr != null ? libStr.getLineCount() : 0); // ????? monitor.worked(TASK_PARSE_JS / jsFiles.length); } monitor.setTaskName(Messages.T0007.getText()); mark(markList); logger.debug("parse time : " + String.valueOf(System.currentTimeMillis() - parseStart)); monitor.subTask(Messages.T0004.getText()); monitor.done(); ParserManager.clearCurrentParser(); JsParseResult jsParseResult = new JsParseResult(); jsParseResult.setErrorCount(markList.size()); return jsParseResult; } catch (IOException e) { logger.put(Messages.EM0100, e); throw new CoreException(new Status(IStatus.ERROR, JSLintPlugin.PLUGIN_ID, null, e)); } catch (ScriptException e) { throw new CoreException(new Status(IStatus.WARNING, JSLintPlugin.PLUGIN_ID, null, e)); } } /** * ????????. * * @throws InterruptedException . */ private void checkCancel() throws InterruptedException { if (monitor.isCanceled()) { ParserManager.clearCurrentParser(); throw new InterruptedException(); } } /** * ?options?maxerr??.<br> * ??????JSLint????????,<br> * ??????????????maxerr?????? * * @param options . * @return ??. */ private CheckOption[] handleMaxerr(CheckOption[] options) { List<CheckOption> newOptionList = new ArrayList<CheckOption>(); boolean containMaxerr = false; for (CheckOption checkOption : options) { logger.debug("option : " + checkOption.toString()); if ("maxerr".equals(checkOption.getKey())) { checkOption.setValue(String.valueOf(Integer.MAX_VALUE)); containMaxerr = true; } newOptionList.add(checkOption); } if (containMaxerr) { return (CheckOption[]) newOptionList.toArray(new CheckOption[newOptionList.size()]); } // ??????maxerr??. CheckOption maxerrOption = JSHintDefaultOptions.MAXERR.convertToOption(); newOptionList.add(maxerrOption); return (CheckOption[]) newOptionList.toArray(new CheckOption[newOptionList.size()]); } /** * ?Engine??. * * @param jslintFile . * @return Engine. */ private Engine getEngine(IFile jslintFile) { if (JSLintPluginConstant.JS_LINT_NAME.equals(jslintFile.getName())) { return Engine.JSLINT; } else { return Engine.JSHINT; } } /** * parse?????. * * @throws CoreException ?. */ void beforeCheck() throws CoreException { } /** * ?????. * * @param file ?. * @throws CoreException ?. */ void beforeCheckAtFile(IFile file) throws CoreException { file.deleteMarkers(JSLintPluginConstant.JS_TYPE_MARKER, true, IResource.DEPTH_INFINITE); } /** * ???. * * @return . * @throws CoreException ?. */ protected JsFileInfo getLibrary() throws CoreException { return null; } /** * ?Js??. * * @param jsFileList * @return ?Js * @throws CoreException ?. */ protected IFile[] getJsFile() throws CoreException { final List<IFile> jsFileList = new ArrayList<IFile>(); if (resource instanceof IContainer) { IContainer container = (IContainer) resource; // ?js?. container.accept(new IResourceVisitor() { @Override public boolean visit(IResource resource) throws CoreException { if (JSLintPluginConstant.EXTENTION_JS.equals(resource.getFileExtension())) { jsFileList.add((IFile) resource); } return true; } }); } else if (JSLintPluginConstant.EXTENTION_JS.equals(resource.getFileExtension())) { jsFileList.add((IFile) resource); } else { // ??????? throw new AssertionError(); } return (IFile[]) jsFileList.toArray(new IFile[jsFileList.size()]); } /** * CoreExceptin?. * * @param severity . * @param messages . * @throws CoreException CoreException */ private void throwCoreException(int severity, String... messages) throws CoreException { MultiStatus multiStatus = new MultiStatus(JSLintPlugin.PLUGIN_ID, IStatus.OK, Messages.EM0001.getText(), null); for (String string : messages) { IStatus iStatus = new Status(severity, JSLintPlugin.PLUGIN_ID, string, null); multiStatus.add(iStatus); } throw new CoreException(multiStatus); } /** * ???. * * @param list . * @param iFile ?js. * @param errors . * @param startPosition ?. * @throws CoreException . */ private void addMakingList(List<JsMarkingSupport> list, IFile iFile, JSCheckerErrorBean[] errors, int startPosition) throws CoreException { int i = 0; for (JSCheckerErrorBean jsLintError : errors) { if (jsLintError.getLine() > startPosition) { // . FilterLevel revel = matchExcludeFilter(jsLintError.getReason()); if (i < maxerr && !FilterLevel.IGNORE.equals(revel)) { JsMarkingSupport support = new JsMarkingSupport( iFile.createMarker(JSLintPluginConstant.JS_TYPE_MARKER)); support.putMessageAttribute(jsLintError.getReason()); if (FilterLevel.ERROR.equals(revel)) { support.putSeverityAttribute(IMarker.SEVERITY_ERROR); } else { support.putSeverityAttribute(IMarker.SEVERITY_WARNING); } support.putLocationAttribute( Messages.VM0000.format(jsLintError.getLine().intValue() - startPosition)); support.putLineNumAttribute(jsLintError.getLine().intValue() - startPosition); list.add(support); i++; } } } } /** * ???????. * * @param list ?. */ private void mark(List<JsMarkingSupport> list) { int i = 0; int atFile = list.size() / 400; if (atFile == 0) { atFile = 1; } for (JsMarkingSupport jsMarkingSupport : list) { jsMarkingSupport.marking(); i++; if (i % atFile == 0) { monitor.subTask(Messages.T0008.format(i + 1, list.size())); this.monitor.worked(TASK_MARK_VIEW * atFile / list.size()); } } } /** * ???????????. * * @param reason ?. * @return ?????,????null. */ private FilterLevel matchExcludeFilter(String reason) { FilterBean[] filterBeans = bean.getFilterBeans(); FilterLevel revel = null; for (FilterBean filterBean : filterBeans) { if (!filterBean.isState()) { continue; } Pattern pattern = Pattern.compile(filterBean.getRegex()); Matcher matcher = pattern.matcher(reason); // ?????? if (matcher.matches()) { revel = filterBean.getRevel(); if (FilterLevel.IGNORE.equals(revel)) { // ?????. return revel; } } } return revel; } /** * ??(???)??. * * @return ??(???) */ protected IResource getResource() { return resource; } @Override public void cansel() { monitor.setCanceled(true); } /** * ??. * * @return . */ protected ConfigBean getBean() { return bean; } }