Bug 578948 - [18][javadoc] incorrect handling of overlapping multiple
annotations within @snippet

Change-Id: I50ff70abdae5e5d9edafc17d3137cf3fc32ecc1d
Signed-off-by: Kalyan Prasad Tatavarthi <kalyan_prasad@in.ibm.com>
Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.ui/+/191692
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavaDocSnippetStringEvaluator.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavaDocSnippetStringEvaluator.java
new file mode 100644
index 0000000..26def92
--- /dev/null
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavaDocSnippetStringEvaluator.java
@@ -0,0 +1,665 @@
+package org.eclipse.jdt.internal.ui.text.javadoc;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.JavaDocRegion;
+import org.eclipse.jdt.core.dom.MemberRef;
+import org.eclipse.jdt.core.dom.MethodRef;
+import org.eclipse.jdt.core.dom.MethodRefParameter;
+import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.dom.TagElement;
+import org.eclipse.jdt.core.dom.TagProperty;
+import org.eclipse.jdt.core.dom.TextElement;
+
+import org.eclipse.jdt.internal.corext.dom.ASTNodes;
+
+import org.eclipse.jdt.internal.ui.JavaPlugin;
+import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks;
+
+public class JavaDocSnippetStringEvaluator {
+
+	/**
+	 * Either an IMember or an IPackageFragment.
+	 */
+	private final IJavaElement fElement;
+
+	public enum ReplacementStringIntervalStatus {
+		/**
+		 * replacement interval occurs before the given ActionElement interval
+		 */
+		BEFORE,
+		/**
+		 * replacement interval occurs after the given ActionElement interval
+		 */
+		AFTER,
+		/**
+		 * replacement interval occurs within the given ActionElement interval
+		 */
+		WITHIN,
+		/**
+		 * replacement interval contains the given ActionElement interval
+		 */
+		ENCOMPASS,
+		/**
+		 * replacement interval starts before the given ActionElement interval and ends within the ActionElement interval
+		 */
+		PREV_OVERLAP,
+		/**
+		 * replacement interval starts within the given ActionElement interval and ends after the ActionElement interval
+		 */
+		POST_OVERLAP,
+		/**
+		 * Default Value, do nothing
+		 */
+		DEFAULT
+	}
+
+	public class ActionElement{
+		public int start;
+		public int end;
+		public String startTag;
+		public String endTag;
+
+		public ActionElement(int start, int end, String startTag, String endTag) {
+			this.start= start;
+			this.end= end;
+			this.startTag= startTag;
+			this.endTag= endTag;
+		}
+
+		public ReplacementStringIntervalStatus getIntervalStatus(int replacementIntervalStart, int replacementIntervalEnd) {
+			ReplacementStringIntervalStatus intervalStatus= ReplacementStringIntervalStatus.DEFAULT;
+			int startDiff = replacementIntervalStart - this.start;
+			int endDiff = replacementIntervalEnd - this.end;
+
+			if (this.end <= replacementIntervalStart) {
+				intervalStatus= ReplacementStringIntervalStatus.AFTER;
+			} else if (this.start >= replacementIntervalEnd) {
+				intervalStatus= ReplacementStringIntervalStatus.BEFORE;
+			} else if (startDiff <= 0 && endDiff >= 0) {
+				intervalStatus= ReplacementStringIntervalStatus.ENCOMPASS;
+			} else if (startDiff > 0 && endDiff < 0) {
+				intervalStatus= ReplacementStringIntervalStatus.WITHIN;
+			} else if (startDiff > 0) {
+				intervalStatus= ReplacementStringIntervalStatus.POST_OVERLAP;
+			} else if (endDiff < 0) {
+				intervalStatus= ReplacementStringIntervalStatus.PREV_OVERLAP;
+			}
+
+			return intervalStatus;
+		}
+
+	}
+
+	public class StringItem{
+		public int index;
+		public String tag;
+		public StringItem(int index, String tag) {
+			this.index= index;
+			this.tag= tag;
+		}
+	}
+
+	public JavaDocSnippetStringEvaluator(IJavaElement element) {
+		this.fElement= element;
+	}
+
+	public void AddTagElementString(TagElement snippetTag, StringBuffer buffer) {
+		if (snippetTag != null) {
+			List<Object> fragments = snippetTag.fragments();
+			for( Object fragment : fragments) {
+				String str= ""; //$NON-NLS-1$
+				if (fragment instanceof TextElement) {
+					TextElement textElement= (TextElement) fragment;
+					List<TagElement> tagElements= getTagElementsForTextElement(snippetTag, textElement);
+					str = getModifiedString(textElement, tagElements);
+				} else if (fragment instanceof JavaDocRegion) {
+					JavaDocRegion region = (JavaDocRegion) fragment;
+					if (region.isDummyRegion()) {
+						List<TagElement> tagElements= getTagElementsForDummyJavaDocRegion(snippetTag, region);
+						str = getModifiedString(region, tagElements);
+					}
+				} else if (fragment instanceof TagElement) {
+					TagElement tagElement= (TagElement) fragment;
+					List<TagElement> tagElements= getTagElementsForTagElement(snippetTag, tagElement);
+					str = getModifiedString(tagElement, tagElements);
+				}
+				buffer.append(str);
+			}
+		}
+	}
+
+	private String getModifiedString(TextElement textElement, List<TagElement> tags) {
+		return getModifiedString(textElement.getText(), tags);
+	}
+
+	private String getModifiedString(TagElement tagElement, List<TagElement> tags) {
+		return getModifiedString(((TextElement)tagElement.fragments().get(0)).getText(), tags);
+	}
+
+	private String getModifiedString(JavaDocRegion region, List<TagElement> tags) {
+		return getModifiedString(((TextElement)region.fragments().get(0)).getText(), tags);
+	}
+
+	private String getModifiedString(String str, List<TagElement> tags) {
+		List<ActionElement> actionElements= new ArrayList<>();
+		String modifiedStr= str;
+		for (TagElement tag : tags) {
+			String name= tag.getTagName();
+			if (TagElement.TAG_HIGHLIGHT.equals(name)) {
+				handleSnippetHighlight(modifiedStr, tag, actionElements);
+			} else if (TagElement.TAG_REPLACE.equals(name)) {
+				modifiedStr= handleSnippetReplace(modifiedStr, tag, actionElements);
+			} else if (TagElement.TAG_LINK.equals(name)) {
+				handleSnippetLink(modifiedStr, tag, actionElements);
+			}
+		}
+		return getString( modifiedStr, actionElements);
+	}
+
+	private String getString(String str, List<ActionElement> actionElements) {
+		String modifiedStr = str;
+		List<StringItem> items= new ArrayList<>();
+		for (ActionElement actElem : actionElements) {
+			StringItem startItem = new StringItem(actElem.start, actElem.startTag);
+			StringItem endItem = new StringItem(actElem.end, actElem.endTag);
+			ListIterator<StringItem> iterator = items.listIterator();
+			boolean endIndexAdded = false;
+			boolean startIndexAdded = false;
+			while (iterator.hasNext()) {
+				StringItem elem= iterator.next();
+				if (!endIndexAdded && elem.index < endItem.index) {
+					iterator.previous();
+					iterator.add(endItem);
+					endIndexAdded = true;
+					iterator.next();
+				}
+				if (!startIndexAdded && elem.index < startItem.index) {
+					iterator.previous();
+					iterator.add(startItem);
+					startIndexAdded = true;
+					iterator.next();
+				}
+				if (startIndexAdded && endIndexAdded) {
+					break;
+				}
+			}
+			if (!endIndexAdded) {
+				items.add(endItem);
+			}
+			if (!startIndexAdded) {
+				items.add(startItem);
+			}
+		}
+		for (StringItem item : items) {
+			modifiedStr = modifiedStr.substring(0, item.index) + item.tag + modifiedStr.substring(item.index);
+		}
+		return modifiedStr;
+	}
+
+	private void modifyPrevActionItemsReplacement(int replacementIntervalStart, int relacementIntervalEnd, int replacementStrNewLength, List<ActionElement> actionElements) {
+		ListIterator<ActionElement> iterator = actionElements.listIterator();
+		int oldLength = relacementIntervalEnd - replacementIntervalStart;
+		int diff = replacementStrNewLength - oldLength;
+		while (iterator.hasNext()) {
+			ActionElement elem= iterator.next();
+			ReplacementStringIntervalStatus intervalStatus= elem.getIntervalStatus(replacementIntervalStart, relacementIntervalEnd);
+			int endDiff = relacementIntervalEnd - elem.end;
+			switch(intervalStatus) {
+				case AFTER:
+					//do nothing., nothing needs to be done here
+					break;
+				case BEFORE:
+					if (diff != 0) {
+						elem.start+= diff;
+						elem.end+= diff;
+					}
+					break;
+				case ENCOMPASS:
+					iterator.remove();
+					break;
+				case POST_OVERLAP:
+					elem.end= replacementIntervalStart;
+					break;
+				case PREV_OVERLAP:
+					elem.end += diff;
+					elem.start = relacementIntervalEnd + diff;
+					break;
+				case WITHIN:
+					// modify the old ActionElement to end before the replacement string start
+					// Create a new Element element to start from the replacement string end
+					int oldEnd = elem.end;
+					elem.end= replacementIntervalStart;
+					int newStart = oldEnd + endDiff + diff;
+					ActionElement newElem= new  ActionElement(newStart, oldEnd, elem.startTag, elem.endTag);
+					iterator.add(newElem);
+					break;
+				case DEFAULT:
+				default:
+					break;
+			}
+		}
+	}
+
+	private List<TagElement> getTagElementsForTextElement(TagElement snippetTag, TextElement textElement) {
+		List<TagElement> tagElements= new ArrayList<>();
+		List<JavaDocRegion> regions= snippetTag.tagRegionsStartingAtTextElement(textElement);
+		List<JavaDocRegion> masterList= snippetTag.tagRegionsContainingTextElement(textElement);
+		masterList.removeAll(regions);
+		for (JavaDocRegion region : masterList) {
+			for (Object tagObj : region.tags()) {
+				tagElements.add((TagElement) tagObj);
+			}
+		}
+		for (JavaDocRegion region : regions) {
+			for (Object tagObj : region.tags()) {
+				if (tagObj instanceof TagElement) {
+					TagElement tagElem= (TagElement) tagObj;
+					Object prop= tagElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
+					if (prop instanceof Integer) {
+						int val = ((Integer)prop).intValue();
+						ListIterator<TagElement> listIterator= tagElements.listIterator();
+						TagElement addBefore= null;
+						while (listIterator.hasNext()) {
+				           TagElement tElem=  listIterator.next();
+				           Object prop2= tElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
+				           if (prop2 instanceof Integer) {
+				        	   int val2 = ((Integer)prop2).intValue();
+				        	   if (val2 > val) {
+				        		   addBefore= tElem;
+				        		   break;
+				        	   }
+				           }
+				        }
+						if (addBefore == null) {
+							tagElements.add(tagElem);
+						} else {
+							tagElements.add(tagElements.indexOf(addBefore), tagElem);
+						}
+					}
+				}
+			}
+		}
+		return tagElements;
+	}
+
+	private List<TagElement> getTagElementsForDummyJavaDocRegion(TagElement snippetTag, JavaDocRegion javaDocRegion) {
+		List<TagElement> tagElements= new ArrayList<>();
+		TextElement textElement= (TextElement) javaDocRegion.fragments().get(0);
+		List<JavaDocRegion> regions= snippetTag.tagRegionsStartingAtTextElement(textElement);
+		List<JavaDocRegion> masterList= snippetTag.tagRegionsContainingTextElement(textElement);
+		masterList.removeAll(regions);
+		for (JavaDocRegion region : masterList) {
+			for (Object tagObj : region.tags()) {
+				tagElements.add((TagElement) tagObj);
+			}
+		}
+		regions.add(javaDocRegion);
+		for (JavaDocRegion region : regions) {
+			for (Object tagObj : region.tags()) {
+				if (tagObj instanceof TagElement) {
+					TagElement tagElem= (TagElement) tagObj;
+					Object prop= tagElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
+					if (prop instanceof Integer) {
+						int val = ((Integer)prop).intValue();
+						ListIterator<TagElement> listIterator= tagElements.listIterator();
+						TagElement addBefore= null;
+						while (listIterator.hasNext()) {
+				           TagElement tElem=  listIterator.next();
+				           Object prop2= tElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
+				           if (prop2 instanceof Integer) {
+				        	   int val2 = ((Integer)prop2).intValue();
+				        	   if (val2 > val) {
+				        		   addBefore= tElem;
+				        		   break;
+				        	   }
+				           }
+				        }
+						if (addBefore == null) {
+							tagElements.add(tagElem);
+						} else {
+							tagElements.add(tagElements.indexOf(addBefore), tagElem);
+						}
+					}
+				}
+			}
+		}
+
+		return tagElements;
+	}
+
+	private List<TagElement> getTagElementsForTagElement(TagElement snippetTag, TagElement tag) {
+		List<TagElement> tagElements= new ArrayList<>();
+		TextElement textElement= (TextElement) tag.fragments().get(0);
+		List<JavaDocRegion> regions= snippetTag.tagRegionsStartingAtTextElement(textElement);
+		List<JavaDocRegion> masterList= snippetTag.tagRegionsContainingTextElement(textElement);
+		masterList.removeAll(regions);
+		for (JavaDocRegion region : masterList) {
+			for (Object tagObj : region.tags()) {
+				tagElements.add((TagElement) tagObj);
+			}
+		}
+		for (JavaDocRegion region : regions) {
+			for (Object tagObj : region.tags()) {
+				if (tagObj instanceof TagElement) {
+					TagElement tagElem= (TagElement) tagObj;
+					Object prop= tagElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
+					if (prop instanceof Integer) {
+						int val = ((Integer)prop).intValue();
+						ListIterator<TagElement> listIterator= tagElements.listIterator();
+						TagElement addBefore= null;
+						while (listIterator.hasNext()) {
+				           TagElement tElem=  listIterator.next();
+				           Object prop2= tElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
+				           if (prop2 instanceof Integer) {
+				        	   int val2 = ((Integer)prop).intValue();
+				        	   if (val2 > val) {
+				        		   addBefore= tElem;
+				        		   break;
+				        	   }
+				           }
+				        }
+						if (addBefore == null) {
+							tagElements.add(tagElem);
+						} else {
+							tagElements.add(tagElements.indexOf(addBefore), tagElem);
+						}
+					}
+				}
+			}
+		}
+		Object prop3= tag.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
+		if (prop3 instanceof Integer) {
+			int val = ((Integer)prop3).intValue();
+			ListIterator<TagElement> listIterator= tagElements.listIterator();
+			TagElement addBefore= null;
+			while (listIterator.hasNext()) {
+		          TagElement tElem=  listIterator.next();
+		          Object prop2= tElem.getProperty(TagProperty.TAG_PROPERTY_SNIPPET_INLINE_TAG_COUNT);
+		          if (prop2 instanceof Integer) {
+		       	   int val2 = ((Integer)prop2).intValue();
+		       	   if (val2 > val) {
+		       		   addBefore= tElem;
+		       		   break;
+		       	   }
+		          }
+		       }
+			if (addBefore == null) {
+				tagElements.add(tag);
+			} else {
+				tagElements.add(tagElements.indexOf(addBefore), tag);
+			}
+		}
+		return tagElements;
+	}
+
+	private void handleSnippetHighlight(String text, TagElement tagElement, List<ActionElement> actionElements) {
+		try {
+			List<? extends TagProperty> tagProperties= tagElement.tagProperties();
+			String defHighlight= getHighlightHtmlTag(tagProperties);
+			String startDefHighlight = '<' + defHighlight + '>';
+			String endDefHighlight = "</" + defHighlight + '>'; //$NON-NLS-1$
+			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
+			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
+			Pattern regexPattern = null;
+			if (regExValue != null) {
+				regexPattern = Pattern.compile(regExValue);
+			}
+			if (regexPattern != null) {
+				Matcher matcher = regexPattern.matcher(text);
+				while (matcher.find()) {
+					actionElements.add(new ActionElement(matcher.start(), matcher.end(), startDefHighlight, endDefHighlight));
+				}
+			} else if (subStringValue != null) {
+				int startIndex = 0;
+				while ((startIndex = text.indexOf(subStringValue, startIndex)) != -1) {
+					actionElements.add(new ActionElement(startIndex, startIndex + subStringValue.length(), startDefHighlight, endDefHighlight));
+					startIndex += subStringValue.length();
+				}
+			} else {
+				actionElements.add(new ActionElement(0, text.length(), startDefHighlight, endDefHighlight));
+			}
+			return;
+		} catch (PatternSyntaxException e) {
+			// do nothing
+		}
+		return;
+	}
+
+	private String handleSnippetReplace(String text, TagElement tagElement, List<ActionElement> actionElements) {
+		try {
+			List<? extends TagProperty> tagProperties= tagElement.tagProperties();
+			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
+			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
+			String substitution = getPropertyValue("replacement", tagProperties); //$NON-NLS-1$
+			Pattern regexPattern = null;
+			if (regExValue != null) {
+				regexPattern = Pattern.compile(regExValue);
+			}
+			String modifiedText = text;
+			if (regexPattern != null) {
+				Matcher matcher = regexPattern.matcher(modifiedText);
+				StringBuilder strBuild= new StringBuilder();
+				int finalMatchIndex = 0;
+				while (matcher.find()) {
+					finalMatchIndex = matcher.end();
+					modifyPrevActionItemsReplacement(matcher.start(), matcher.end(), substitution.length(), actionElements);
+					matcher.appendReplacement(strBuild, substitution);
+				}
+				modifiedText = strBuild.toString() + modifiedText.substring(finalMatchIndex);
+			} else if (subStringValue != null) {
+				int startIndex = 0;
+				while ((startIndex = modifiedText.indexOf(subStringValue, startIndex)) != -1) {
+					modifyPrevActionItemsReplacement(startIndex, startIndex+ subStringValue.length(), substitution.length(), actionElements);
+					modifiedText = modifiedText.substring(0, startIndex) + substitution + modifiedText.substring(startIndex + subStringValue.length());
+					startIndex += substitution.length() ;
+				}
+			} else {
+				actionElements.clear();
+				modifiedText = substitution;
+			}
+			return modifiedText;
+		} catch (PatternSyntaxException e) {
+			// do nothing
+		}
+		return text;
+	}
+
+
+	private void handleSnippetLink(String text, TagElement tagElement, List<ActionElement> actionElements) {
+		try {
+			List<? extends TagProperty> tagProperties= tagElement.tagProperties();
+			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
+			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
+			String additionalStartTag= getLinkHtmlTag(tagProperties);
+			String additionalEndTag= ""; //$NON-NLS-1$
+			if (additionalStartTag.length() > 0) {
+				additionalEndTag= "</" + additionalStartTag + '>'; //$NON-NLS-1$
+				additionalStartTag= '<' + additionalStartTag + '>';
+			}
+			ASTNode target = getPropertyNodeValue("target", tagProperties); //$NON-NLS-1$
+			String linkRefTxt = getLinkRef(target);
+			String startDefLink = linkRefTxt + additionalStartTag;
+			String endDefLink = additionalEndTag+"</a>"; //$NON-NLS-1$
+			Pattern regexPattern = null;
+			if (regExValue != null) {
+				regexPattern = Pattern.compile(regExValue);
+			}
+			String modifiedText = text;
+			if (regexPattern != null) {
+				Matcher matcher = regexPattern.matcher(modifiedText);
+				while (matcher.find()) {
+					actionElements.add(new ActionElement(matcher.start(), matcher.end(), startDefLink, endDefLink));
+				}
+			} else if (subStringValue != null) {
+				int startIndex = 0;
+				while ((startIndex = modifiedText.indexOf(subStringValue, startIndex)) != -1) {
+					actionElements.add(new ActionElement(startIndex, startIndex+ subStringValue.length(), startDefLink, endDefLink));
+					startIndex = startIndex+ subStringValue.length() ;
+				}
+			} else {
+				String subText = modifiedText.trim();
+				if (subText.length() < text.length()) {
+					int startIndex = text.indexOf(subText);
+					actionElements.add(new ActionElement(startIndex, startIndex + subText.length(), startDefLink, endDefLink));
+				}
+			}
+			return;
+		} catch (PatternSyntaxException e) {
+			// do nothing
+		}
+		return;
+	}
+
+	private String getLinkRef(ASTNode node) {
+		String str= ""; //$NON-NLS-1$
+		String refTypeName= null;
+		String refMemberName= null;
+		String[] refMethodParamTypes= null;
+		String[] refMethodParamNames= null;
+		if (node instanceof Name) {
+			Name name = (Name) node;
+			refTypeName= name.getFullyQualifiedName();
+		} else if (node instanceof MemberRef) {
+			MemberRef memberRef= (MemberRef) node;
+			Name qualifier= memberRef.getQualifier();
+			refTypeName= qualifier == null ? "" : qualifier.getFullyQualifiedName(); //$NON-NLS-1$
+			refMemberName= memberRef.getName().getIdentifier();
+		} else if (node instanceof MethodRef) {
+			MethodRef methodRef= (MethodRef) node;
+			Name qualifier= methodRef.getQualifier();
+			refTypeName= qualifier == null ? "" : qualifier.getFullyQualifiedName(); //$NON-NLS-1$
+			refMemberName= methodRef.getName().getIdentifier();
+			List<MethodRefParameter> params= methodRef.parameters();
+			int ps= params.size();
+			refMethodParamTypes= new String[ps];
+			refMethodParamNames= new String[ps];
+			for (int i= 0; i < ps; i++) {
+				MethodRefParameter param= params.get(i);
+				refMethodParamTypes[i]= ASTNodes.asString(param.getType());
+				SimpleName paramName= param.getName();
+				if (paramName != null)
+					refMethodParamNames[i]= paramName.getIdentifier();
+			}
+		}
+
+		if (refTypeName != null) {
+			str +="<a href='"; //$NON-NLS-1$
+			try {
+				String scheme= JavaElementLinks.JAVADOC_SCHEME;
+				String uri= JavaElementLinks.createURI(scheme, fElement, refTypeName, refMemberName, refMethodParamTypes);
+				str += uri;
+			} catch (URISyntaxException e) {
+				JavaPlugin.log(e);
+			}
+			str += "'>"; //$NON-NLS-1$
+		}
+		return str;
+	}
+
+	private String getLinkHtmlTag(List<? extends ASTNode> tagProperties) {
+		String defaultTag= "code"; //$NON-NLS-1$
+		if (tagProperties != null) {
+			for (ASTNode node : tagProperties) {
+				if (node instanceof TagProperty) {
+					TagProperty tagProp = (TagProperty) node;
+					if ("type".equals(tagProp.getName())) { //$NON-NLS-1$
+						String tagValue = stripQuotes(tagProp.getStringValue());
+						switch (tagValue) {
+							case "linkplain" :  //$NON-NLS-1$
+								defaultTag= ""; //$NON-NLS-1$
+								break;
+							default:
+								break;
+						}
+						break;
+					}
+				}
+			}
+		}
+		return defaultTag;
+	}
+
+	private String getPropertyValue(String property, List<? extends ASTNode> tagProperties) {
+		String defaultTag= null;
+		if (tagProperties != null && property!= null) {
+			for (ASTNode node : tagProperties) {
+				if (node instanceof TagProperty) {
+					TagProperty tagProp = (TagProperty) node;
+					if (property.equals(tagProp.getName())) {
+						defaultTag= stripQuotes(tagProp.getStringValue());
+						break;
+					}
+				}
+			}
+		}
+		return defaultTag;
+	}
+	private ASTNode getPropertyNodeValue(String property, List<? extends ASTNode> tagProperties) {
+		ASTNode defaultTag= null;
+		if (tagProperties != null && property!= null) {
+			for (ASTNode node : tagProperties) {
+				if (node instanceof TagProperty) {
+					TagProperty tagProp = (TagProperty) node;
+					if (property.equals(tagProp.getName())) {
+						defaultTag= tagProp.getNodeValue();
+						break;
+					}
+				}
+			}
+		}
+		return defaultTag;
+	}
+
+	private String stripQuotes (String str) {
+		String newStr = str;
+		if (str != null && str.length() >= 2) {
+			int length = str.length();
+			if ((str.charAt(0) == '"' && str.charAt(length-1) == '"')
+					|| (str.charAt(0) == '\'' && str.charAt(length-1) == '\'')) {
+				newStr = str.substring(1, length-1);
+			}
+		}
+		return newStr;
+	}
+
+	private String getHighlightHtmlTag(List<? extends ASTNode> tagProperties) {
+		String defaultTag= "b"; //$NON-NLS-1$
+		if (tagProperties != null) {
+			for (ASTNode node : tagProperties) {
+				if (node instanceof TagProperty) {
+					TagProperty tagProp = (TagProperty) node;
+					if ("type".equals(tagProp.getName())) { //$NON-NLS-1$
+						String tagValue = stripQuotes(tagProp.getStringValue());
+						switch (tagValue) {
+							case "bold" :  //$NON-NLS-1$
+								defaultTag= "b"; //$NON-NLS-1$
+								break;
+							case "italic" :  //$NON-NLS-1$
+								defaultTag= "i"; //$NON-NLS-1$
+								break;
+							case "highlighted" :  //$NON-NLS-1$
+								defaultTag= "mark"; //$NON-NLS-1$
+								break;
+							default :
+								defaultTag= ""; //$NON-NLS-1$
+								break;
+						}
+						break;
+					}
+				}
+			}
+		}
+		return defaultTag;
+	}
+
+}
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavadocContentAccess2.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavadocContentAccess2.java
index 369411b..a8bbc67 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavadocContentAccess2.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/javadoc/JavadocContentAccess2.java
@@ -34,9 +34,6 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
@@ -90,7 +87,6 @@
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.core.dom.IBinding;
 import org.eclipse.jdt.core.dom.IVariableBinding;
