1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-21 16:05:25 +02:00

Bug 298069: Wrong encoding for lines in search result.

This commit is contained in:
Markus Schorn 2010-01-04 10:43:49 +00:00
parent 4733439ba4
commit d27a79d465
2 changed files with 263 additions and 257 deletions

View file

@ -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.model.ext;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.parser;x-internal:=true, 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.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.token;x-friends:="org.eclipse.cdt.ui",
org.eclipse.cdt.internal.core.parser.util;x-internal:=true, org.eclipse.cdt.internal.core.parser.util;x-internal:=true,
org.eclipse.cdt.internal.core.pdom;x-friends:="org.eclipse.cdt.ui", org.eclipse.cdt.internal.core.pdom;x-friends:="org.eclipse.cdt.ui",

View file

@ -1,256 +1,262 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2009 QNX Software Systems and others. * Copyright (c) 2009, 2010 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Andrey Eremchenko, kamre@ngs.ru - 222495 C/C++ search should show line matches and line numbers * 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; *******************************************************************************/
package org.eclipse.cdt.internal.ui.search;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocument;
import org.eclipse.cdt.core.index.IIndexFileLocation; import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.parser.CodeReader; import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.CUIPlugin;
/** import org.eclipse.cdt.internal.core.parser.scanner.AbstractCharArray;
* Element representing a line with one ore more matches. import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent;
*/
public class LineSearchElement extends PDOMSearchElement { /**
public static final class Match { * Element representing a line with one ore more matches.
private final int fOffset; */
private final int fLength; public class LineSearchElement extends PDOMSearchElement {
private final boolean fIsPolymorphicCall; public static final class Match {
private final ICElement fEnclosingElement; private final int fOffset;
private final int fLength;
public Match(int offset, int length, boolean isPolymorphicCall, ICElement enclosingElement) { private final boolean fIsPolymorphicCall;
fOffset = offset; private final ICElement fEnclosingElement;
fLength = length;
fIsPolymorphicCall = isPolymorphicCall; public Match(int offset, int length, boolean isPolymorphicCall, ICElement enclosingElement) {
fEnclosingElement = enclosingElement; fOffset = offset;
} fLength = length;
fIsPolymorphicCall = isPolymorphicCall;
public int getOffset() { fEnclosingElement = enclosingElement;
return fOffset; }
}
public int getOffset() {
public int getLength() { return fOffset;
return fLength; }
}
public int getLength() {
public boolean isPolymorphicCall() { return fLength;
return fIsPolymorphicCall; }
}
public boolean isPolymorphicCall() {
public ICElement getEnclosingElement() { return fIsPolymorphicCall;
return fEnclosingElement; }
}
public ICElement getEnclosingElement() {
@Override return fEnclosingElement;
public boolean equals(Object obj) { }
if (!(obj instanceof Match))
return false; @Override
Match m = (Match) obj; public boolean equals(Object obj) {
return (fOffset == m.fOffset) && (fLength == m.fLength); if (!(obj instanceof Match))
} return false;
Match m = (Match) obj;
@Override return (fOffset == m.fOffset) && (fLength == m.fLength);
public int hashCode() { }
return 31 * fOffset + fLength;
} @Override
} public int hashCode() {
return 31 * fOffset + fLength;
private static final class MatchesComparator implements Comparator<Match> { }
public int compare(Match m1, Match m2) { }
return m1.getOffset() - m2.getOffset();
} private static final class MatchesComparator implements Comparator<Match> {
} 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 int fOffset;
private final static MatchesComparator MATCHES_COMPARATOR = new MatchesComparator(); private final int fNumber;
private final String fContent;
private LineSearchElement(IIndexFileLocation file, Match[] matches, int number, String content, int offset) { private final Match[] fMatches;
super(file); private final static MatchesComparator MATCHES_COMPARATOR = new MatchesComparator();
fMatches = matches;
fNumber = number; private LineSearchElement(IIndexFileLocation file, Match[] matches, int number, String content, int offset) {
// skip whitespace at the beginning super(file);
int index = 0; fMatches = matches;
int length = content.length(); fNumber = number;
int firstMatchOffset = matches[0].getOffset(); // skip whitespace at the beginning
while (offset < firstMatchOffset && length > 0) { int index = 0;
if (!Character.isWhitespace(content.charAt(index))) int length = content.length();
break; int firstMatchOffset = matches[0].getOffset();
index++; while (offset < firstMatchOffset && length > 0) {
offset++; if (!Character.isWhitespace(content.charAt(index)))
length--; break;
} index++;
fOffset = offset; offset++;
fContent = content.substring(index); length--;
} }
fOffset = offset;
public int getOffset() { fContent = content.substring(index);
return fOffset; }
}
public int getOffset() {
public int getLineNumber() { return fOffset;
return fNumber; }
}
public int getLineNumber() {
public String getContent() { return fNumber;
return fContent; }
}
public String getContent() {
public Match[] getMatches() { return fContent;
return fMatches; }
}
public Match[] getMatches() {
@Override return fMatches;
public String toString() { }
return fNumber + ": " + fContent; //$NON-NLS-1$
} @Override
public String toString() {
@Override return fNumber + ": " + fContent; //$NON-NLS-1$
public boolean equals(Object obj) { }
if (!(obj instanceof LineSearchElement))
return false; @Override
LineSearchElement other = (LineSearchElement) obj; public boolean equals(Object obj) {
return (fOffset == other.fOffset) && (super.equals(obj)) && (fMatches.equals(other.fMatches)); if (!(obj instanceof LineSearchElement))
} return false;
LineSearchElement other = (LineSearchElement) obj;
@Override return (fOffset == other.fOffset) && (super.equals(obj)) && (fMatches.equals(other.fMatches));
public int hashCode() { }
return fOffset + 31 * (super.hashCode() + 31 * fMatches.hashCode());
} @Override
public int hashCode() {
public static LineSearchElement[] createElements(IIndexFileLocation fileLocation, Match[] matches) { return fOffset + 31 * (super.hashCode() + 31 * fMatches.hashCode());
// sort matches according to their offsets }
Arrays.sort(matches, MATCHES_COMPARATOR);
LineSearchElement[] result = {}; public static LineSearchElement[] createElements(IIndexFileLocation fileLocation, Match[] matches) {
try { // sort matches according to their offsets
String path = fileLocation.getURI().getPath(); Arrays.sort(matches, MATCHES_COMPARATOR);
// read the content of file LineSearchElement[] result = {};
CodeReader reader = new CodeReader(path);
result = collectLineElements(reader.buffer, matches, fileLocation); // read the content of file
} catch (IOException e) { FileContent content = FileContent.create(fileLocation);
CUIPlugin.log(e); AbstractCharArray buf = ((InternalFileContent) content).getSource();
} if (buf != null)
return result; result = collectLineElements(buf, matches, fileLocation);
} return result;
}
public static LineSearchElement[] createElements(IIndexFileLocation fileLocation, Match[] matches,
IDocument document) { public static LineSearchElement[] createElements(IIndexFileLocation fileLocation, Match[] matches,
// sort matches according to their offsets IDocument document) {
Arrays.sort(matches, MATCHES_COMPARATOR); // sort matches according to their offsets
// group all matches by lines and create LineSearchElements Arrays.sort(matches, MATCHES_COMPARATOR);
List<LineSearchElement> result = new ArrayList<LineSearchElement>(); // group all matches by lines and create LineSearchElements
int firstMatch = 0; List<LineSearchElement> result = new ArrayList<LineSearchElement>();
while (firstMatch < matches.length) { int firstMatch = 0;
try { while (firstMatch < matches.length) {
int lineNumber = document.getLineOfOffset(matches[firstMatch].getOffset()); try {
int lineOffset = document.getLineOffset(lineNumber); int lineNumber = document.getLineOfOffset(matches[firstMatch].getOffset());
int lineLength = document.getLineLength(lineNumber); int lineOffset = document.getLineOffset(lineNumber);
int nextlineOffset = lineOffset + lineLength; int lineLength = document.getLineLength(lineNumber);
int nextMatch = firstMatch; int nextlineOffset = lineOffset + lineLength;
int nextMatchOffset = matches[nextMatch].getOffset(); int nextMatch = firstMatch;
while (nextMatch < matches.length && nextMatchOffset < nextlineOffset) { int nextMatchOffset = matches[nextMatch].getOffset();
nextMatch++; while (nextMatch < matches.length && nextMatchOffset < nextlineOffset) {
if (nextMatch < matches.length) nextMatch++;
nextMatchOffset = matches[nextMatch].getOffset(); if (nextMatch < matches.length)
} nextMatchOffset = matches[nextMatch].getOffset();
int lineMatchesCount = nextMatch - firstMatch; }
Match[] lineMatches = new Match[lineMatchesCount]; int lineMatchesCount = nextMatch - firstMatch;
System.arraycopy(matches, firstMatch, lineMatches, 0, lineMatchesCount); Match[] lineMatches = new Match[lineMatchesCount];
String content = document.get(lineOffset, lineLength); System.arraycopy(matches, firstMatch, lineMatches, 0, lineMatchesCount);
result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber + 1, content, lineOffset)); String content = document.get(lineOffset, lineLength);
firstMatch = nextMatch; result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber + 1, content, lineOffset));
} catch (BadLocationException e) { firstMatch = nextMatch;
CUIPlugin.log(e); } catch (BadLocationException e) {
} CUIPlugin.log(e);
} }
return result.toArray(new LineSearchElement[result.size()]); }
} return result.toArray(new LineSearchElement[result.size()]);
}
private static LineSearchElement[] collectLineElements(char[] buffer, Match[] matches,
IIndexFileLocation fileLocation) { private static LineSearchElement[] collectLineElements(AbstractCharArray buf, Match[] matches,
List<LineSearchElement> result = new ArrayList<LineSearchElement>(); IIndexFileLocation fileLocation) {
boolean skipLF = false; List<LineSearchElement> result = new ArrayList<LineSearchElement>();
int lineNumber = 1; boolean skipLF = false;
int lineOffset = 0; int lineNumber = 1;
int lineFirstMatch = -1; // not matched int lineOffset = 0;
int nextMatch = 0; int lineFirstMatch = -1; // not matched
int nextMatchOffset = matches[nextMatch].getOffset(); int nextMatch = 0;
for (int pos = 0; pos < buffer.length; pos++) { int nextMatchOffset = matches[nextMatch].getOffset();
char c = buffer[pos]; for (int pos = 0; buf.isValidOffset(pos); pos++) {
// consider '\n' and '\r' char c = buf.get(pos);
if (skipLF) { // consider '\n' and '\r'
skipLF = false; if (skipLF) {
if (c == '\n') { skipLF = false;
lineOffset = pos + 1; if (c == '\n') {
continue; lineOffset = pos + 1;
} continue;
} }
if (c == '\n' || c == '\r') { }
// create new LineElement if there were matches if (c == '\n' || c == '\r') {
if (lineFirstMatch != -1) { // create new LineElement if there were matches
int lineLength = pos - lineOffset; if (lineFirstMatch != -1) {
int lineMatchesCount = nextMatch - lineFirstMatch; int lineLength = pos - lineOffset;
Match[] lineMatches = new Match[lineMatchesCount]; int lineMatchesCount = nextMatch - lineFirstMatch;
System.arraycopy(matches, lineFirstMatch, lineMatches, 0, lineMatchesCount); Match[] lineMatches = new Match[lineMatchesCount];
String lineContent = new String(buffer, lineOffset, lineLength); System.arraycopy(matches, lineFirstMatch, lineMatches, 0, lineMatchesCount);
result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber, lineContent, char[] lineChars= new char[lineLength];
lineOffset)); buf.arraycopy(lineOffset, lineChars, 0, lineLength);
lineFirstMatch = -1; String lineContent = new String(lineChars);
if (nextMatch >= matches.length) result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber, lineContent,
break; lineOffset));
if (matches[nextMatch].getOffset() < pos) lineFirstMatch = -1;
lineFirstMatch = nextMatch; if (nextMatch >= matches.length)
} break;
lineNumber++; if (matches[nextMatch].getOffset() < pos)
lineOffset = pos + 1; lineFirstMatch = nextMatch;
if (c == '\r') }
skipLF = true; lineNumber++;
continue; lineOffset = pos + 1;
} if (c == '\r')
// compare offset of next match with current position skipLF = true;
if (nextMatchOffset > pos) continue;
continue; }
// next match was reached // compare offset of next match with current position
// check if this match is the first for current line if (nextMatchOffset > pos)
if (lineFirstMatch == -1) continue;
lineFirstMatch = nextMatch; // next match was reached
// goto to next match // check if this match is the first for current line
nextMatch++; if (lineFirstMatch == -1)
if (nextMatch < matches.length) { lineFirstMatch = nextMatch;
// update offset of next match // goto to next match
nextMatchOffset = matches[nextMatch].getOffset(); nextMatch++;
} else { if (nextMatch < matches.length) {
// no more matches // update offset of next match
nextMatchOffset = buffer.length; nextMatchOffset = matches[nextMatch].getOffset();
} } else {
} // no more matches
// check if there were matches on the last line break;
if (lineFirstMatch != -1) { }
int lineLength = buffer.length - lineOffset; }
int lineMatchesCount = nextMatch - lineFirstMatch; // check if there were matches on the last line
Match[] lineMatches = new Match[lineMatchesCount]; if (lineFirstMatch != -1) {
System.arraycopy(matches, lineFirstMatch, lineMatches, 0, lineMatchesCount); int lineLength = buf.getLength() - lineOffset;
String lineContent = new String(buffer, lineOffset, lineLength); int lineMatchesCount = nextMatch - lineFirstMatch;
result.add(new LineSearchElement(fileLocation, lineMatches, lineNumber, lineContent, lineOffset)); Match[] lineMatches = new Match[lineMatchesCount];
} System.arraycopy(matches, lineFirstMatch, lineMatches, 0, lineMatchesCount);
return result.toArray(new LineSearchElement[result.size()]);
} 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()]);
}
}