blob: 423c1cf6e84734e7a5297e365c3597c4c9c5c170 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 - 2006 University Of British Columbia 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:
* University Of British Columbia - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.internal.bugs.java;
import java.util.List;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.Comment;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.TextElement;
import org.eclipse.jdt.internal.corext.dom.NodeFinder;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.mylyn.internal.bugzilla.ui.BugzillaHyperlinkUtil;
import org.eclipse.mylyn.internal.core.util.MylarStatusHandler;
import org.eclipse.mylyn.provisional.tasklist.TaskRepository;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.texteditor.ITextEditor;
/**
* @author Shawn Minto
* Detects bugzilla hyperlinks within source code
*/
public class BugzillaHyperLinkDetector extends AbstractHyperlinkDetector {
private TaskRepository repository;
public BugzillaHyperLinkDetector(TaskRepository repository) {
this.repository = repository;
}
@SuppressWarnings("unchecked")
public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) {
ITextEditor textEditor = getEditor();
if (region == null || textEditor == null || canShowMultipleHyperlinks || !(textEditor instanceof JavaEditor))
return null;
IEditorSite site = textEditor.getEditorSite();
if (site == null)
return null;
IJavaElement javaElement;
Object adapter = textEditor.getEditorInput().getAdapter(IJavaElement.class);
if (adapter instanceof IJavaElement) {
javaElement = (IJavaElement)adapter;
} else {
return null;
}
if (javaElement == null)
return null;
CompilationUnit ast = JavaPlugin.getDefault().getASTProvider().getAST(javaElement, ASTProvider.WAIT_NO, null);
if (ast == null)
return null;
ASTNode node = NodeFinder.perform(ast, region.getOffset(), 1);
if (node == null || !(node instanceof TextElement || node instanceof Block))
return null;
String comment = null;
int commentStart = -1;
if (node instanceof TextElement) {
TextElement element = (TextElement) node;
comment = element.getText();
commentStart = element.getStartPosition();
} else if (node instanceof Block) {
Comment c = findComment(ast.getCommentList(), region.getOffset(), 1);
if (c != null) {
try {
IDocument document = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
String commentString = document.get(c.getStartPosition(), c.getLength());
comment = getStringFromComment(c, region.getOffset(), commentString);
commentStart = getLocationFromComment(c, comment, commentString) + c.getStartPosition();
} catch (BadLocationException e) {
MylarStatusHandler.log(e, "Failed to get text for comment");
}
}
}
if (comment == null)
return null;
int startOffset = region.getOffset();
int endOffset = startOffset + region.getLength();
return BugzillaHyperlinkUtil.findBugHyperlinks(repository.getUrl(), startOffset, endOffset, comment, commentStart);
}
// private IHyperlink[] findBugHyperlinks(int startOffset, int endOffset, String comment, int commentStart) {
//
// Pattern p = Pattern.compile("^.*bug\\s+\\d+.*");
// Matcher m = p.matcher(comment.toLowerCase().trim());
// boolean b = m.matches();
//
// p = Pattern.compile("^.*bug#\\s+\\d+.*");
// m = p.matcher(comment.toLowerCase().trim());
// boolean b2 = m.matches();
//
// p = Pattern.compile("^.*bug\\s#\\d+.*");
// m = p.matcher(comment.toLowerCase().trim());
// boolean b3 = m.matches();
//
// p = Pattern.compile("^.*bug#\\d+.*");
// m = p.matcher(comment.toLowerCase().trim());
// boolean b4 = m.matches();
//
// // XXX walk forward from where we are
// if (b || b2 || b3 || b4) {
//
// int start = comment.toLowerCase().indexOf("bug");
// int ahead = 4;
// if (b2 || b3 || b4) {
// int pound = comment.toLowerCase().indexOf("#", start);
// ahead = pound - start + 1;
// }
// String endComment = comment.substring(start + ahead, comment.length());
// endComment = endComment.trim();
// int endCommentStart = comment.indexOf(endComment);
//
// int end = comment.indexOf(" ", endCommentStart);
// int end2 = comment.indexOf(":", endCommentStart);
//
// if ((end2 < end && end2 != -1) || (end == -1 && end2 != -1)) {
// end = end2;
// }
//
// if (end == -1)
// end = comment.length();
//
// try {
// int bugId = Integer.parseInt(comment.substring(endCommentStart, end).trim());
//
// start += commentStart;
// end += commentStart;
//
// if (startOffset >= start && endOffset <= end) {
// IRegion sregion = new Region(start, end - start);
// return new IHyperlink[] { new BugzillaHyperLink(sregion, bugId) };
// }
// } catch (NumberFormatException e) {
// return null;
// }
// }
// return null;
// }
private int getLocationFromComment(Comment c, String commentLine, String commentString) {
if (commentLine == null) {
return -1;
} else {
return commentString.indexOf(commentLine);
}
}
private String getStringFromComment(Comment comment, int desiredOffset, String commentString) {
String[] parts = commentString.split("\n");
if (parts.length > 1) {
int offset = comment.getStartPosition();
for (String part : parts) {
int newOffset = offset + part.length() + 1;
if (desiredOffset >= offset && desiredOffset <= newOffset) {
return part;
}
}
} else {
return commentString;
}
return null;
}
private Comment findComment(List<Comment> commentList, int offset, int i) {
for (Comment comment : commentList) {
if (comment.getStartPosition() <= offset
&& (comment.getStartPosition() + comment.getLength() >= offset + i)) {
return comment;
}
}
return null;
}
}