-import org.eclipse.jdt.core.dom.JavaDocRegion;
 import org.eclipse.jdt.core.dom.Javadoc;
 import org.eclipse.jdt.core.dom.MemberRef;
 import org.eclipse.jdt.core.dom.MethodRef;
@@ -461,6 +457,8 @@
 	 */
 	private final IJavaElement fElement;
 
+	private final JavaDocSnippetStringEvaluator fSnippetStringEvaluator;
+
 	/**
 	 * The method, or <code>null</code> if {@link #fElement} is not a method where @inheritDoc could
 	 * work.
@@ -482,6 +480,7 @@
 		Assert.isNotNull(element);
 		Assert.isTrue(element instanceof IMethod || element instanceof ILocalVariable || element instanceof ITypeParameter);
 		fElement= element;
+		fSnippetStringEvaluator= new JavaDocSnippetStringEvaluator(fElement);
 		fMethod= (IMethod) ((element instanceof ILocalVariable || element instanceof ITypeParameter) ? element.getParent() : element);
 		fJavadoc= javadoc;
 		fSource= source;
@@ -491,6 +490,7 @@
 	private JavadocContentAccess2(IJavaElement element, Javadoc javadoc, String source) {
 		Assert.isTrue(element instanceof IMember || element instanceof IPackageFragment || element instanceof ILocalVariable || element instanceof ITypeParameter);
 		fElement= element;
+		fSnippetStringEvaluator= new JavaDocSnippetStringEvaluator(fElement);
 		fMethod= null;
 		fJavadoc= javadoc;
 		fSource= source;
@@ -1931,22 +1931,7 @@
 				if (fs > 0) {
 					fBuf.append("<pre><code>"); //$NON-NLS-1$
 					fBuf.append(BlOCK_TAG_ENTRY_START);
-					for(Object fragment : node.fragments()) {
-						if (fragment instanceof  TextElement) {
-							TextElement memberRef= (TextElement) fragment;
-							fBuf.append(getTextElementString(node, memberRef));
-						} else if (fragment instanceof TagElement) {
-							TagElement tagElem= (TagElement) fragment;
-							String str= getSnippetTagElementString(node, tagElem);
-							fBuf.append(str);
-						} else if (fragment instanceof JavaDocRegion) {
-							JavaDocRegion region= (JavaDocRegion) fragment;
-							if (region.isDummyRegion()) {
-								String str = getDummyJavadocRegionString(region, node);
-								fBuf.append(str);
-							}
-						}
-					}
+					fSnippetStringEvaluator.AddTagElementString(node, fBuf);
 					fBuf.append(BlOCK_TAG_ENTRY_END);
 				}
 			} else {
@@ -1955,474 +1940,11 @@
 		}
 	}
 
-	private String getTextElementString(TagElement snippetTag, TextElement textElem) {
-		String text = textElem.getText();
-		String changedText = text;
-		List<JavaDocRegion> regions= snippetTag.tagRegionsContainingTextElement(textElem);
-		for (JavaDocRegion region : regions) {
-			changedText = getJavaDocRegionString(region, changedText);
-		}
-		return changedText;
-	}
-
-	private String getJavaDocRegionString(JavaDocRegion region, String str) {
-		String changedText = ""; //$NON-NLS-1$
-		if (region != null && str != null) {
-			changedText = str;
-			List<Object> tags= region.tags();
-			for (Object tag : tags) {
-				if (tag instanceof TagElement) {
-					TagElement tagElem = (TagElement) tag;
-					String name= tagElem.getTagName();
-					if (TagElement.TAG_HIGHLIGHT.equals(name)) {
-						changedText= handleSnippetHighlight(changedText, tagElem.tagProperties());
-					} else if (TagElement.TAG_REPLACE.equals(name)) {
-						changedText= handleSnippetReplace(changedText, tagElem.tagProperties());
-					} else if (TagElement.TAG_LINK.equals(name)) {
-						changedText= handleSnippetLink(changedText, tagElem.tagProperties());
-					}
-				}
-			}
-		}
-		return changedText;
-	}
-
-	private String getSnippetTagElementString(TagElement snippetTag, TagElement tagElem) {
-		String str= ""; //$NON-NLS-1$
-		if (tagElem != null) {
-			List<Object> fragments = tagElem.fragments();
-			for (Object fragment : fragments) {
-				if (fragment instanceof TextElement) {
-					str = ((TextElement)fragment).getText();
-					List<JavaDocRegion> regions= getRegionsBeforeASTNode(snippetTag,(TextElement)fragment, tagElem);
-					for (JavaDocRegion region : regions) {
-						str = getJavaDocRegionString(region, str);
-					}
-					String name= tagElem.getTagName();
-					if (TagElement.TAG_HIGHLIGHT.equals(name)) {
-						str= handleSnippetHighlight(str, tagElem.tagProperties());
-					} else if (TagElement.TAG_REPLACE.equals(name)) {
-						str= handleSnippetReplace(str, tagElem.tagProperties());
-					}  else if (TagElement.TAG_LINK.equals(name)) {
-						str= handleSnippetLink(str, tagElem.tagProperties());
-					}
-					regions= getRegionsAfterASTNode(snippetTag,(TextElement)fragment, tagElem);
-					for (JavaDocRegion region : regions) {
-						str = getJavaDocRegionString(region, str);
-					}
-				}
-			}
-
-		}
-		return str;
-	}
-
-	private List<JavaDocRegion> getRegionsBeforeASTNode(TagElement snippetTag,TextElement textElement, ASTNode node) {
-		List<JavaDocRegion> regions= snippetTag.tagRegionsContainingTextElement(textElement);
-		List<JavaDocRegion> regionsBefore = new ArrayList<>();
-		int nodeStart = node.getStartPosition();
-		for (JavaDocRegion region : regions) {
-			for (Object tagObj : region.tags()) {
-				if (tagObj instanceof TagElement) {
-					int start = ((TagElement)tagObj).getStartPosition();
-					if (start < nodeStart) {
-						regionsBefore.add(region);
-						break;
-					}
-				}
-			}
-		}
-		return regionsBefore;
-	}
-
-	private List<JavaDocRegion> getRegionsAfterASTNode(TagElement snippetTag,TextElement textElement, ASTNode node) {
-		List<JavaDocRegion> regions= snippetTag.tagRegionsContainingTextElement(textElement);
-		List<JavaDocRegion> regionsAfter = new ArrayList<>();
-		int nodeStart = node.getStartPosition();
-		for (JavaDocRegion region : regions) {
-			for (Object tagObj : region.tags()) {
-				if (tagObj instanceof TagElement) {
-					int start = ((TagElement)tagObj).getStartPosition();
-					if (start > nodeStart) {
-						regionsAfter.add(region);
-						break;
-					}
-				}
-			}
-		}
-		return regionsAfter;
-	}
-
-	private String getDummyJavadocRegionString(JavaDocRegion jregion, TagElement snippetTag) {
-		String str= ""; //$NON-NLS-1$
-		if (jregion != null) {
-			List<Object> tags = jregion.tags();
-			List<Object> fragments = jregion.fragments();
-			if (fragments.size() == 0) {
-				return str;
-			}
-			for (Object fragment: fragments) {
-				if (fragment instanceof TextElement) {
-					String textStr = ((TextElement)fragment).getText();
-					List<JavaDocRegion> regions= getRegionsBeforeASTNode(snippetTag,(TextElement)fragment, jregion);
-					for (JavaDocRegion region : regions) {
-						textStr = getJavaDocRegionString(region, textStr);
-					}
-					if (textStr.length() > 0 && tags.size() > 0)  {
-						for (Object tag : tags) {
-							if (tag instanceof TagElement) {
-								TagElement tagElem= (TagElement) tag;
-								String name= tagElem.getTagName();
-								if (TagElement.TAG_HIGHLIGHT.equals(name)) {
-									textStr= handleSnippetHighlight(textStr, tagElem.tagProperties());
-								} else if (TagElement.TAG_REPLACE.equals(name)) {
-									textStr= handleSnippetReplace(textStr, tagElem.tagProperties());
-								} else if (TagElement.TAG_LINK.equals(name)) {
-									textStr= handleSnippetLink(textStr, tagElem.tagProperties());
-								}
-							}
-						}
-					}
-					regions= getRegionsAfterASTNode(snippetTag,(TextElement)fragment, jregion);
-					for (JavaDocRegion region : regions) {
-						textStr = getJavaDocRegionString(region, textStr);
-					}
-					str += textStr;
-				}
-				if (fragment instanceof JavaDocRegion) {
-					str += getDummyJavadocRegionString((JavaDocRegion)fragment, snippetTag);
-				}
-			}
-		}
-		return str;
-	}
-
 	private void handleInvalidSnippet() {
 		fBuf.append("<pre><code>\n"); //$NON-NLS-1$
 		fBuf.append("<mark>invalid @Snippet</mark>"); //$NON-NLS-1$
 	}
 
-	private String handleSnippetReplace(String text, List<? extends ASTNode> tagProperties) {
-		try {
-			boolean process = arePropertyValuesStringLiterals(tagProperties) ? true : false;
-			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
-			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
-			String substitution = getPropertyValue("replacement", tagProperties); //$NON-NLS-1$
-			Pattern regexPattern = null;
-			if (regExValue != null) {
-				regexPattern = Pattern.compile(regExValue);
-			}
-			String modifiedText = text;
-			if (process) {
-				if (regexPattern != null && process) {
-					Matcher matcher = regexPattern.matcher(modifiedText);
-					StringBuilder strBuild= new StringBuilder();
-					int finalMatchIndex = 0;
-					while (matcher.find()) {
-						finalMatchIndex = matcher.end();
-						matcher.appendReplacement(strBuild, substitution);
-					}
-					modifiedText = strBuild.toString() + modifiedText.substring(finalMatchIndex);
-				} else if (subStringValue != null) {
-					int startIndex = 0;
-					while (true) {
-						startIndex = modifiedText.indexOf(subStringValue, startIndex);
-						if (startIndex == -1) {
-							break;
-						} else {
-							modifiedText = modifiedText.substring(0, startIndex) + substitution + modifiedText.substring(startIndex + subStringValue.length());
-							startIndex = startIndex + substitution.length() ;
-						}
-					}
-				} else {
-					modifiedText = substitution;
-				}
-			}
-			return modifiedText;
-		} catch (PatternSyntaxException e) {
-			// do nothing
-		}
-		return text;
-	}
-
-	private String handleSnippetHighlight(String text, List<? extends ASTNode> tagProperties) {
-		try {
-			String defHighlight= getHighlightHtmlTag(tagProperties);
-			String startDefHighlight = '<' + defHighlight + '>';
-			String endDefHighlight = "</" + defHighlight + '>'; //$NON-NLS-1$
-			boolean process = true;
-			if (defHighlight.length() == 0 || !arePropertyValuesStringLiterals(tagProperties)) {
-				process = false;
-			}
-			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
-			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
-			int additionalLength = startDefHighlight.length() + endDefHighlight.length();
-			Pattern regexPattern = null;
-			if (regExValue != null) {
-				regexPattern = Pattern.compile(regExValue);
-			}
-			String modifiedText = text;
-			if (process) {
-				if (regexPattern != null && process) {
-					Matcher matcher = regexPattern.matcher(modifiedText);
-					StringBuilder strBuild= new StringBuilder();
-					int finalMatchIndex = 0;
-					while (matcher.find()) {
-						finalMatchIndex = matcher.end();
-						String replacementStr= startDefHighlight + modifiedText.substring(matcher.start(), matcher.end()) + endDefHighlight;
-						matcher.appendReplacement(strBuild, replacementStr);
-					}
-					modifiedText = strBuild.toString() + modifiedText.substring(finalMatchIndex);
-				} else if (subStringValue != null) {
-					int startIndex = 0;
-					while (true) {
-						startIndex = modifiedText.indexOf(subStringValue, startIndex);
-						if (startIndex == -1) {
-							break;
-						} else {
-							modifiedText = modifiedText.substring(0, startIndex) + startDefHighlight + subStringValue + endDefHighlight + modifiedText.substring(startIndex + subStringValue.length());
-							startIndex = startIndex + subStringValue.length() + additionalLength;
-						}
-					}
-				} else {
-					modifiedText = startDefHighlight + modifiedText + endDefHighlight;
-				}
-			}
-			return modifiedText;
-		} catch (PatternSyntaxException e) {
-			// do nothing
-		}
-		return text;
-	}
-
-	private String handleSnippetLink(String text, List<? extends ASTNode> tagProperties) {
-		try {
-			String regExValue = getPropertyValue("regex", tagProperties); //$NON-NLS-1$
-			String subStringValue = getPropertyValue("substring", tagProperties); //$NON-NLS-1$
-			String additionalStartTag= getLinkHtmlTag(tagProperties);
-			String additionalEndTag= ""; //$NON-NLS-1$
-			if (additionalStartTag.length() > 0) {
-				additionalEndTag= "</" + additionalStartTag + '>'; //$NON-NLS-1$
-				additionalStartTag= '<' + additionalStartTag + '>';
-			}
-			ASTNode target = getPropertyNodeValue("target", tagProperties); //$NON-NLS-1$
-			String linkRefTxt = getLinkRef(target);
-			String startDefLink = linkRefTxt + additionalStartTag;
-			String endDefLink = additionalEndTag+"</a>"; //$NON-NLS-1$
-			int additionalLength = startDefLink.length() + endDefLink.length();
-			Pattern regexPattern = null;
-			if (regExValue != null) {
-				regexPattern = Pattern.compile(regExValue);
-			}
-			String modifiedText = text;
-			if (regexPattern != null) {
-				Matcher matcher = regexPattern.matcher(modifiedText);
-				StringBuilder strBuild= new StringBuilder();
-				int finalMatchIndex = 0;
-				while (matcher.find()) {
-					finalMatchIndex = matcher.end();
-					String replacementStr= startDefLink + modifiedText.substring(matcher.start(), matcher.end()) + endDefLink;
-					matcher.appendReplacement(strBuild, replacementStr);
-				}
-				modifiedText = strBuild.toString() + modifiedText.substring(finalMatchIndex);
-			} else if (subStringValue != null) {
-				int startIndex = 0;
-				while (true) {
-					startIndex = modifiedText.indexOf(subStringValue, startIndex);
-					if (startIndex == -1) {
-						break;
-					} else {
-						modifiedText = modifiedText.substring(0, startIndex) + startDefLink + subStringValue + endDefLink + modifiedText.substring(startIndex + subStringValue.length());
-						startIndex = startIndex + subStringValue.length() + additionalLength;
-					}
-				}
-			} else {
-				String subText = modifiedText.trim();
-				String pre = ""; //$NON-NLS-1$
-				String post = ""; //$NON-NLS-1$
-				if (subText.length() < text.length()) {
-					int index = text.indexOf(subText);
-					if (index > 0) {
-						pre = text.substring(0, index);
-						post = text.substring(index + subText.length());
-					}
-				}
-				modifiedText = pre + startDefLink + subText + endDefLink + post;
-			}
-			return modifiedText;
-		} catch (PatternSyntaxException e) {
-			// do nothing
-		}
-		return text;
-	}
-
-	private String getLinkRef(ASTNode node) {
-		String str= ""; //$NON-NLS-1$
-		String refTypeName= null;
-		String refMemberName= null;
-		String[] refMethodParamTypes= null;
-		String[] refMethodParamNames= null;
-		if (node instanceof Name) {
-			Name name = (Name) node;
-			refTypeName= name.getFullyQualifiedName();
-		} else if (node instanceof MemberRef) {
-			MemberRef memberRef= (MemberRef) node;
-			Name qualifier= memberRef.getQualifier();
-			refTypeName= qualifier == null ? "" : qualifier.getFullyQualifiedName(); //$NON-NLS-1$
-			refMemberName= memberRef.getName().getIdentifier();
-		} else if (node instanceof MethodRef) {
-			MethodRef methodRef= (MethodRef) node;
-			Name qualifier= methodRef.getQualifier();
-			refTypeName= qualifier == null ? "" : qualifier.getFullyQualifiedName(); //$NON-NLS-1$
-			refMemberName= methodRef.getName().getIdentifier();
-			List<MethodRefParameter> params= methodRef.parameters();
-			int ps= params.size();
-			refMethodParamTypes= new String[ps];
-			refMethodParamNames= new String[ps];
-			for (int i= 0; i < ps; i++) {
-				MethodRefParameter param= params.get(i);
-				refMethodParamTypes[i]= ASTNodes.asString(param.getType());
-				SimpleName paramName= param.getName();
-				if (paramName != null)
-					refMethodParamNames[i]= paramName.getIdentifier();
-			}
-		}
-
-		if (refTypeName != null) {
-			str +="<a href='"; //$NON-NLS-1$
-			try {
-				String scheme= JavaElementLinks.JAVADOC_SCHEME;
-				String uri= JavaElementLinks.createURI(scheme, fElement, refTypeName, refMemberName, refMethodParamTypes);
-				str += uri;
-			} catch (URISyntaxException e) {
-				JavaPlugin.log(e);
-			}
-			str += "'>"; //$NON-NLS-1$
-		}
-		return str;
-	}
-
-	private String getHighlightHtmlTag(List<? extends ASTNode> tagProperties) {
-		String defaultTag= "b"; //$NON-NLS-1$
-		if (tagProperties != null) {
-			for (ASTNode node : tagProperties) {
-				if (node instanceof TagProperty) {
-					TagProperty tagProp = (TagProperty) node;
-					if ("type".equals(tagProp.getName())) { //$NON-NLS-1$
-						String tagValue = stripQuotes(tagProp.getStringValue());
-						switch (tagValue) {
-							case "bold" :  //$NON-NLS-1$
-								defaultTag= "b"; //$NON-NLS-1$
-								break;
-							case "italic" :  //$NON-NLS-1$
-								defaultTag= "i"; //$NON-NLS-1$
-								break;
-							case "highlighted" :  //$NON-NLS-1$
-								defaultTag= "mark"; //$NON-NLS-1$
-								break;
-							default :
-								defaultTag= ""; //$NON-NLS-1$
-								break;
-						}
-						break;
-					}
-				}
-			}
-		}
-		return defaultTag;
-	}
-
-	private String getLinkHtmlTag(List<? extends ASTNode> tagProperties) {
-		String defaultTag= "code"; //$NON-NLS-1$
-		if (tagProperties != null) {
-			for (ASTNode node : tagProperties) {
-				if (node instanceof TagProperty) {
-					TagProperty tagProp = (TagProperty) node;
-					if ("type".equals(tagProp.getName())) { //$NON-NLS-1$
-						String tagValue = stripQuotes(tagProp.getStringValue());
-						switch (tagValue) {
-							case "linkplain" :  //$NON-NLS-1$
-								defaultTag= ""; //$NON-NLS-1$
-								break;
-							default:
-								break;
-						}
-						break;
-					}
-				}
-			}
-		}
-		return defaultTag;
-	}
-
-	private boolean arePropertyValuesStringLiterals(List<? extends ASTNode> tagProperties) {
-		boolean val= true;
-		if (tagProperties != null) {
-			final String SUBSTRING = "substring"; //$NON-NLS-1$
-			final String REGEX = "regex"; //$NON-NLS-1$
-			final String TYPE = "type"; //$NON-NLS-1$
-			for (ASTNode node : tagProperties) {
-				if (node instanceof TagProperty) {
-					TagProperty tagProp = (TagProperty) node;
-					String propName = tagProp.getName();
-					if (SUBSTRING.equals(propName)
-							|| REGEX.equals(propName)
-							|| TYPE.equals(propName)) {
-						String value= tagProp.getStringValue();
-						String changed= stripQuotes(value);
-						if (changed.equals(value)) {
-							val= false;
-							break;
-						}
-					}
-				}
-			}
-		}
-		return val;
-	}
-	private String getPropertyValue(String property, List<? extends ASTNode> tagProperties) {
-		String defaultTag= null;
-		if (tagProperties != null && property!= null) {
-			for (ASTNode node : tagProperties) {
-				if (node instanceof TagProperty) {
-					TagProperty tagProp = (TagProperty) node;
-					if (property.equals(tagProp.getName())) {
-						defaultTag= stripQuotes(tagProp.getStringValue());
-						break;
-					}
-				}
-			}
-		}
-		return defaultTag;
-	}
-	private ASTNode getPropertyNodeValue(String property, List<? extends ASTNode> tagProperties) {
-		ASTNode defaultTag= null;
-		if (tagProperties != null && property!= null) {
-			for (ASTNode node : tagProperties) {
-				if (node instanceof TagProperty) {
-					TagProperty tagProp = (TagProperty) node;
-					if (property.equals(tagProp.getName())) {
-						defaultTag= tagProp.getNodeValue();
-						break;
-					}
-				}
-			}
-		}
-		return defaultTag;
-	}
-
-	private String stripQuotes (String str) {
-		String newStr = str;
-		if (str != null && str.length() >= 2) {
-			int length = str.length();
-			if ((str.charAt(0) == '"' && str.charAt(length-1) == '"')
-					|| (str.charAt(0) == '\'' && str.charAt(length-1) == '\'')) {
-				newStr = str.substring(1, length-1);
-			}
-		}
-		return newStr;
-	}
-
 	private void handleIndex(List<? extends ASTNode> fragments) {
 		int fs= fragments.size();
 		if (fs > 0) {