### Eclipse Workspace Patch 1.0 #P org.eclipse.mylyn.bugzilla.tests Index: src/org/eclipse/mylyn/bugzilla/tests/AllBugzillaTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/AllBugzillaTests.java,v retrieving revision 1.56 diff -u -r1.56 AllBugzillaTests.java --- src/org/eclipse/mylyn/bugzilla/tests/AllBugzillaTests.java 13 May 2010 14:41:32 -0000 1.56 +++ src/org/eclipse/mylyn/bugzilla/tests/AllBugzillaTests.java 26 May 2010 03:34:37 -0000 @@ -17,6 +17,7 @@ import org.eclipse.mylyn.bugzilla.tests.core.BugzillaPriorityTest; import org.eclipse.mylyn.bugzilla.tests.core.BugzillaXMLRPCTest; import org.eclipse.mylyn.bugzilla.tests.support.BugzillaFixture; +import org.eclipse.mylyn.bugzilla.tests.ui.BugzillaHyperlinkDetectorTest; import org.eclipse.mylyn.bugzilla.tests.ui.BugzillaRepositorySettingsPageTest; import org.eclipse.mylyn.bugzilla.tests.ui.BugzillaSearchPageTest; import org.eclipse.mylyn.bugzilla.tests.ui.BugzillaTaskHyperlinkDetectorTest; @@ -40,6 +41,7 @@ suite.addTestSuite(BugzillaSearchPageTest.class); suite.addTestSuite(BugzillaDateTimeTests.class); suite.addTestSuite(BugzillaTaskHyperlinkDetectorTest.class); + suite.addTestSuite(BugzillaHyperlinkDetectorTest.class); // Each of these tests gets executed against every repo in BugzillaFixture.ALL // unless otherwise excluded Index: src/org/eclipse/mylyn/bugzilla/tests/ui/BugzillaTaskHyperlinkDetectorTest.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.tests/src/org/eclipse/mylyn/bugzilla/tests/ui/BugzillaTaskHyperlinkDetectorTest.java,v retrieving revision 1.7 diff -u -r1.7 BugzillaTaskHyperlinkDetectorTest.java --- src/org/eclipse/mylyn/bugzilla/tests/ui/BugzillaTaskHyperlinkDetectorTest.java 24 May 2010 23:33:44 -0000 1.7 +++ src/org/eclipse/mylyn/bugzilla/tests/ui/BugzillaTaskHyperlinkDetectorTest.java 26 May 2010 03:34:37 -0000 @@ -339,7 +339,7 @@ assertEquals("123", taskLink.getTaskId()); assertEquals(testString.indexOf(format), taskLink.getHyperlinkRegion().getOffset()); Object comment = taskLink.getSelection(); - assertNotNull(comment); + assertNotNull(format, comment); assertEquals(TaskAttribute.PREFIX_COMMENT + "44556677", comment); } for (String format : commentFormats) { @@ -657,4 +657,15 @@ assertEquals(1, links.length); assertEquals(testString.indexOf(ATTACHMENT_NUMBER), links[0].getHyperlinkRegion().getOffset()); } + + public void testCommentLotsOfWhitespace() { + String testString = "bug 123 d bug 245 comment 1"; + viewer.setDocument(new Document(testString)); + Region region = new Region(0, testString.length()); + IHyperlink[] links = detector.detectHyperlinks(viewer, region, false); + assertNotNull(links); + assertEquals(1, links.length); + assertEquals(testString.indexOf(ATTACHMENT_NUMBER), links[0].getHyperlinkRegion().getOffset()); + } + } Index: src/org/eclipse/mylyn/bugzilla/tests/ui/BugzillaHyperlinkDetectorTest.java =================================================================== RCS file: src/org/eclipse/mylyn/bugzilla/tests/ui/BugzillaHyperlinkDetectorTest.java diff -N src/org/eclipse/mylyn/bugzilla/tests/ui/BugzillaHyperlinkDetectorTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/bugzilla/tests/ui/BugzillaHyperlinkDetectorTest.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,153 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.bugzilla.tests.ui; + +import junit.framework.TestCase; + +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.hyperlink.IHyperlink; +import org.eclipse.mylyn.internal.bugzilla.core.BugzillaCorePlugin; +import org.eclipse.mylyn.internal.bugzilla.ui.TaskAttachmentHyperlink; +import org.eclipse.mylyn.internal.bugzilla.ui.tasklist.BugzillaConnectorUi; +import org.eclipse.mylyn.internal.tasks.core.TaskTask; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.core.data.TaskAttribute; +import org.eclipse.mylyn.tasks.ui.TaskHyperlink; + +/** + * @author Steffen Pingel + */ +public class BugzillaHyperlinkDetectorTest extends TestCase { + + private BugzillaConnectorUi connector; + + private TaskRepository repository; + + private TaskTask task; + + private TaskAttachmentHyperlink alink(int offset, int length, String attachmentId) { + TaskAttachmentHyperlink link = new TaskAttachmentHyperlink(new Region(offset, length), repository, attachmentId); + return link; + } + + private void assertHyperlinks(String string, IHyperlink... expected) { + IHyperlink[] links = connector.findHyperlinks(repository, task, string, -1, 0); + if (expected.length == 0) { + assertNull(links); + return; + } + assertNotNull("Expected hyperlinks in " + string, links); + assertEquals(expected.length, links.length); + for (int i = 0; i < links.length; i++) { + assertEquals(expected[i], links[i]); + } + } + + private TaskHyperlink link(int offset, int length, String taskId) { + return link(offset, length, taskId, null); + } + + private TaskHyperlink link(int offset, int length, String taskId, String commentId) { + TaskHyperlink link = new TaskHyperlink(new Region(offset, length), repository, taskId); + if (commentId != null) { + link.setSelection(TaskAttribute.PREFIX_COMMENT + commentId); + } + return link; + } + + @Override + protected void setUp() throws Exception { + repository = new TaskRepository(BugzillaCorePlugin.CONNECTOR_KIND, "http://localhost"); + task = new TaskTask(BugzillaCorePlugin.CONNECTOR_KIND, "http://localhost", "123"); + connector = new BugzillaConnectorUi(); + } + + public void testFindHyperlinksAttachment() { + assertHyperlinks("attachment 123", alink(0, 14, "123")); + assertHyperlinks("attachment 123", alink(0, 15, "123")); + assertHyperlinks("attachment # 123", alink(0, 17, "123")); + assertHyperlinks("attachment#1", alink(0, 12, "1")); + assertHyperlinks("attachment (id=123)", alink(0, 19, "123")); + assertHyperlinks("Created attachment 123", alink(0, 22, "123")); + assertHyperlinks("Created an attachment 123", alink(0, 25, "123")); + assertHyperlinks("Created an attachment (id=123)", alink(0, 30, "123")); + } + + public void testFindHyperlinksBug() { + assertHyperlinks("bug123", link(0, 6, "123")); + assertHyperlinks("bug 123", link(0, 7, "123")); + assertHyperlinks("bug 123", link(0, 8, "123")); + assertHyperlinks("bug#123", link(0, 7, "123")); + assertHyperlinks("bug # 123", link(0, 11, "123")); + } + + public void testFindHyperlinksTask() { + assertHyperlinks("task123", link(0, 7, "123")); + } + + public void testFindHyperlinksDuplicateOf() { + assertHyperlinks("duplicate of 123", link(0, 15, "123")); + } + + public void testFindHyperlinksBugComment() { + assertHyperlinks("bug 123 comment 12", link(0, 18, "123", "12")); + assertHyperlinks("bug#123 comment 12", link(0, 18, "123", "12")); + assertHyperlinks("bug 123 comment#12", link(0, 18, "123", "12")); + assertHyperlinks("bug#123 comment#12", link(0, 18, "123", "12")); + assertHyperlinks("bug 123 comment# 12", link(0, 22, "123", "12")); + assertHyperlinks("bug456comment#1", link(0, 15, "456", "1")); + } + + public void testFindHyperlinksBugNoComment() { + assertHyperlinks("bug 123#c1", link(0, 7, "123")); + assertHyperlinks("bug 123#1", link(0, 7, "123")); + assertHyperlinks("bug#123#c1", link(0, 7, "123")); + assertHyperlinks("bug#123#1", link(0, 7, "123")); + } + + public void testFindHyperlinksComment() { + assertHyperlinks("comment#12", link(0, 10, "123", "12")); + assertHyperlinks("comment #12", link(0, 12, "123", "12")); + assertHyperlinks("comment 1", link(0, 9, "123", "1")); + } + + public void testFindHyperlinksInline() { + assertHyperlinks("abc bug 123 def", link(4, 7, "123")); + } + + public void testFindHyperlinksMultiple() { + assertHyperlinks("bug 456#comment#12", link(0, 7, "456"), link(8, 10, "123", "12")); + assertHyperlinks("bug 123 bug 456", link(0, 7, "123"), link(20, 7, "456")); + } + + public void testFindHyperlinksNoAttachment() { + assertHyperlinks("attachment"); + assertHyperlinks("attachmen 123"); + assertHyperlinks("attachment id"); + assertHyperlinks("attachment id"); + assertHyperlinks("Create attachment 123"); + } + + public void testFindHyperlinksNoBug() { + assertHyperlinks("bu 123"); + assertHyperlinks("bu# 123"); + assertHyperlinks("bug"); + assertHyperlinks("bugcomment"); + assertHyperlinks("bug#comment"); + } + + public void testFindHyperlinksNoComment() { + assertHyperlinks("c 12"); + assertHyperlinks("#c12"); + assertHyperlinks("comment"); + } +} #P org.eclipse.mylyn.bugzilla.ui Index: src/org/eclipse/mylyn/internal/bugzilla/ui/TaskAttachmentHyperlink.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.ui/src/org/eclipse/mylyn/internal/bugzilla/ui/TaskAttachmentHyperlink.java,v retrieving revision 1.1 diff -u -r1.1 TaskAttachmentHyperlink.java --- src/org/eclipse/mylyn/internal/bugzilla/ui/TaskAttachmentHyperlink.java 14 Aug 2009 14:04:23 -0000 1.1 +++ src/org/eclipse/mylyn/internal/bugzilla/ui/TaskAttachmentHyperlink.java 26 May 2010 03:34:38 -0000 @@ -55,4 +55,57 @@ String url = repository.getUrl() + IBugzillaConstants.URL_GET_ATTACHMENT_SUFFIX + attachmentId; TasksUiUtil.openUrl(url); } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((attachmentId == null) ? 0 : attachmentId.hashCode()); + result = prime * result + ((region == null) ? 0 : region.hashCode()); + result = prime * result + ((repository == null) ? 0 : repository.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TaskAttachmentHyperlink other = (TaskAttachmentHyperlink) obj; + if (attachmentId == null) { + if (other.attachmentId != null) { + return false; + } + } else if (!attachmentId.equals(other.attachmentId)) { + return false; + } + if (region == null) { + if (other.region != null) { + return false; + } + } else if (!region.equals(other.region)) { + return false; + } + if (repository == null) { + if (other.repository != null) { + return false; + } + } else if (!repository.equals(other.repository)) { + return false; + } + return true; + } + + @Override + public String toString() { + return "TaskAttachmentHyperlink [attachmentId=" + attachmentId + ", region=" + region + ", repository=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + repository + "]"; //$NON-NLS-1$ + } + } Index: src/org/eclipse/mylyn/internal/bugzilla/ui/tasklist/BugzillaConnectorUi.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.ui/src/org/eclipse/mylyn/internal/bugzilla/ui/tasklist/BugzillaConnectorUi.java,v retrieving revision 1.54 diff -u -r1.54 BugzillaConnectorUi.java --- src/org/eclipse/mylyn/internal/bugzilla/ui/tasklist/BugzillaConnectorUi.java 24 May 2010 23:33:43 -0000 1.54 +++ src/org/eclipse/mylyn/internal/bugzilla/ui/tasklist/BugzillaConnectorUi.java 26 May 2010 03:34:38 -0000 @@ -20,7 +20,6 @@ import java.util.regex.Pattern; import org.eclipse.jface.resource.ImageDescriptor; -import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.hyperlink.IHyperlink; import org.eclipse.jface.viewers.IStructuredSelection; @@ -54,19 +53,17 @@ */ public class BugzillaConnectorUi extends AbstractRepositoryConnectorUi { - private static final int GET_TASK_NUM_GROUP = 8; + private static final String BUG = "(?:duplicate of|bug|task)\\s*#?\\s*(\\d+)"; //$NON-NLS-1$ - private static final int GET_COMMENT_NUM_GROUP = 13; + private static final String COMMENT = "comment\\s*#?\\s*(\\d+)"; //$NON-NLS-1$ - private static final int GET_ATTACHMENT_NUM_GROUP = 3; + private static final String REGEXP_BUG = "(?:\\W||^)(" + BUG + "(?:\\s*" + COMMENT + ")?)|(" + COMMENT + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - private static final String regexp_bug = "(((duplicate of|((\\W||^)+(bug|task)))( ?#? ?)(\\d+))?((\\W||\\s)*(comment|c)??(\\s*#\\s*)(\\d+))?)"; //$NON-NLS-1$ + private static final String REGEXP_ATTACHMENT = "(?:Created (?:an )?)?attachment\\s*#?\\s*(?:\\(id=)?(\\d+)\\)?"; //$NON-NLS-1$ - private static final String regexp_attachment = "Created (an )?attachment\\s*(\\(id=)?(\\d+)"; //$NON-NLS-1$ + private static final Pattern PATTERN_BUG = Pattern.compile(REGEXP_BUG, Pattern.CASE_INSENSITIVE); - private static final Pattern PATTERN_BUG = Pattern.compile(regexp_bug, Pattern.CASE_INSENSITIVE); - - private static final Pattern PATTERN_ATTACHMENT = Pattern.compile(regexp_attachment, Pattern.CASE_INSENSITIVE); + private static final Pattern PATTERN_ATTACHMENT = Pattern.compile(REGEXP_ATTACHMENT, Pattern.CASE_INSENSITIVE); @Override public String getAccountCreationUrl(TaskRepository taskRepository) { @@ -189,7 +186,21 @@ Matcher mb = PATTERN_BUG.matcher(text); while (mb.find()) { if (index == -1 || (index >= mb.start() && index <= mb.end())) { - IHyperlink link = extractHyperlinkBug(repository, task, textOffset, mb); + TaskHyperlink link = null; + if (mb.group(1) != null) { + // bug comment + Region region = new Region(textOffset + mb.start(1), mb.end(1) - mb.start(1)); + link = new TaskHyperlink(region, repository, mb.group(2)); + if (mb.group(3) != null) { + link.setSelection(TaskAttribute.PREFIX_COMMENT + mb.group(3)); + } + } else if (task != null && mb.group(4) != null) { + // comment + Region region = new Region(textOffset + mb.start(4), mb.end(4) - mb.start(4)); + link = new TaskHyperlink(region, repository, task.getTaskId()); + link.setSelection(TaskAttribute.PREFIX_COMMENT + mb.group(5)); + } + if (link != null) { if (hyperlinksFound == null) { hyperlinksFound = new ArrayList(); @@ -201,92 +212,17 @@ Matcher ma = PATTERN_ATTACHMENT.matcher(text); while (ma.find()) { if (index == -1 || (index >= ma.start() && index <= ma.end())) { - IHyperlink link = extractHyperlinkAttachment(repository, textOffset, ma); - if (link != null) { - if (hyperlinksFound == null) { - hyperlinksFound = new ArrayList(); - } - hyperlinksFound.add(link); + // attachment + Region region = new Region(textOffset + ma.start(), ma.end() - ma.start()); + TaskAttachmentHyperlink link = new TaskAttachmentHyperlink(region, repository, ma.group(1)); + if (hyperlinksFound == null) { + hyperlinksFound = new ArrayList(); } + hyperlinksFound.add(link); } } return (hyperlinksFound != null) ? hyperlinksFound.toArray(new IHyperlink[0]) : null; } - private static IHyperlink extractHyperlinkBug(TaskRepository repository, ITask task, int regionOffset, Matcher m) { - - int start = m.start(); - if (m.group().startsWith("duplicate")) { //$NON-NLS-1$ - start = m.start() + m.group().indexOf(m.group(GET_TASK_NUM_GROUP)); - } else { - start = m.start(); - for (int index = 0; index < m.group().length() && !Character.isLetter(m.group().charAt(index)); index++, start++) { - } - } - - int end = m.end(); - - if (end == -1) { - end = m.group().length(); - } - - start += regionOffset; - end += regionOffset; - String bugId = m.group(GET_TASK_NUM_GROUP); - if (bugId == null) { - String commentId = m.group(GET_COMMENT_NUM_GROUP); - IRegion sregion = new Region(start, end - start); - if (commentId != null) { - String taskID; - if (task != null) { - taskID = task.getTaskId(); - } else { - taskID = ""; //$NON-NLS-1$ - } - TaskHyperlink taskHyperLink = new TaskHyperlink(sregion, repository, taskID); - if (commentId != null) { - taskHyperLink.setSelection(TaskAttribute.PREFIX_COMMENT + commentId); - } - return taskHyperLink; - - } - } else { - bugId.trim(); - IRegion sregion = new Region(start, end - start); - TaskHyperlink taskHyperLink = new TaskHyperlink(sregion, repository, bugId); - String commentId = m.group(GET_COMMENT_NUM_GROUP); - if (commentId != null) { - taskHyperLink.setSelection(TaskAttribute.PREFIX_COMMENT + commentId); - } - return taskHyperLink; - } - return null; - } - - private static IHyperlink extractHyperlinkAttachment(TaskRepository repository, int regionOffset, Matcher m) { - - int start = -1; - start = m.start(); - for (int index = 0; index < m.group().length() && !Character.isLetter(m.group().charAt(index)); index++, start++) { - } - - int end = m.end(); - - if (end == -1) { - end = m.group().length(); - } - - start += regionOffset; - end += regionOffset; - - String attachmentId = m.group(GET_ATTACHMENT_NUM_GROUP); - if (attachmentId != null) { - start = start + m.group().indexOf(m.group(GET_ATTACHMENT_NUM_GROUP)); - - IRegion sregion = new Region(start, end - start); - return new TaskAttachmentHyperlink(sregion, repository, attachmentId); - } - return null; - } } #P org.eclipse.mylyn.tasks.ui Index: src/org/eclipse/mylyn/tasks/ui/TaskHyperlink.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/TaskHyperlink.java,v retrieving revision 1.19 diff -u -r1.19 TaskHyperlink.java --- src/org/eclipse/mylyn/tasks/ui/TaskHyperlink.java 1 Mar 2010 01:43:34 -0000 1.19 +++ src/org/eclipse/mylyn/tasks/ui/TaskHyperlink.java 26 May 2010 03:34:38 -0000 @@ -38,7 +38,7 @@ private final String taskId; - Object selection; + private Object selection; public TaskHyperlink(IRegion region, TaskRepository repository, String taskId) { this.region = region; @@ -114,4 +114,64 @@ this.selection = selection; } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((region == null) ? 0 : region.hashCode()); + result = prime * result + ((repository == null) ? 0 : repository.hashCode()); + result = prime * result + ((selection == null) ? 0 : selection.hashCode()); + result = prime * result + ((taskId == null) ? 0 : taskId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + TaskHyperlink other = (TaskHyperlink) obj; + if (region == null) { + if (other.region != null) { + return false; + } + } else if (!region.equals(other.region)) { + return false; + } + if (repository == null) { + if (other.repository != null) { + return false; + } + } else if (!repository.equals(other.repository)) { + return false; + } + if (selection == null) { + if (other.selection != null) { + return false; + } + } else if (!selection.equals(other.selection)) { + return false; + } + if (taskId == null) { + if (other.taskId != null) { + return false; + } + } else if (!taskId.equals(other.taskId)) { + return false; + } + return true; + } + + @Override + public String toString() { + return "TaskHyperlink [region=" + region + ", repository=" + repository + ", selection=" + selection //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + ", taskId=" + taskId + "]"; //$NON-NLS-1$ //$NON-NLS-2$ + } + }