[pmd-devel] pmd-eclipse/src/net/sourceforge/pmd/eclipse DeleteLineFix.java,1.1,1.2 MarkerInfo.java,1
A source code analyzer
Brought to you by:
adangel,
juansotuyo
From: Philippe H. <phh...@us...> - 2003-11-30 22:57:47
|
Update of /cvsroot/pmd/pmd-eclipse/src/net/sourceforge/pmd/eclipse In directory sc8-pr-cvs1:/tmp/cvs-serv24646/src/net/sourceforge/pmd/eclipse Modified Files: ASTWriterImpl.java PMDEclipseException.java PMDProcessor.java RuleSetWriterImpl.java PMDPlugin.java PMDDeltaVisitor.java PMDConstants.java PMDVisitorRunner.java PMDVisitor.java Added Files: DeleteLineFix.java MarkerInfo.java PMDResolutionGenerator.java PMDAbstractVisitor.java PMDResolution.java Log Message: Merging from eclipse-v2 development branch Index: ASTWriterImpl.java =================================================================== RCS file: /cvsroot/pmd/pmd-eclipse/src/net/sourceforge/pmd/eclipse/ASTWriterImpl.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** ASTWriterImpl.java 30 Oct 2003 23:36:29 -0000 1.2 --- ASTWriterImpl.java 30 Nov 2003 22:57:43 -0000 1.3 *************** *** 1,19 **** ! /* ! * <copyright> Copyright 1997-2003 PMD for Eclipse Development team under ! * sponsorship of the Defense Advanced Research Projects Agency (DARPA). ! * ! * This program is free software; you can redistribute it and/or modify it ! * under the terms of the Cougaar Open Source License as published by DARPA on ! * the Cougaar Open Source Website (www.cougaar.org). ! * ! * THE COUGAAR SOFTWARE AND ANY DERIVATIVE SUPPLIED BY LICENSOR IS PROVIDED "AS ! * IS" WITHOUT WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING ! * (BUT NOT LIMITED TO) ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ! * FOR A PARTICULAR PURPOSE, AND WITHOUT ANY WARRANTIES AS TO NON-INFRINGEMENT. ! * IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, SPECIAL, ! * INDIRECT OR CONSEQUENTIAL DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE OF ! * DATA OR PROFITS, TORTIOUS CONDUCT, ARISING OUT OF OR IN CONNECTION WITH THE ! * USE OR PERFORMANCE OF THE COUGAAR SOFTWARE. ! * * </copyright> */ --- 1,22 ---- ! /* ! * <copyright> ! * Copyright 1997-2003 PMD for Eclipse Development team ! * under sponsorship of the Defense Advanced Research Projects ! * Agency (DARPA). ! * ! * This program is free software; you can redistribute it and/or modify ! * it under the terms of the Cougaar Open Source License as published by ! * DARPA on the Cougaar Open Source Website (www.cougaar.org). ! * ! * THE COUGAAR SOFTWARE AND ANY DERIVATIVE SUPPLIED BY LICENSOR IS ! * PROVIDED "AS IS" WITHOUT WARRANTIES OF ANY KIND, WHETHER EXPRESS OR ! * IMPLIED, INCLUDING (BUT NOT LIMITED TO) ALL IMPLIED WARRANTIES OF ! * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND WITHOUT ! * ANY WARRANTIES AS TO NON-INFRINGEMENT. IN NO EVENT SHALL COPYRIGHT ! * HOLDER BE LIABLE FOR ANY DIRECT, SPECIAL, INDIRECT OR CONSEQUENTIAL ! * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE OF DATA OR PROFITS, ! * TORTIOUS CONDUCT, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ! * PERFORMANCE OF THE COUGAAR SOFTWARE. ! * * </copyright> */ *************** *** 52,62 **** * * $Log$ ! * Revision 1.2 2003/10/30 23:36:29 phherlin ! * Fixing bugs ! * #819518 : AST writes out method return types incorrectly * #820241 : VariableDeclaration doesn't show variable modifiers ! * Revision 1.1 2003/10/27 20:14:13 phherlin * Refactoring AST generation. Using a ASTWriter. ! * */ public class ASTWriterImpl implements ASTWriter { --- 55,69 ---- * * $Log$ ! * Revision 1.3 2003/11/30 22:57:43 phherlin ! * Merging from eclipse-v2 development branch ! * ! * Revision 1.1.2.1 2003/10/30 23:23:01 phherlin ! * Fixing bugs ! * #819518 : AST writes out method return types incorrectly * #820241 : VariableDeclaration doesn't show variable modifiers ! * ! * Revision 1.1 2003/10/27 20:14:13 phherlin * Refactoring AST generation. Using a ASTWriter. ! * */ public class ASTWriterImpl implements ASTWriter { *************** *** 64,70 **** /** ! * @see net.sourceforge.pmd.eclipse.ASTWriter#write(java.io.Writer, ! * net.sourceforge.pmd.ast.ASTCompilationUnit) ! */ public void write(Writer writer, ASTCompilationUnit compilationUnit) throws PMDEclipseException { try { --- 71,76 ---- /** ! * @see net.sourceforge.pmd.eclipse.ASTWriter#write(java.io.Writer, net.sourceforge.pmd.ast.ASTCompilationUnit) ! */ public void write(Writer writer, ASTCompilationUnit compilationUnit) throws PMDEclipseException { try { *************** *** 92,103 **** /** ! * Transform a ast node to a xml element ! * ! * @param doc ! * the generated document ! * @param simpleNode ! * a ast node ! * @return a xml element ! */ private Element getElement(Document doc, SimpleNode simpleNode) { log.debug("creating element " + simpleNode); --- 98,106 ---- /** ! * Transform a ast node to a xml element ! * @param doc the generated document ! * @param simpleNode a ast node ! * @return a xml element ! */ private Element getElement(Document doc, SimpleNode simpleNode) { log.debug("creating element " + simpleNode); *************** *** 116,127 **** /** ! * Add attributes to element by introspecting the node. This way, the ! * abstract tree can evolve indepently from the way it is persisted ! * ! * @param element ! * a xml element ! * @param simpleNode ! * a ast node ! */ private void addAttributes(Element element, SimpleNode simpleNode) { try { --- 119,127 ---- /** ! * Add attributes to element by introspecting the node. This way, the abstract ! * tree can evolve indepently from the way it is persisted ! * @param element a xml element ! * @param simpleNode a ast node ! */ private void addAttributes(Element element, SimpleNode simpleNode) { try { Index: PMDEclipseException.java =================================================================== RCS file: /cvsroot/pmd/pmd-eclipse/src/net/sourceforge/pmd/eclipse/PMDEclipseException.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** PMDEclipseException.java 14 Oct 2003 21:56:47 -0000 1.1 --- PMDEclipseException.java 30 Nov 2003 22:57:43 -0000 1.2 *************** *** 23,26 **** --- 23,29 ---- package net.sourceforge.pmd.eclipse; + import java.io.PrintStream; + import java.io.PrintWriter; + /** * An exception to encapsulate exceptions thrown by various plug-in components *************** *** 30,33 **** --- 33,42 ---- * * $Log$ + * Revision 1.2 2003/11/30 22:57:43 phherlin + * Merging from eclipse-v2 development branch + * + * Revision 1.1.2.1 2003/10/29 13:22:33 phherlin + * Fix JDK1.3 runtime problem (Thanks to Eduard Naum) + * * Revision 1.1 2003/10/14 21:56:47 phherlin * Creation *************** *** 35,38 **** --- 44,48 ---- */ public class PMDEclipseException extends Exception { + private Throwable cause; // Waiting for JDK 1.4 ! /** *************** *** 57,61 **** */ public PMDEclipseException(String message, Throwable cause) { ! super(message, cause); } --- 67,72 ---- */ public PMDEclipseException(String message, Throwable cause) { ! super(message); ! setCause(cause); } *************** *** 65,69 **** */ public PMDEclipseException(Throwable cause) { ! super(cause); } --- 76,127 ---- */ public PMDEclipseException(Throwable cause) { ! setCause(cause); ! } ! ! /** ! * @return ! */ ! public Throwable getCause() { ! return cause; ! } ! ! /** ! * @param throwable ! */ ! public void setCause(Throwable throwable) { ! cause = throwable; ! } ! ! /** ! * @see java.lang.Throwable#printStackTrace() ! */ ! public void printStackTrace() { ! super.printStackTrace(); ! if (getCause() != null) { ! System.err.println("Caused by:"); ! getCause().printStackTrace(); ! } ! } ! ! /** ! * @see java.lang.Throwable#printStackTrace(java.io.PrintStream) ! */ ! public void printStackTrace(PrintStream s) { ! super.printStackTrace(s); ! if (getCause() != null) { ! s.println("Caused by:"); ! getCause().printStackTrace(s); ! } ! } ! ! /** ! * @see java.lang.Throwable#printStackTrace(java.io.PrintWriter) ! */ ! public void printStackTrace(PrintWriter s) { ! super.printStackTrace(s); ! if (getCause() != null) { ! s.println("Caused by:"); ! getCause().printStackTrace(s); ! } } Index: PMDProcessor.java =================================================================== RCS file: /cvsroot/pmd/pmd-eclipse/src/net/sourceforge/pmd/eclipse/PMDProcessor.java,v retrieving revision 1.13 retrieving revision 1.14 diff -C2 -d -r1.13 -r1.14 *** PMDProcessor.java 30 Oct 2003 16:59:42 -0000 1.13 --- PMDProcessor.java 30 Nov 2003 22:57:43 -0000 1.14 *************** *** 22,26 **** import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.eclipse.core.internal.resources.MarkerInfo; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; --- 22,25 ---- *************** *** 37,42 **** * * $Log$ ! * Revision 1.13 2003/10/30 16:59:42 phherlin ! * Merging v1.2.1 features : refactoring JDK 1.3 compatibility feature * * Revision 1.12 2003/10/14 21:25:04 phherlin --- 36,53 ---- * * $Log$ ! * Revision 1.14 2003/11/30 22:57:43 phherlin ! * Merging from eclipse-v2 development branch ! * ! * Revision 1.12.2.4 2003/11/27 22:18:26 phherlin ! * Fixing bug #850242 : PMD working from time to time ! * ! * Revision 1.12.2.3 2003/11/04 13:27:35 phherlin ! * Minor corrections in log messages ! * ! * Revision 1.12.2.2 2003/11/03 14:40:16 phherlin ! * Refactoring to remove usage of Eclipse internal APIs ! * ! * Revision 1.12.2.1 2003/10/29 14:26:05 phherlin ! * Refactoring JDK 1.3 compatibility feature. Now use the compiler compliance option. * * Revision 1.12 2003/10/14 21:25:04 phherlin *************** *** 148,152 **** if (!reviewsList.contains(review)) { markerSet.add(getMarkerInfo(violation, fTask ? PMDPlugin.PMD_TASKMARKER : PMDPlugin.PMD_MARKER)); ! log.debug("Adding a violation " + violation); } else { log.debug( --- 159,163 ---- if (!reviewsList.contains(review)) { markerSet.add(getMarkerInfo(violation, fTask ? PMDPlugin.PMD_TASKMARKER : PMDPlugin.PMD_MARKER)); ! log.debug("Adding a violation for rule " + violation.getRule().getName() + " at line " + violation.getLine()); } else { log.debug( *************** *** 160,164 **** if (accumulator != null) { ! log.debug("Adding markerSet to accumulator for file " + file); accumulator.put(file, markerSet); } --- 171,175 ---- if (accumulator != null) { ! log.debug("Adding markerSet to accumulator for file " + file.getName()); accumulator.put(file, markerSet); } *************** *** 192,196 **** markerInfo.setType(type); - // markerInfo.setCreationTime(System.currentTimeMillis()); List attributeNames = new ArrayList(); --- 203,206 ---- *************** *** 229,233 **** break; } ! markerInfo.setAttributes((String[]) attributeNames.toArray(new String[attributeNames.size()]), values.toArray()); return markerInfo; --- 239,245 ---- break; } ! ! markerInfo.setAttributeNames((String[]) attributeNames.toArray(new String[attributeNames.size()])); ! markerInfo.setAttributeValues(values.toArray()); return markerInfo; *************** *** 247,272 **** BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents())); while (reader.ready()) { ! String line = reader.readLine().trim(); ! lineNumber++; ! if (line.startsWith("/*")) { ! if (line.indexOf("*/") == -1) { ! comment = true; ! } ! } else if (comment && (line.indexOf("*/") != -1)) { ! comment = false; ! } else if (!comment && line.startsWith(PMDPlugin.REVIEW_MARKER)) { ! String tail = line.substring(17); ! int index = tail.indexOf(':'); ! String ruleName = tail.substring(0, index); ! pendingReviews.push(ruleName); ! findLine = true; ! } else if (!comment && findLine) { ! if (!line.equals("") && !line.startsWith("//")) { ! findLine = false; ! while (!pendingReviews.empty()) { ! Review review = new Review(); ! review.ruleName = (String) pendingReviews.pop(); ! review.lineNumber = lineNumber; ! reviewsList.add(review); } } --- 259,287 ---- BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents())); while (reader.ready()) { ! String line = reader.readLine(); ! if (line != null) { ! line = line.trim(); ! lineNumber++; ! if (line.startsWith("/*")) { ! if (line.indexOf("*/") == -1) { ! comment = true; ! } ! } else if (comment && (line.indexOf("*/") != -1)) { ! comment = false; ! } else if (!comment && line.startsWith(PMDPlugin.REVIEW_MARKER)) { ! String tail = line.substring(17); ! int index = tail.indexOf(':'); ! String ruleName = tail.substring(0, index); ! pendingReviews.push(ruleName); ! findLine = true; ! } else if (!comment && findLine) { ! if (!line.equals("") && !line.startsWith("//")) { ! findLine = false; ! while (!pendingReviews.empty()) { ! Review review = new Review(); ! review.ruleName = (String) pendingReviews.pop(); ! review.lineNumber = lineNumber; ! reviewsList.add(review); ! } } } Index: RuleSetWriterImpl.java =================================================================== RCS file: /cvsroot/pmd/pmd-eclipse/src/net/sourceforge/pmd/eclipse/RuleSetWriterImpl.java,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** RuleSetWriterImpl.java 16 Oct 2003 22:26:37 -0000 1.1 --- RuleSetWriterImpl.java 30 Nov 2003 22:57:43 -0000 1.2 *************** *** 15,18 **** --- 15,20 ---- import net.sourceforge.pmd.RuleSet; + import org.apache.commons.logging.Log; + import org.apache.commons.logging.LogFactory; import org.apache.xml.serialize.DOMSerializer; import org.apache.xml.serialize.OutputFormat; *************** *** 33,38 **** * * $Log$ * Revision 1.1 2003/10/16 22:26:37 phherlin ! * Fix bug #810858. * Complete refactoring of rule set generation. Using a DOM tree and the Xerces 2 serializer. * --- 35,46 ---- * * $Log$ + * Revision 1.2 2003/11/30 22:57:43 phherlin + * Merging from eclipse-v2 development branch + * + * Revision 1.1.2.1 2003/11/07 14:31:48 phherlin + * Reverse to identation usage, remove dummy text nodes + * * Revision 1.1 2003/10/16 22:26:37 phherlin ! * Fix bug #810858. * Complete refactoring of rule set generation. Using a DOM tree and the Xerces 2 serializer. * *************** *** 49,52 **** --- 57,61 ---- */ public class RuleSetWriterImpl implements RuleSetWriter { + private static Log log = LogFactory.getLog("net.sourceforge.pmd.eclipse.RuleSetWriterImpl"); /** *************** *** 66,71 **** OutputFormat outputFormat = new OutputFormat(doc); outputFormat.setEncoding("UTF-8"); ! outputFormat.setPreserveSpace(true); ! outputFormat.setPreserveEmptyAttributes(true); DOMSerializer serializer = new XMLSerializer(writer, outputFormat); serializer.serialize(doc); --- 75,79 ---- OutputFormat outputFormat = new OutputFormat(doc); outputFormat.setEncoding("UTF-8"); ! outputFormat.setIndenting(true); DOMSerializer serializer = new XMLSerializer(writer, outputFormat); serializer.serialize(doc); *************** *** 98,102 **** Iterator rules = ruleSet.getRules().iterator(); while (rules.hasNext()) { ! Element ruleElement = getRuleElement(doc, (Rule) rules.next()); ruleSetElement.appendChild(ruleElement); } --- 106,112 ---- Iterator rules = ruleSet.getRules().iterator(); while (rules.hasNext()) { ! Rule rule = (Rule) rules.next(); ! log.debug("Serializing rule " + rule.getName()); ! Element ruleElement = getRuleElement(doc, rule); ruleSetElement.appendChild(ruleElement); } *************** *** 154,159 **** private Element getExampleElement(Document doc, String example) { Element exampleElement = doc.createElement("example"); - Text dummy = doc.createTextNode("\n"); - exampleElement.appendChild(dummy); CDATASection cdataSection = doc.createCDATASection(example); exampleElement.appendChild(cdataSection); --- 164,167 ---- *************** *** 182,187 **** private Element getPropertiesElement(Document doc, Properties properties) { Element propertiesElement = doc.createElement("properties"); - Text dummy = doc.createTextNode("\n"); - propertiesElement.appendChild(dummy); Enumeration keys = properties.keys(); while (keys.hasMoreElements()) { --- 190,193 ---- *************** *** 189,193 **** Element propertyElement = getPropertyElement(doc, (String) key, (String) properties.get(key)); propertiesElement.appendChild(propertyElement); - propertiesElement.appendChild(dummy); } return propertiesElement; --- 195,198 ---- *************** *** 206,211 **** if (key.equals("xpath")) { Element valueElement = doc.createElement("value"); - Text dummy = doc.createTextNode("\n"); - valueElement.appendChild(dummy); CDATASection cdataSection = doc.createCDATASection(value); valueElement.appendChild(cdataSection); --- 211,214 ---- Index: PMDPlugin.java =================================================================== RCS file: /cvsroot/pmd/pmd-eclipse/src/net/sourceforge/pmd/eclipse/PMDPlugin.java,v retrieving revision 1.16 retrieving revision 1.17 diff -C2 -d -r1.16 -r1.17 *** PMDPlugin.java 30 Oct 2003 16:59:42 -0000 1.16 --- PMDPlugin.java 30 Nov 2003 22:57:43 -0000 1.17 *************** *** 24,27 **** --- 24,28 ---- import org.apache.commons.logging.LogFactory; import org.apache.log4j.xml.DOMConfigurator; + import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; *************** *** 41,44 **** --- 42,48 ---- import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; + import org.eclipse.ui.IWorkingSet; + import org.eclipse.ui.IWorkingSetManager; + import org.eclipse.ui.PlatformUI; import org.eclipse.ui.plugin.AbstractUIPlugin; *************** *** 51,56 **** * * $Log$ ! * Revision 1.16 2003/10/30 16:59:42 phherlin ! * Merging v1.2.1 features : refactoring JDK 1.3 compatibility feature * * Revision 1.15 2003/10/16 22:26:37 phherlin --- 55,72 ---- * * $Log$ ! * Revision 1.17 2003/11/30 22:57:43 phherlin ! * Merging from eclipse-v2 development branch ! * ! * Revision 1.15.2.4 2003/11/07 14:33:57 phherlin ! * Implementing the "project ruleset" feature ! * ! * Revision 1.15.2.3 2003/11/04 13:26:38 phherlin ! * Implement the working set feature (working set filtering) ! * ! * Revision 1.15.2.2 2003/10/29 14:26:05 phherlin ! * Refactoring JDK 1.3 compatibility feature. Now use the compiler compliance option. ! * ! * Revision 1.15.2.1 2003/10/29 13:22:34 phherlin ! * Fix JDK1.3 runtime problem (Thanks to Eduard Naum) * * Revision 1.15 2003/10/16 22:26:37 phherlin *************** *** 118,121 **** --- 134,150 ---- new QualifiedName(PLUGIN_ID + ".persprops", "active_rulset"); + public static final QualifiedName SESSION_PROPERTY_WORKINGSET = + new QualifiedName(PLUGIN_ID + ".sessprops", "workingset"); + public static final QualifiedName PERSISTENT_PROPERTY_WORKINGSET = + new QualifiedName(PLUGIN_ID + ".persprops", "workingset"); + + public static final QualifiedName SESSION_PROPERTY_STORE_RULESET_PROJECT = + new QualifiedName(PLUGIN_ID + ".sessprops", "store_ruleset_project"); + public static final QualifiedName PERSISTENT_PROPERTY_STORE_RULESET_PROJECT = + new QualifiedName(PLUGIN_ID + ".persprops", "store_ruleset_project"); + + public static final QualifiedName SESSION_PROPERTY_RULESET_MODIFICATION_STAMP = + new QualifiedName(PLUGIN_ID + ".sessprops", "ruleset_modification_stamp"); + public static final String LIST_DELIMITER = ";"; *************** *** 266,270 **** return subRuleSet; } ! /** * Get the rulset configured for the resouce. --- 295,299 ---- return subRuleSet; } ! /** * Get the rulset configured for the resouce. *************** *** 272,275 **** --- 301,323 ---- */ public RuleSet getRuleSetForResource(IResource resource, boolean flCreateProperty) { + log.debug("Asking a ruleset for resource " + resource.getName()); + IProject project = resource.getProject(); + RuleSet projectRuleSet = null; + + if (isRuleSetStoredInProject(project)) { + projectRuleSet = getRuleSetForResourceFromProject(project); + } else { + projectRuleSet = getRuleSetForResourceFromProperties(resource, flCreateProperty); + } + + return projectRuleSet; + } + + /** + * Get the rulset configured for the resouce. + * Currently, it is the one configured for the resource's project + */ + public RuleSet getRuleSetForResourceFromProperties(IResource resource, boolean flCreateProperty) { + log.debug("Searching a ruleset for resource " + resource.getName() + " in properties"); boolean flNeedSave = false; RuleSet projectRuleSet = null; *************** *** 312,319 **** --- 360,405 ---- } catch (CoreException e) { logError("Error when searching for project ruleset. Using the full ruleset.", e); + projectRuleSet = getRuleSet(); } return projectRuleSet; } + + /** + * Retrieve a project ruleset from a ruleset file in the project + * instead of the plugin properties/preferences + * @param project + * @return + */ + public RuleSet getRuleSetForResourceFromProject(IProject project) { + log.debug("Searching a ruleset for project " + project.getName() + " in the project file"); + RuleSet projectRuleSet = null; + IFile ruleSetFile = project.getFile(".ruleset"); + if (ruleSetFile.exists()) { + try { + projectRuleSet = (RuleSet) project.getSessionProperty(SESSION_PROPERTY_ACTIVE_RULESET); + Long oldModificationStamp = (Long) project.getSessionProperty(SESSION_PROPERTY_RULESET_MODIFICATION_STAMP); + long newModificationStamp = ruleSetFile.getModificationStamp(); + if ((oldModificationStamp == null) || (oldModificationStamp.longValue() != newModificationStamp)) { + RuleSetFactory ruleSetFactory = new RuleSetFactory(); + projectRuleSet = ruleSetFactory.createRuleSet(ruleSetFile.getContents()); + project.setSessionProperty(SESSION_PROPERTY_ACTIVE_RULESET, projectRuleSet); + project.setSessionProperty(SESSION_PROPERTY_RULESET_MODIFICATION_STAMP, new Long(newModificationStamp)); + } + } catch (Exception e) { + PMDPlugin.getDefault().showError(getMessage(PMDConstants.MSGKEY_ERROR_LOADING_RULESET), e); + log.debug("", e); + projectRuleSet = null; + } + } + + // If ruleset cannot be loaded from project, try from properties. + if (projectRuleSet == null) { + log.debug("The project does not have a correct ruleset. Return a ruleset from the plugin properties"); + projectRuleSet = getRuleSetForResourceFromProperties(project, false); + } + + return projectRuleSet; + } /** *************** *** 328,333 **** ruleSelectionList.append(rule.getName()).append(LIST_DELIMITER); } ! resource.setPersistentProperty(PERSISTENT_PROPERTY_ACTIVE_RULESET, ruleSelectionList.toString()); resource.setSessionProperty(SESSION_PROPERTY_ACTIVE_RULESET, ruleSet); --- 414,420 ---- ruleSelectionList.append(rule.getName()).append(LIST_DELIMITER); } ! log.debug("Storing ruleset for resource " + resource.getName()); resource.setPersistentProperty(PERSISTENT_PROPERTY_ACTIVE_RULESET, ruleSelectionList.toString()); + log.debug(" list : " + ruleSelectionList.toString()); resource.setSessionProperty(SESSION_PROPERTY_ACTIVE_RULESET, ruleSet); *************** *** 346,349 **** --- 433,437 ---- // First find the ruleset file in the state location IPath ruleSetLocation = getStateLocation().append(RULESET_FILE); + log.debug("ruleset state location : " + ruleSetLocation.toOSString()); File ruleSetFile = new File(ruleSetLocation.toOSString()); if (ruleSetFile.exists()) { *************** *** 369,373 **** } ! // Finally, build a default ruleser if (preferedRuleSet == null) { preferedRuleSet = factory.createRuleSet(getClass().getClassLoader().getResourceAsStream(RULESET_DEFAULTLIST[0])); --- 457,461 ---- } ! // Finally, build a default ruleset if (preferedRuleSet == null) { preferedRuleSet = factory.createRuleSet(getClass().getClassLoader().getResourceAsStream(RULESET_DEFAULTLIST[0])); *************** *** 575,578 **** --- 663,755 ---- reviewAdditionalComment = string; getPreferenceStore().setValue(REVIEW_ADDITIONAL_COMMENT_PREFERENCE, reviewAdditionalComment); + } + + /** + * Get the current working set selected of a project + * Only one working set is allowed. + */ + public IWorkingSet getProjectWorkingSet(IProject project) { + IWorkingSet workingSet = null; + boolean flNeedSave = false; + + try { + workingSet = (IWorkingSet) project.getSessionProperty(SESSION_PROPERTY_WORKINGSET); + if (workingSet == null) { + String workingSetName = project.getPersistentProperty(PERSISTENT_PROPERTY_WORKINGSET); + if (workingSetName != null) { + IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); + workingSet = workingSetManager.getWorkingSet(workingSetName); + if (workingSet != null) { + flNeedSave = true; + } + } + } + + // If needed store modified ruleset + if (flNeedSave) { + setProjectWorkingSet(project, workingSet); + } + } catch (CoreException e) { + logError("Error when searching for project workingset. No workingset returned", e); + } + + return workingSet; + } + + /** + * Store a workingset for a project + */ + public void setProjectWorkingSet(IProject project, IWorkingSet workingSet) { + try { + project.setPersistentProperty(PERSISTENT_PROPERTY_WORKINGSET, workingSet == null ? null : workingSet.getName()); + project.setSessionProperty(SESSION_PROPERTY_WORKINGSET, workingSet); + + } catch (CoreException e) { + PMDPlugin.getDefault().showError(getMessage(PMDConstants.MSGKEY_ERROR_CORE_EXCEPTION), e); + } + } + + /** + * Search the store_ruleset_project property + * @param project + */ + public boolean isRuleSetStoredInProject(IProject project) { + Boolean ruleSetStoredInProject = Boolean.FALSE; + boolean flNeedSave = false; + + try { + ruleSetStoredInProject = (Boolean) project.getSessionProperty(SESSION_PROPERTY_STORE_RULESET_PROJECT); + if (ruleSetStoredInProject == null) { + String property = project.getPersistentProperty(PERSISTENT_PROPERTY_STORE_RULESET_PROJECT); + if (property != null) { + ruleSetStoredInProject = new Boolean(property); + flNeedSave = true; + } + } + + // If needed store modified ruleset + if (flNeedSave) { + setRuleSetStoredInProject(project, ruleSetStoredInProject); + } + } catch (CoreException e) { + logError("Error when searching for the store_ruleset_project property. Assuming the project doesn't store it's own ruleset", e); + } + + return ruleSetStoredInProject == null ? false : ruleSetStoredInProject.booleanValue(); + } + + /** + * Set the store_ruleset_project property + * @param project + * @param ruleSetStoredInProject + */ + public void setRuleSetStoredInProject(IProject project, Boolean ruleSetStoredInProject) { + try { + project.setPersistentProperty(PERSISTENT_PROPERTY_STORE_RULESET_PROJECT, ruleSetStoredInProject == null ? null : ruleSetStoredInProject.toString()); + project.setSessionProperty(SESSION_PROPERTY_STORE_RULESET_PROJECT, ruleSetStoredInProject); + + } catch (CoreException e) { + PMDPlugin.getDefault().showError(getMessage(PMDConstants.MSGKEY_ERROR_CORE_EXCEPTION), e); + } } Index: PMDDeltaVisitor.java =================================================================== RCS file: /cvsroot/pmd/pmd-eclipse/src/net/sourceforge/pmd/eclipse/PMDDeltaVisitor.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** PMDDeltaVisitor.java 19 Jun 2003 20:56:59 -0000 1.5 --- PMDDeltaVisitor.java 30 Nov 2003 22:57:43 -0000 1.6 *************** *** 1,6 **** package net.sourceforge.pmd.eclipse; - import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; --- 1,4 ---- *************** *** 18,21 **** --- 16,25 ---- * @version $Revision$ * $Log$ + * Revision 1.6 2003/11/30 22:57:43 phherlin + * Merging from eclipse-v2 development branch + * + * Revision 1.5.2.1 2003/11/04 13:26:38 phherlin + * Implement the working set feature (working set filtering) + * * Revision 1.5 2003/06/19 20:56:59 phherlin * Improve progress indicator accuracy *************** *** 28,36 **** * */ ! public class PMDDeltaVisitor implements IResourceDeltaVisitor { private static final Log log = LogFactory.getLog("net.sourceforge.pmd.eclipse.PMDDeltaVisitor"); - private IProgressMonitor monitor; - private boolean useTaskMarker = false; - private Map accumulator; /** --- 32,37 ---- * */ ! public class PMDDeltaVisitor extends PMDAbstractVisitor implements IResourceDeltaVisitor { private static final Log log = LogFactory.getLog("net.sourceforge.pmd.eclipse.PMDDeltaVisitor"); /** *************** *** 44,48 **** */ public PMDDeltaVisitor(IProgressMonitor monitor) { ! this.monitor = monitor; } --- 45,49 ---- */ public PMDDeltaVisitor(IProgressMonitor monitor) { ! setMonitor(monitor); } *************** *** 52,55 **** --- 53,57 ---- public boolean visit(IResourceDelta delta) throws CoreException { boolean fProcessChildren = true; + IProgressMonitor monitor = getMonitor(); if ((monitor == null) || ((monitor != null) && (!monitor.isCanceled()))) { *************** *** 96,157 **** */ private void processResource(IResource resource) { ! if ((resource instanceof IFile) ! && (((IFile) resource).getFileExtension() != null) ! && ((IFile) resource).getFileExtension().equals("java")) { ! if (monitor != null) { ! monitor.subTask(((IFile) resource).getName()); } - - PMDProcessor.getInstance().run((IFile) resource, useTaskMarker, getAccumulator()); } - } - - /** - * Returns the monitor. - * @return IProgressMonitor - */ - public IProgressMonitor getMonitor() { - return monitor; - } - - /** - * Sets the monitor. - * @param monitor The monitor to set - */ - public void setMonitor(IProgressMonitor monitor) { - this.monitor = monitor; - } - - /** - * Returns the useTaskMarker. - * @return boolean - */ - public boolean isUseTaskMarker() { - return useTaskMarker; - } - - /** - * Sets the useTaskMarker. - * @param useTaskMarker The useTaskMarker to set - */ - public void setUseTaskMarker(boolean useTaskMarker) { - this.useTaskMarker = useTaskMarker; - } - - /** - * Returns the accumulator. - * @return Map - */ - public Map getAccumulator() { - return accumulator; - } - - /** - * Sets the accumulator. - * @param accumulator The accumulator to set - */ - public void setAccumulator(Map accumulator) { - this.accumulator = accumulator; } --- 98,116 ---- */ private void processResource(IResource resource) { ! IFile file = (IFile) resource.getAdapter(IFile.class); ! if ((file != null) ! && (file.getFileExtension() != null) ! && (file.getFileExtension().equals("java"))) { ! if (getMonitor() != null) { ! getMonitor().subTask(((IFile) resource).getName()); ! } ! ! if (isFileInWorkingSet(file)) { ! PMDProcessor.getInstance().run(file, isUseTaskMarker(), getAccumulator()); ! } else { ! log.debug("The file " + file.getName() + " is not in the working set"); } } } Index: PMDConstants.java =================================================================== RCS file: /cvsroot/pmd/pmd-eclipse/src/net/sourceforge/pmd/eclipse/PMDConstants.java,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** PMDConstants.java 30 Oct 2003 16:59:42 -0000 1.10 --- PMDConstants.java 30 Nov 2003 22:57:43 -0000 1.11 *************** *** 7,12 **** * * $Log$ ! * Revision 1.10 2003/10/30 16:59:42 phherlin ! * Merging v1.2.1 features : refactoring JDK 1.3 compatibility feature * * Revision 1.9 2003/09/29 22:38:09 phherlin --- 7,27 ---- * * $Log$ ! * Revision 1.11 2003/11/30 22:57:43 phherlin ! * Merging from eclipse-v2 development branch ! * ! * Revision 1.9.2.5 2003/11/07 14:33:57 phherlin ! * Implementing the "project ruleset" feature ! * ! * Revision 1.9.2.4 2003/11/05 13:11:47 phherlin ! * Add the Quick fix menu item to the violations view ! * ! * Revision 1.9.2.3 2003/11/04 13:26:38 phherlin ! * Implement the working set feature (working set filtering) ! * ! * Revision 1.9.2.2 2003/10/31 16:53:54 phherlin ! * Implementing lazy check feature ! * ! * Revision 1.9.2.1 2003/10/29 14:26:05 phherlin ! * Refactoring JDK 1.3 compatibility feature. Now use the compiler compliance option. * * Revision 1.9 2003/09/29 22:38:09 phherlin *************** *** 36,40 **** public static final String MSGKEY_PROPERTY_BUTTON_ENABLE = "property.button.enable"; public static final String MSGKEY_PROPERTY_LABEL_SELECT_RULE = "property.label.select_rule"; ! public static final String MSGKEY_PREF_GENERAL_TITLE = "preference.pmd.title"; public static final String MSGKEY_PREF_GENERAL_LABEL_ADDCOMMENT = "preference.pmd.label.addcomment"; --- 51,60 ---- public static final String MSGKEY_PROPERTY_BUTTON_ENABLE = "property.button.enable"; public static final String MSGKEY_PROPERTY_LABEL_SELECT_RULE = "property.label.select_rule"; ! public static final String MSGKEY_PROPERTY_BUTTON_SELECT_WORKINGSET = "property.button.select_workingset"; ! public static final String MSGKEY_PROPERTY_BUTTON_DESELECT_WORKINGSET = "property.button.deselect_workingset"; ! public static final String MSGKEY_PROPERTY_LABEL_NO_WORKINGSET = "property.label.no_workingset"; ! public static final String MSGKEY_PROPERTY_LABEL_SELECTED_WORKINGSET = "property.label.selected_workingset"; ! public static final String MSGKEY_PROPERTY_BUTTON_STORE_RULESET_PROJECT = "property.button.store_ruleset_project"; ! public static final String MSGKEY_PREF_GENERAL_TITLE = "preference.pmd.title"; public static final String MSGKEY_PREF_GENERAL_LABEL_ADDCOMMENT = "preference.pmd.label.addcomment"; *************** *** 95,98 **** --- 115,119 ---- public static final String MSGKEY_VIEW_TOOLTIP_REMOVE_VIOLATION = "view.tooltip.remove_violation"; public static final String MSGKEY_VIEW_TOOLTIP_REVIEW = "view.tooltip.review"; + public static final String MSGKEY_VIEW_TOOLTIP_QUICKFIX = "view.tooltip.quickfix"; public static final String MSGKEY_VIEW_ACTION_PROJECT = "view.action.project"; public static final String MSGKEY_VIEW_ACTION_FILE = "view.action.file"; *************** *** 105,108 **** --- 126,130 ---- public static final String MSGKEY_VIEW_ACTION_REMOVE_VIOLATION = "view.action.remove_violation"; public static final String MSGKEY_VIEW_ACTION_REVIEW = "view.action.review"; + public static final String MSGKEY_VIEW_ACTION_QUICKFIX = "view.action.quickfix"; public static final String MSGKEY_VIEW_MENU_RESOURCE_FILTER = "view.menu.resource_filter"; public static final String MSGKEY_VIEW_MENU_PRIORITY_FILTER = "view.menu.priority_filter"; *************** *** 124,130 **** --- 146,155 ---- public static final String MSGKEY_ERROR_STORING_PROPERTY = "message.error.storing_property"; public static final String MSGKEY_ERROR_FIND_MARKER = "message.error.find_marker"; + public static final String MSGKEY_ERROR_LOADING_RULESET = "message.error.loading_ruleset"; public static final String MSGKEY_QUESTION_TITLE = "message.question.title"; public static final String MSGKEY_QUESTION_RULES_CHANGED = "message.question.rules_changed"; + public static final String MSGKEY_QUESTION_REBUILD_PROJECT = "message.question.rebuild_project"; + public static final String MSGKEY_QUESTION_CREATE_RULESET_FILE = "message.question.create_ruleset_file"; public static final String MSGKEY_CONFIRM_TITLE = "message.confirm.title"; Index: PMDVisitorRunner.java =================================================================== RCS file: /cvsroot/pmd/pmd-eclipse/src/net/sourceforge/pmd/eclipse/PMDVisitorRunner.java,v retrieving revision 1.2 retrieving revision 1.3 diff -C2 -d -r1.2 -r1.3 *** PMDVisitorRunner.java 30 Oct 2003 16:29:16 -0000 1.2 --- PMDVisitorRunner.java 30 Nov 2003 22:57:43 -0000 1.3 *************** *** 8,15 **** import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.eclipse.core.internal.resources.MarkerInfo; - import org.eclipse.core.internal.resources.MarkerManager; - import org.eclipse.core.internal.resources.Workspace; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; --- 8,13 ---- import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.core.resources.IFile; + import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; *************** *** 29,34 **** * * $Log$ ! * Revision 1.2 2003/10/30 16:29:16 phherlin ! * Adapting to Eclipse v3 M4 * * Revision 1.1 2003/05/19 22:27:33 phherlin --- 27,35 ---- * * $Log$ ! * Revision 1.3 2003/11/30 22:57:43 phherlin ! * Merging from eclipse-v2 development branch ! * ! * Revision 1.1.2.1 2003/11/03 14:40:17 phherlin ! * Refactoring to remove usage of Eclipse internal APIs * * Revision 1.1 2003/05/19 22:27:33 phherlin *************** *** 51,55 **** visitor.setAccumulator(markerDirectives); resource.accept(visitor); ! runApplyDirectives(markerDirectives); markerDirectives.clear(); } --- 52,56 ---- visitor.setAccumulator(markerDirectives); resource.accept(visitor); ! doApplyDirectives(markerDirectives); markerDirectives.clear(); } *************** *** 64,71 **** public void run(IProject project, PMDVisitor visitor) throws CoreException { Map markerDirectives = new HashMap(); ! setMonitor(visitor.getMonitor()); visitor.setAccumulator(markerDirectives); project.accept(visitor); ! runApplyDirectives(markerDirectives); markerDirectives.clear(); } --- 65,72 ---- public void run(IProject project, PMDVisitor visitor) throws CoreException { Map markerDirectives = new HashMap(); ! setMonitor(visitor.getMonitor()); visitor.setAccumulator(markerDirectives); project.accept(visitor); ! doApplyDirectives(markerDirectives); markerDirectives.clear(); } *************** *** 81,93 **** visitor.setAccumulator(markerDirectives); resourceDelta.accept(visitor); ! runApplyDirectives(markerDirectives); markerDirectives.clear(); } ! /** ! * Apply the marker changes in a bacth workspace job * @param markerDirectives map of new marker informations */ ! private void runApplyDirectives(final Map markerDirectives) throws CoreException { IWorkspace workspace = ResourcesPlugin.getWorkspace(); workspace.run(new IWorkspaceRunnable() { --- 82,95 ---- visitor.setAccumulator(markerDirectives); resourceDelta.accept(visitor); ! doApplyDirectives(markerDirectives); markerDirectives.clear(); } ! /** ! * Apply the markers on a workspace batch job * @param markerDirectives map of new marker informations + * @throws CoreException */ ! private void doApplyDirectives(final Map markerDirectives) throws CoreException { IWorkspace workspace = ResourcesPlugin.getWorkspace(); workspace.run(new IWorkspaceRunnable() { *************** *** 107,121 **** Set filesSet = markerDirectives.keySet(); Iterator i = filesSet.iterator(); - Workspace workspace = (Workspace) ResourcesPlugin.getWorkspace(); - MarkerManager markerManager = workspace.getMarkerManager(); while (i.hasNext()) { ! IFile file = (IFile) i.next(); try { Set markerInfoSet = (Set) markerDirectives.get(file); file.deleteMarkers(PMDPlugin.PMD_MARKER, true, IResource.DEPTH_INFINITE); ! markerManager.add(file, (MarkerInfo[]) markerInfoSet.toArray(new MarkerInfo[markerInfoSet.size()])); ! } catch (CoreException e) { ! log.warn("CoreException when setting marker info for file " + file.getName() + " : " + e.getMessage()); } } --- 109,129 ---- Set filesSet = markerDirectives.keySet(); Iterator i = filesSet.iterator(); while (i.hasNext()) { ! IFile file = (IFile) i.next(); ! try { + Set markerInfoSet = (Set) markerDirectives.get(file); file.deleteMarkers(PMDPlugin.PMD_MARKER, true, IResource.DEPTH_INFINITE); ! Iterator j = markerInfoSet.iterator(); ! while (j.hasNext()) { ! MarkerInfo markerInfo = (MarkerInfo) j.next(); ! IMarker marker = file.createMarker(markerInfo.getType()); ! marker.setAttributes(markerInfo.getAttributeNames(), markerInfo.getAttributeValues()); ! } ! ! } catch (CoreException e) { ! log.warn("CoreException when setting marker info for file " + file.getName() + " : " + e.getMessage()); } } *************** *** 127,131 **** /** ! * @return Returns the monitor. */ public IProgressMonitor getMonitor() { --- 135,139 ---- /** ! * @return */ public IProgressMonitor getMonitor() { *************** *** 134,138 **** /** ! * @param monitor The monitor to set. */ public void setMonitor(IProgressMonitor monitor) { --- 142,146 ---- /** ! * @param monitor */ public void setMonitor(IProgressMonitor monitor) { Index: PMDVisitor.java =================================================================== RCS file: /cvsroot/pmd/pmd-eclipse/src/net/sourceforge/pmd/eclipse/PMDVisitor.java,v retrieving revision 1.15 retrieving revision 1.16 diff -C2 -d -r1.15 -r1.16 *** PMDVisitor.java 30 Oct 2003 16:29:16 -0000 1.15 --- PMDVisitor.java 30 Nov 2003 22:57:43 -0000 1.16 *************** *** 1,6 **** package net.sourceforge.pmd.eclipse; - import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; --- 1,4 ---- *************** *** 23,28 **** * * $Log$ ! * Revision 1.15 2003/10/30 16:29:16 phherlin ! * Adapting to Eclipse v3 M4 * * Revision 1.14 2003/06/30 22:00:53 phherlin --- 21,32 ---- * * $Log$ ! * Revision 1.16 2003/11/30 22:57:43 phherlin ! * Merging from eclipse-v2 development branch ! * ! * Revision 1.14.2.2 2003/11/04 13:26:38 phherlin ! * Implement the working set feature (working set filtering) ! * ! * Revision 1.14.2.1 2003/11/03 14:40:16 phherlin ! * Refactoring to remove usage of Eclipse internal APIs * * Revision 1.14 2003/06/30 22:00:53 phherlin *************** *** 42,51 **** * */ ! public class PMDVisitor implements IResourceVisitor { private static final Log log = LogFactory.getLog("net.sourceforge.pmd.eclipse.PMDVisitor"); ! private IProgressMonitor monitor; ! private boolean useTaskMarker = false; ! private Map accumulator; ! /** * Construct with a progress monitor --- 46,52 ---- * */ ! public class PMDVisitor extends PMDAbstractVisitor implements IResourceVisitor { private static final Log log = LogFactory.getLog("net.sourceforge.pmd.eclipse.PMDVisitor"); ! /** * Construct with a progress monitor *************** *** 54,58 **** public PMDVisitor(IProgressMonitor monitor) { log.debug("Instanciating a new visitor"); ! this.monitor = monitor; } --- 55,59 ---- public PMDVisitor(IProgressMonitor monitor) { log.debug("Instanciating a new visitor"); ! setMonitor(monitor); } *************** *** 63,71 **** log.debug("Visiting resource " + resource.getName()); boolean fVisitChildren = true; if ((monitor == null) || ((monitor != null) && (!monitor.isCanceled()))) { ! if ((resource instanceof IFile) ! && (((IFile) resource).getFileExtension() != null) ! && ((IFile) resource).getFileExtension().equals("java")) { if (monitor != null) { --- 64,74 ---- log.debug("Visiting resource " + resource.getName()); boolean fVisitChildren = true; + IProgressMonitor monitor = getMonitor(); if ((monitor == null) || ((monitor != null) && (!monitor.isCanceled()))) { ! IFile file = (IFile) resource.getAdapter(IFile.class); ! if ((file != null) ! && (file.getFileExtension() != null) ! && (file.getFileExtension().equals("java"))) { if (monitor != null) { *************** *** 73,80 **** PMDPlugin.getDefault().getMessage(PMDConstants.MSGKEY_MONITOR_CHECKING_FILE) + " " ! + ((IFile) resource).getName()); } - - PMDProcessor.getInstance().run((IFile) resource, useTaskMarker, getAccumulator()); fVisitChildren = false; --- 76,87 ---- PMDPlugin.getDefault().getMessage(PMDConstants.MSGKEY_MONITOR_CHECKING_FILE) + " " ! + file.getName()); ! } ! ! if (isFileInWorkingSet(file)) { ! PMDProcessor.getInstance().run(file, isUseTaskMarker(), getAccumulator()); ! } else { ! log.debug("The file " + file.getName() + " is not in the working set"); } fVisitChildren = false; *************** *** 91,141 **** return fVisitChildren; - } - /** - * Returns the useTaskMarker. - * @return boolean - */ - public boolean isUseTaskMarker() { - return useTaskMarker; - } - - /** - * Sets the useTaskMarker. - * @param useTaskMarker The useTaskMarker to set - */ - public void setUseTaskMarker(boolean useTaskMarker) { - this.useTaskMarker = useTaskMarker; - } - - /** - * Returns the accumulator. - * @return Map - */ - public Map getAccumulator() { - log.debug("Returning the accumulator " + accumulator); - return accumulator; - } - - /** - * Sets the accumulator. - * @param accumulator The accumulator to set - */ - public void setAccumulator(Map accumulator) { - this.accumulator = accumulator; - log.debug("Setting accumulator " + accumulator); - } - - /** - * @return Returns the monitor. - */ - public IProgressMonitor getMonitor() { - return monitor; - } - - /** - * @param monitor The monitor to set. - */ - public void setMonitor(IProgressMonitor monitor) { - this.monitor = monitor; } --- 98,101 ---- |