From d1e966b06e3dfb9e0579c58f380735b7c295e7e4 Mon Sep 17 00:00:00 2001 From: Andrew Gvozdev Date: Thu, 4 Jul 2013 15:50:35 -0400 Subject: [PATCH] Bug 412250: Makefile Editor won't open include with F3 --- .../core/makefile/gnu/GNUMakefile.java | 2 +- .../ui/editor/OpenDeclarationAction.java | 29 +++++- .../internal/ui/text/WordPartDetector.java | 89 +++++++++++++++++-- 3 files changed, 112 insertions(+), 8 deletions(-) diff --git a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/GNUMakefile.java b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/GNUMakefile.java index 0c99819b3a2..ff642da143e 100644 --- a/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/GNUMakefile.java +++ b/build/org.eclipse.cdt.make.core/src/org/eclipse/cdt/make/internal/core/makefile/gnu/GNUMakefile.java @@ -523,7 +523,7 @@ public class GNUMakefile extends AbstractMakefile implements IGNUMakefile { // ignore the "include" keyword. continue; } - filenames[i - 1] = st.nextToken(); + filenames[i - 1] = expandString(st.nextToken(), true); } } else { filenames = new String[0]; diff --git a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/editor/OpenDeclarationAction.java b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/editor/OpenDeclarationAction.java index 8d783d2adc1..439aae3b886 100644 --- a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/editor/OpenDeclarationAction.java +++ b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/editor/OpenDeclarationAction.java @@ -10,8 +10,12 @@ *******************************************************************************/ package org.eclipse.cdt.make.internal.ui.editor; +import java.net.URI; +import java.util.Arrays; + import org.eclipse.cdt.make.core.makefile.IDirective; import org.eclipse.cdt.make.core.makefile.IMakefile; +import org.eclipse.cdt.make.core.makefile.gnu.IInclude; import org.eclipse.cdt.make.internal.ui.MakeUIPlugin; import org.eclipse.cdt.make.internal.ui.text.WordPartDetector; import org.eclipse.cdt.make.ui.IWorkingCopyManager; @@ -50,13 +54,36 @@ public class OpenDeclarationAction extends TextEditorAction { try { ITextSelection textSelection = (ITextSelection) provider.getSelection(); int offset = textSelection.getOffset(); - WordPartDetector wordPart = new WordPartDetector(doc, textSelection.getOffset()); + WordPartDetector wordPart = new WordPartDetector(doc, offset); String name = wordPart.toString(); if (WordPartDetector.inMacro(doc, offset)) { directives = makefile.getMacroDefinitions(name); if (directives.length == 0) { directives = makefile.getBuiltinMacroDefinitions(name); } + } else if (wordPart.isIncludeDirective()) { + String incFile = wordPart.getIncludedFile(); + incFile = makefile.expandString(incFile, true); + for (IDirective dir : makefile.getDirectives()) { + if (dir instanceof IInclude) { + IInclude includeDirective = (IInclude) dir; + if (Arrays.asList(((IInclude) dir).getFilenames()).contains(incFile)) { + IDirective[] includedMakefiles = includeDirective.getDirectives(); + for (IDirective includedMakefileDir : includedMakefiles) { + if (includedMakefileDir instanceof IMakefile) { + IMakefile includedMakefile = (IMakefile) includedMakefileDir; + URI uri = includedMakefile.getFileURI(); + // endsWith() is potentially inaccurate but IInclude does not provide better way + if (uri != null && uri.toString().endsWith(incFile)) { + directives = new IDirective[1]; + directives[0] = includedMakefileDir; + break; + } + } + } + } + } + } } else { directives = makefile.getTargetRules(name); } diff --git a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/WordPartDetector.java b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/WordPartDetector.java index 0f127bcf76e..5b494cdec75 100644 --- a/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/WordPartDetector.java +++ b/build/org.eclipse.cdt.make.ui/src/org/eclipse/cdt/make/internal/ui/text/WordPartDetector.java @@ -10,22 +10,21 @@ *******************************************************************************/ package org.eclipse.cdt.make.internal.ui.text; +import org.eclipse.cdt.make.internal.ui.MakeUIPlugin; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; -/** - * Used to scan and detect for SQL keywords - */ public class WordPartDetector { - String wordPart = ""; //$NON-NLS-1$ + IDocument document; int offset; + String wordPart = ""; //$NON-NLS-1$ /** * WordPartDetector. * @param viewer is a text viewer - * @param documentOffset into the SQL document + * @param documentOffset */ public WordPartDetector(ITextViewer viewer, int documentOffset) { this(viewer.getDocument(), documentOffset); @@ -37,6 +36,7 @@ public class WordPartDetector { * @param documentOffset */ public WordPartDetector(IDocument doc, int documentOffset) { + document = doc; offset = documentOffset - 1; int endOffset = documentOffset; try { @@ -71,7 +71,7 @@ public class WordPartDetector { if (c == '$') { isMacro = true; break; - } else if (Character.isWhitespace(c)) { + } else if (Character.isWhitespace(c) || c == ')' || c == '}') { break; } } @@ -80,6 +80,83 @@ public class WordPartDetector { return isMacro; } + /** + * Quick check if the cursor sits on an include directive line. + * + * @return {@code true} if the cursor is located on include line, {@code false} otherwise. + */ + public boolean isIncludeDirective() { + boolean isIncludeDirective = false; + try { + int lineNumber = document.getLineOfOffset(offset); + String line = document.get(document.getLineOffset(lineNumber), document.getLineLength(lineNumber)); + String firstWord = findWord(line.trim(), 1); + isIncludeDirective = isIncludeKeyword(firstWord); + } catch (BadLocationException e) { + MakeUIPlugin.log(e); + } + return isIncludeDirective; + } + + /** + * Gets include file name under the cursor. + * + * @return include file name to which the cursor location corresponds. + */ + public String getIncludedFile() { + String inc = null; + try { + int lineNumber = document.getLineOfOffset(offset); + int lineOffset = document.getLineOffset(lineNumber); + String line = document.get(lineOffset, document.getLineLength(lineNumber)); + + int position = offset -lineOffset; + inc = findWord(line, position); + if (isIncludeKeyword(inc)) { + inc = findWord(line, line.indexOf(inc) + inc.length() + 1); + } + } catch (BadLocationException e) { + MakeUIPlugin.log(e); + } + return inc; + } + + /** + * Find word located in the given position. A word is defined here as a sequence of non-space characters. + */ + private static String findWord(String line, int position) { + String firstHalf; + try { + firstHalf = line.substring(0, position); + } catch (IndexOutOfBoundsException e) { + firstHalf = line; + } + String secondHalf; + try { + secondHalf = line.substring(position); + } catch (IndexOutOfBoundsException e) { + secondHalf = ""; //$NON-NLS-1$ + } + int startIndex = firstHalf.lastIndexOf(' ') + 1; + int firstHalfLen = firstHalf.length(); + int endIndex = firstHalfLen + secondHalf.indexOf(' '); + if (endIndex < firstHalfLen) { + endIndex = line.length(); + } + // trim() gets rid of trailing end of line if captured + String word = line.substring(startIndex, endIndex).trim(); + return word; + } + + /** + * Check if the string is include keyword. + */ + private static boolean isIncludeKeyword(String inc) { + @SuppressWarnings("nls") + boolean isKeyword = "include".equals(inc) || "-include".equals(inc) || "sinclude".equals(inc); + return isKeyword; + } + @Override public String toString() { return wordPart;