From d27a79d4650e359af65bfb25cdd5d8f5ab15ab51 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Mon, 4 Jan 2010 10:43:49 +0000 Subject: [PATCH] Bug 298069: Wrong encoding for lines in search result. --- .../org.eclipse.cdt.core/META-INF/MANIFEST.MF | 2 +- .../internal/ui/search/LineSearchElement.java | 518 +++++++++--------- 2 files changed, 263 insertions(+), 257 deletions(-) diff --git a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF index be7308cea99..cae7f8ed7f0 100644 --- a/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.core/META-INF/MANIFEST.MF @@ -61,7 +61,7 @@ Export-Package: org.eclipse.cdt.core, org.eclipse.cdt.internal.core.model.ext;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.parser;x-internal:=true, org.eclipse.cdt.internal.core.parser.problem;x-internal:=true, - org.eclipse.cdt.internal.core.parser.scanner;x-internal:=true, + org.eclipse.cdt.internal.core.parser.scanner;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.parser.token;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.parser.util;x-internal:=true, org.eclipse.cdt.internal.core.pdom;x-friends:="org.eclipse.cdt.ui", diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/LineSearchElement.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/LineSearchElement.java index a8a193d0b28..39502a05df3 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/LineSearchElement.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/search/LineSearchElement.java @@ -1,256 +1,262 @@ -/******************************************************************************* - * Copyright (c) 2009 QNX Software Systems 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: - * Andrey Eremchenko, kamre@ngs.ru - 222495 C/C++ search should show line matches and line numbers - *******************************************************************************/ -package org.eclipse.cdt.internal.ui.search; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.IDocument; - -import org.eclipse.cdt.core.index.IIndexFileLocation; -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.core.parser.CodeReader; -import org.eclipse.cdt.ui.CUIPlugin; - -/** - * Element representing a line with one ore more matches. - */ -public class LineSearchElement extends PDOMSearchElement { - public static final class Match { - private final int fOffset; - private final int fLength; - private final boolean fIsPolymorphicCall; - private final ICElement fEnclosingElement; - - public Match(int offset, int length, boolean isPolymorphicCall, ICElement enclosingElement) { - fOffset = offset; - fLength = length; - fIsPolymorphicCall = isPolymorphicCall; - fEnclosingElement = enclosingElement; - } - - public int getOffset() { - return fOffset; - } - - public int getLength() { - return fLength; - } - - public boolean isPolymorphicCall() { - return fIsPolymorphicCall; - } - - public ICElement getEnclosingElement() { - return fEnclosingElement; - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Match)) - return false; - Match m = (Match) obj; - return (fOffset == m.fOffset) && (fLength == m.fLength); - } - - @Override - public int hashCode() { - return 31 * fOffset + fLength; - } - } - - private static final class MatchesComparator implements Comparator { - public int compare(Match m1, Match m2) { - return m1.getOffset() - m2.getOffset(); - } - } - - private final int fOffset; - private final int fNumber; - private final String fContent; - private final Match[] fMatches; - private final static MatchesComparator MATCHES_COMPARATOR = new MatchesComparator(); - - private LineSearchElement(IIndexFileLocation file, Match[] matches, int number, String content, int offset) { - super(file); - fMatches = matches; - fNumber = number; - // skip whitespace at the beginning - int index = 0; - int length = content.length(); - int firstMatchOffset = matches[0].getOffset(); - while (offset < firstMatchOffset && length > 0) { - if (!Character.isWhitespace(content.charAt(index))) - break; - index++; - offset++; - length--; - } - fOffset = offset; - fContent = content.substring(index); - } - - public int getOffset() { - return fOffset; - } - - public int getLineNumber() { - return fNumber; - } - - public String getContent() { - return fContent; - } - - public Match[] getMatches() { - return fMatches; - } - - @Override - public String toString() { - return fNumber + ": " + fContent; //$NON-NLS-1$ - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof LineSearchElement)) - return false; - LineSearchElement other = (LineSearchElement) obj; - return (fOffset == other.fOffset) && (super.equals(obj)) && (fMatches.equals(other.fMatches)); - } - - @Override - public int hashCode() { - return fOffset + 31 * (super.hashCode() + 31 * fMatches.hashCode()); - } - - public static LineSearchElement[] createElements(IIndexFileLocation fileLocation, Match[] matches) { - // sort matches according to their offsets - Arrays.sort(matches, MATCHES_COMPARATOR); - LineSearchElement[] result = {}; - try { - String path = fileLocation.getURI().getPath(); - // read the content of file - CodeReader reader = new CodeReader(path); - result = collectLineElements(reader.buffer, matches, fileLocation); - } catch (IOException e) { - CUIPlugin.log(e); - } - return result; - } - - public static LineSearchElement[] createElements(IIndexFileLocation fileLocation, Match[] matches, - IDocument document) { - // sort matches according to their offsets - Arrays.sort(matches, MATCHES_COMPARATOR); - // group all matches by lines and create LineSearchElements - List result = new ArrayList(); - int firstMatch = 0; - while (firstMatch < matches.length) { - try { - int lineNumber = document.getLineOfOffset(matches[firstMatch].getOffset()); - int lineOffset = document.getLineOffset(lineNumber); - int lineLength = document.getLineLength(lineNumber); - int nextlineOffset = lineOffset + lineLength; - int nextMatch = firstMatch; - int nextMatchOffset = matches[nextMatch].getOffset(); - while (nextMatch < matches.length && nextMatchOffset < nextlineOffset) { - nextMatch++; - if (nextMatch < matches.length) - nextMatchOffset = matches[nextMatch].getOffset(); - } - int lineMatchesCount = nextMatch - firstMatch; - Match[] lineMatches = new Match[lineMatchesCount]; - System.arraycopy(matches, firstMatch, lineMatches, 0, lineMatchesCount); - String content = document.get(lineOffset, lineLength); - result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber + 1, content, lineOffset)); - firstMatch = nextMatch; - } catch (BadLocationException e) { - CUIPlugin.log(e); - } - } - return result.toArray(new LineSearchElement[result.size()]); - } - - private static LineSearchElement[] collectLineElements(char[] buffer, Match[] matches, - IIndexFileLocation fileLocation) { - List result = new ArrayList(); - boolean skipLF = false; - int lineNumber = 1; - int lineOffset = 0; - int lineFirstMatch = -1; // not matched - int nextMatch = 0; - int nextMatchOffset = matches[nextMatch].getOffset(); - for (int pos = 0; pos < buffer.length; pos++) { - char c = buffer[pos]; - // consider '\n' and '\r' - if (skipLF) { - skipLF = false; - if (c == '\n') { - lineOffset = pos + 1; - continue; - } - } - if (c == '\n' || c == '\r') { - // create new LineElement if there were matches - if (lineFirstMatch != -1) { - int lineLength = pos - lineOffset; - int lineMatchesCount = nextMatch - lineFirstMatch; - Match[] lineMatches = new Match[lineMatchesCount]; - System.arraycopy(matches, lineFirstMatch, lineMatches, 0, lineMatchesCount); - String lineContent = new String(buffer, lineOffset, lineLength); - result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber, lineContent, - lineOffset)); - lineFirstMatch = -1; - if (nextMatch >= matches.length) - break; - if (matches[nextMatch].getOffset() < pos) - lineFirstMatch = nextMatch; - } - lineNumber++; - lineOffset = pos + 1; - if (c == '\r') - skipLF = true; - continue; - } - // compare offset of next match with current position - if (nextMatchOffset > pos) - continue; - // next match was reached - // check if this match is the first for current line - if (lineFirstMatch == -1) - lineFirstMatch = nextMatch; - // goto to next match - nextMatch++; - if (nextMatch < matches.length) { - // update offset of next match - nextMatchOffset = matches[nextMatch].getOffset(); - } else { - // no more matches - nextMatchOffset = buffer.length; - } - } - // check if there were matches on the last line - if (lineFirstMatch != -1) { - int lineLength = buffer.length - lineOffset; - int lineMatchesCount = nextMatch - lineFirstMatch; - Match[] lineMatches = new Match[lineMatchesCount]; - System.arraycopy(matches, lineFirstMatch, lineMatches, 0, lineMatchesCount); - String lineContent = new String(buffer, lineOffset, lineLength); - result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber, lineContent, lineOffset)); - } - return result.toArray(new LineSearchElement[result.size()]); - } -} +/******************************************************************************* + * Copyright (c) 2009, 2010 QNX Software Systems 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: + * Andrey Eremchenko, kamre@ngs.ru - 222495 C/C++ search should show line matches and line numbers + * Markus Schorn (Wind River Systems) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.search; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; + +import org.eclipse.cdt.core.index.IIndexFileLocation; +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.parser.FileContent; +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.core.parser.scanner.AbstractCharArray; +import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent; + +/** + * Element representing a line with one ore more matches. + */ +public class LineSearchElement extends PDOMSearchElement { + public static final class Match { + private final int fOffset; + private final int fLength; + private final boolean fIsPolymorphicCall; + private final ICElement fEnclosingElement; + + public Match(int offset, int length, boolean isPolymorphicCall, ICElement enclosingElement) { + fOffset = offset; + fLength = length; + fIsPolymorphicCall = isPolymorphicCall; + fEnclosingElement = enclosingElement; + } + + public int getOffset() { + return fOffset; + } + + public int getLength() { + return fLength; + } + + public boolean isPolymorphicCall() { + return fIsPolymorphicCall; + } + + public ICElement getEnclosingElement() { + return fEnclosingElement; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Match)) + return false; + Match m = (Match) obj; + return (fOffset == m.fOffset) && (fLength == m.fLength); + } + + @Override + public int hashCode() { + return 31 * fOffset + fLength; + } + } + + private static final class MatchesComparator implements Comparator { + public int compare(Match m1, Match m2) { + return m1.getOffset() - m2.getOffset(); + } + } + + private final int fOffset; + private final int fNumber; + private final String fContent; + private final Match[] fMatches; + private final static MatchesComparator MATCHES_COMPARATOR = new MatchesComparator(); + + private LineSearchElement(IIndexFileLocation file, Match[] matches, int number, String content, int offset) { + super(file); + fMatches = matches; + fNumber = number; + // skip whitespace at the beginning + int index = 0; + int length = content.length(); + int firstMatchOffset = matches[0].getOffset(); + while (offset < firstMatchOffset && length > 0) { + if (!Character.isWhitespace(content.charAt(index))) + break; + index++; + offset++; + length--; + } + fOffset = offset; + fContent = content.substring(index); + } + + public int getOffset() { + return fOffset; + } + + public int getLineNumber() { + return fNumber; + } + + public String getContent() { + return fContent; + } + + public Match[] getMatches() { + return fMatches; + } + + @Override + public String toString() { + return fNumber + ": " + fContent; //$NON-NLS-1$ + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof LineSearchElement)) + return false; + LineSearchElement other = (LineSearchElement) obj; + return (fOffset == other.fOffset) && (super.equals(obj)) && (fMatches.equals(other.fMatches)); + } + + @Override + public int hashCode() { + return fOffset + 31 * (super.hashCode() + 31 * fMatches.hashCode()); + } + + public static LineSearchElement[] createElements(IIndexFileLocation fileLocation, Match[] matches) { + // sort matches according to their offsets + Arrays.sort(matches, MATCHES_COMPARATOR); + LineSearchElement[] result = {}; + + // read the content of file + FileContent content = FileContent.create(fileLocation); + AbstractCharArray buf = ((InternalFileContent) content).getSource(); + if (buf != null) + result = collectLineElements(buf, matches, fileLocation); + return result; + } + + public static LineSearchElement[] createElements(IIndexFileLocation fileLocation, Match[] matches, + IDocument document) { + // sort matches according to their offsets + Arrays.sort(matches, MATCHES_COMPARATOR); + // group all matches by lines and create LineSearchElements + List result = new ArrayList(); + int firstMatch = 0; + while (firstMatch < matches.length) { + try { + int lineNumber = document.getLineOfOffset(matches[firstMatch].getOffset()); + int lineOffset = document.getLineOffset(lineNumber); + int lineLength = document.getLineLength(lineNumber); + int nextlineOffset = lineOffset + lineLength; + int nextMatch = firstMatch; + int nextMatchOffset = matches[nextMatch].getOffset(); + while (nextMatch < matches.length && nextMatchOffset < nextlineOffset) { + nextMatch++; + if (nextMatch < matches.length) + nextMatchOffset = matches[nextMatch].getOffset(); + } + int lineMatchesCount = nextMatch - firstMatch; + Match[] lineMatches = new Match[lineMatchesCount]; + System.arraycopy(matches, firstMatch, lineMatches, 0, lineMatchesCount); + String content = document.get(lineOffset, lineLength); + result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber + 1, content, lineOffset)); + firstMatch = nextMatch; + } catch (BadLocationException e) { + CUIPlugin.log(e); + } + } + return result.toArray(new LineSearchElement[result.size()]); + } + + private static LineSearchElement[] collectLineElements(AbstractCharArray buf, Match[] matches, + IIndexFileLocation fileLocation) { + List result = new ArrayList(); + boolean skipLF = false; + int lineNumber = 1; + int lineOffset = 0; + int lineFirstMatch = -1; // not matched + int nextMatch = 0; + int nextMatchOffset = matches[nextMatch].getOffset(); + for (int pos = 0; buf.isValidOffset(pos); pos++) { + char c = buf.get(pos); + // consider '\n' and '\r' + if (skipLF) { + skipLF = false; + if (c == '\n') { + lineOffset = pos + 1; + continue; + } + } + if (c == '\n' || c == '\r') { + // create new LineElement if there were matches + if (lineFirstMatch != -1) { + int lineLength = pos - lineOffset; + int lineMatchesCount = nextMatch - lineFirstMatch; + Match[] lineMatches = new Match[lineMatchesCount]; + System.arraycopy(matches, lineFirstMatch, lineMatches, 0, lineMatchesCount); + char[] lineChars= new char[lineLength]; + buf.arraycopy(lineOffset, lineChars, 0, lineLength); + String lineContent = new String(lineChars); + result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber, lineContent, + lineOffset)); + lineFirstMatch = -1; + if (nextMatch >= matches.length) + break; + if (matches[nextMatch].getOffset() < pos) + lineFirstMatch = nextMatch; + } + lineNumber++; + lineOffset = pos + 1; + if (c == '\r') + skipLF = true; + continue; + } + // compare offset of next match with current position + if (nextMatchOffset > pos) + continue; + // next match was reached + // check if this match is the first for current line + if (lineFirstMatch == -1) + lineFirstMatch = nextMatch; + // goto to next match + nextMatch++; + if (nextMatch < matches.length) { + // update offset of next match + nextMatchOffset = matches[nextMatch].getOffset(); + } else { + // no more matches + break; + } + } + // check if there were matches on the last line + if (lineFirstMatch != -1) { + int lineLength = buf.getLength() - lineOffset; + int lineMatchesCount = nextMatch - lineFirstMatch; + Match[] lineMatches = new Match[lineMatchesCount]; + System.arraycopy(matches, lineFirstMatch, lineMatches, 0, lineMatchesCount); + + char[] lineChars= new char[lineLength]; + buf.arraycopy(lineOffset, lineChars, 0, lineLength); + String lineContent = new String(lineChars); + result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber, lineContent, lineOffset)); + } + return result.toArray(new LineSearchElement[result.size()]); + } +}