Fixed special cases of INDEX function (single columns / single rows, and errors)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@693658 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2640d092ea
commit
27c3aeb55f
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
<release version="3.1.1-alpha1" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">Fixed special cases of INDEX function (single column/single row, errors)</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45761 - Support for Very Hidden excel sheets in HSSF</action>
|
<action dev="POI-DEVELOPERS" type="add">45761 - Support for Very Hidden excel sheets in HSSF</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45738 - Initial HWPF support for Office Art Shapes</action>
|
<action dev="POI-DEVELOPERS" type="add">45738 - Initial HWPF support for Office Art Shapes</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45720 - Fixed HSSFWorkbook.cloneSheet to correctly clone sheets with drawings</action>
|
<action dev="POI-DEVELOPERS" type="fix">45720 - Fixed HSSFWorkbook.cloneSheet to correctly clone sheets with drawings</action>
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
<!-- Don't forget to update changes.xml too! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
<release version="3.1.1-alpha1" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">Fixed special cases of INDEX function (single column/single row, errors)</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45761 - Support for Very Hidden excel sheets in HSSF</action>
|
<action dev="POI-DEVELOPERS" type="add">45761 - Support for Very Hidden excel sheets in HSSF</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45738 - Initial HWPF support for Office Art Shapes</action>
|
<action dev="POI-DEVELOPERS" type="add">45738 - Initial HWPF support for Office Art Shapes</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45720 - Fixed HSSFWorkbook.cloneSheet to correctly clone sheets with drawings</action>
|
<action dev="POI-DEVELOPERS" type="fix">45720 - Fixed HSSFWorkbook.cloneSheet to correctly clone sheets with drawings</action>
|
||||||
|
@ -22,6 +22,7 @@ import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
|||||||
import org.apache.poi.hssf.record.formula.eval.Eval;
|
import org.apache.poi.hssf.record.formula.eval.Eval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
|
import org.apache.poi.hssf.record.formula.eval.EvaluationException;
|
||||||
import org.apache.poi.hssf.record.formula.eval.OperandResolver;
|
import org.apache.poi.hssf.record.formula.eval.OperandResolver;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.RefEval;
|
||||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,6 +52,10 @@ public final class Index implements Function {
|
|||||||
return ErrorEval.VALUE_INVALID;
|
return ErrorEval.VALUE_INVALID;
|
||||||
}
|
}
|
||||||
Eval firstArg = args[0];
|
Eval firstArg = args[0];
|
||||||
|
if (firstArg instanceof RefEval) {
|
||||||
|
// convert to area ref for simpler code in getValueFromArea()
|
||||||
|
firstArg = ((RefEval)firstArg).offset(0, 0, 0, 0);
|
||||||
|
}
|
||||||
if(!(firstArg instanceof AreaEval)) {
|
if(!(firstArg instanceof AreaEval)) {
|
||||||
|
|
||||||
// else the other variation of this function takes an array as the first argument
|
// else the other variation of this function takes an array as the first argument
|
||||||
@ -84,16 +89,63 @@ public final class Index implements Function {
|
|||||||
// too many arguments
|
// too many arguments
|
||||||
return ErrorEval.VALUE_INVALID;
|
return ErrorEval.VALUE_INVALID;
|
||||||
}
|
}
|
||||||
return getValueFromArea(reference, rowIx, columnIx);
|
return getValueFromArea(reference, rowIx, columnIx, nArgs);
|
||||||
} catch (EvaluationException e) {
|
} catch (EvaluationException e) {
|
||||||
return e.getErrorEval();
|
return e.getErrorEval();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ValueEval getValueFromArea(AreaEval ae, int rowIx, int columnIx) throws EvaluationException {
|
/**
|
||||||
|
* @param nArgs - needed because error codes are slightly different when only 2 args are passed
|
||||||
|
*/
|
||||||
|
private static ValueEval getValueFromArea(AreaEval ae, int pRowIx, int pColumnIx, int nArgs) throws EvaluationException {
|
||||||
|
int rowIx;
|
||||||
|
int columnIx;
|
||||||
|
|
||||||
|
// when the area ref is a single row or a single column,
|
||||||
|
// there are special rules for conversion of rowIx and columnIx
|
||||||
|
if (ae.isRow()) {
|
||||||
|
if (ae.isColumn()) {
|
||||||
|
rowIx = pRowIx == -1 ? 0 : pRowIx;
|
||||||
|
columnIx = pColumnIx == -1 ? 0 : pColumnIx;
|
||||||
|
} else {
|
||||||
|
if (nArgs == 2) {
|
||||||
|
rowIx = 0;
|
||||||
|
columnIx = pRowIx;
|
||||||
|
} else {
|
||||||
|
rowIx = pRowIx == -1 ? 0 : pRowIx;
|
||||||
|
columnIx = pColumnIx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rowIx < -1 || columnIx < -1) {
|
||||||
|
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||||
|
}
|
||||||
|
} else if (ae.isColumn()) {
|
||||||
|
if (nArgs == 2) {
|
||||||
|
rowIx = pRowIx;
|
||||||
|
columnIx = 0;
|
||||||
|
} else {
|
||||||
|
rowIx = pRowIx;
|
||||||
|
columnIx = pColumnIx == -1 ? 0 : pColumnIx;
|
||||||
|
}
|
||||||
|
if (rowIx < -1 || columnIx < -1) {
|
||||||
|
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (nArgs == 2) {
|
||||||
|
// always an error with 2-D area refs
|
||||||
|
if (pRowIx < -1) {
|
||||||
|
throw new EvaluationException(ErrorEval.VALUE_INVALID);
|
||||||
|
}
|
||||||
|
throw new EvaluationException(ErrorEval.REF_INVALID);
|
||||||
|
}
|
||||||
|
// Normal case - area ref is 2-D, and both index args were provided
|
||||||
|
rowIx = pRowIx;
|
||||||
|
columnIx = pColumnIx;
|
||||||
|
}
|
||||||
|
|
||||||
int width = ae.getWidth();
|
int width = ae.getWidth();
|
||||||
int height = ae.getHeight();
|
int height = ae.getHeight();
|
||||||
|
|
||||||
// Slightly irregular logic for bounds checking errors
|
// Slightly irregular logic for bounds checking errors
|
||||||
if (rowIx >= height || columnIx >= width) {
|
if (rowIx >= height || columnIx >= width) {
|
||||||
throw new EvaluationException(ErrorEval.REF_INVALID);
|
throw new EvaluationException(ErrorEval.REF_INVALID);
|
||||||
|
Binary file not shown.
@ -34,6 +34,7 @@ public final class AllIndividualFunctionEvaluationTests {
|
|||||||
result.addTestSuite(TestDate.class);
|
result.addTestSuite(TestDate.class);
|
||||||
result.addTestSuite(TestFinanceLib.class);
|
result.addTestSuite(TestFinanceLib.class);
|
||||||
result.addTestSuite(TestIndex.class);
|
result.addTestSuite(TestIndex.class);
|
||||||
|
result.addTestSuite(TestIndexFunctionFromSpreadsheet.class);
|
||||||
result.addTestSuite(TestIsBlank.class);
|
result.addTestSuite(TestIsBlank.class);
|
||||||
result.addTestSuite(TestLen.class);
|
result.addTestSuite(TestLen.class);
|
||||||
result.addTestSuite(TestLookupFunctionsFromSpreadsheet.class);
|
result.addTestSuite(TestLookupFunctionsFromSpreadsheet.class);
|
||||||
|
@ -48,11 +48,11 @@ public final class TestIndex extends TestCase {
|
|||||||
double[] values = TEST_VALUES0;
|
double[] values = TEST_VALUES0;
|
||||||
confirmAreaEval("C1:D6", values, 4, 1, 7);
|
confirmAreaEval("C1:D6", values, 4, 1, 7);
|
||||||
confirmAreaEval("C1:D6", values, 6, 2, 12);
|
confirmAreaEval("C1:D6", values, 6, 2, 12);
|
||||||
confirmAreaEval("C1:D6", values, 3, -1, 5);
|
confirmAreaEval("C1:D6", values, 3, 1, 5);
|
||||||
|
|
||||||
// now treat same data as 3 columns, 4 rows
|
// now treat same data as 3 columns, 4 rows
|
||||||
confirmAreaEval("C10:E13", values, 2, 2, 5);
|
confirmAreaEval("C10:E13", values, 2, 2, 5);
|
||||||
confirmAreaEval("C10:E13", values, 4, -1, 10);
|
confirmAreaEval("C10:E13", values, 4, 1, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,259 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.hssf.record.formula.functions;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
import junit.framework.AssertionFailedError;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.CellValue;
|
||||||
|
import org.apache.poi.hssf.util.CellReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests INDEX() as loaded from a test data spreadsheet.<p/>
|
||||||
|
*
|
||||||
|
* @author Josh Micich
|
||||||
|
*/
|
||||||
|
public final class TestIndexFunctionFromSpreadsheet extends TestCase {
|
||||||
|
|
||||||
|
private static final class Result {
|
||||||
|
public static final int SOME_EVALUATIONS_FAILED = -1;
|
||||||
|
public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
|
||||||
|
public static final int NO_EVALUATIONS_FOUND = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class defines constants for navigating around the test data spreadsheet used for these tests.
|
||||||
|
*/
|
||||||
|
private static final class SS {
|
||||||
|
|
||||||
|
/** Name of the test spreadsheet (found in the standard test data folder) */
|
||||||
|
public final static String FILENAME = "IndexFunctionTestCaseData.xls";
|
||||||
|
|
||||||
|
public static final int COLUMN_INDEX_EVALUATION = 2; // Column 'C'
|
||||||
|
public static final int COLUMN_INDEX_EXPECTED_RESULT = 3; // Column 'D'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note - multiple failures are aggregated before ending.
|
||||||
|
// If one or more functions fail, a single AssertionFailedError is thrown at the end
|
||||||
|
private int _evaluationFailureCount;
|
||||||
|
private int _evaluationSuccessCount;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static void confirmExpectedResult(String msg, HSSFCell expected, HSSFFormulaEvaluator.CellValue actual) {
|
||||||
|
if (expected == null) {
|
||||||
|
throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
|
||||||
|
}
|
||||||
|
if(actual == null) {
|
||||||
|
throw new AssertionFailedError(msg + " - actual value was null");
|
||||||
|
}
|
||||||
|
if(expected.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
|
||||||
|
confirmErrorResult(msg, expected.getErrorCellValue(), actual);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(actual.getCellType() == HSSFCell.CELL_TYPE_ERROR) {
|
||||||
|
throw unexpectedError(msg, expected, actual.getErrorValue());
|
||||||
|
}
|
||||||
|
if(actual.getCellType() != expected.getCellType()) {
|
||||||
|
throw wrongTypeError(msg, expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (expected.getCellType()) {
|
||||||
|
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||||
|
assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
|
||||||
|
break;
|
||||||
|
case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
|
||||||
|
throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
|
||||||
|
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||||
|
assertEquals(expected.getNumericCellValue(), actual.getNumberValue(), 0.0);
|
||||||
|
break;
|
||||||
|
case HSSFCell.CELL_TYPE_STRING:
|
||||||
|
assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getRichTextStringValue().getString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) {
|
||||||
|
return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was "
|
||||||
|
+ formatValue(actualValue)
|
||||||
|
+ " but the expected result was "
|
||||||
|
+ formatValue(expectedCell)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
private static AssertionFailedError unexpectedError(String msgPrefix, HSSFCell expected, int actualErrorCode) {
|
||||||
|
return new AssertionFailedError(msgPrefix + " Error code ("
|
||||||
|
+ ErrorEval.getText(actualErrorCode)
|
||||||
|
+ ") was evaluated, but the expected result was "
|
||||||
|
+ formatValue(expected)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void confirmErrorResult(String msgPrefix, int expectedErrorCode, CellValue actual) {
|
||||||
|
if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) {
|
||||||
|
throw new AssertionFailedError(msgPrefix + " Expected cell error ("
|
||||||
|
+ ErrorEval.getText(expectedErrorCode) + ") but actual value was "
|
||||||
|
+ formatValue(actual));
|
||||||
|
}
|
||||||
|
if(expectedErrorCode != actual.getErrorValue()) {
|
||||||
|
throw new AssertionFailedError(msgPrefix + " Expected cell error code ("
|
||||||
|
+ ErrorEval.getText(expectedErrorCode)
|
||||||
|
+ ") but actual error code was ("
|
||||||
|
+ ErrorEval.getText(actual.getErrorValue())
|
||||||
|
+ ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String formatValue(HSSFCell expecedCell) {
|
||||||
|
switch (expecedCell.getCellType()) {
|
||||||
|
case HSSFCell.CELL_TYPE_BLANK: return "<blank>";
|
||||||
|
case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(expecedCell.getBooleanCellValue());
|
||||||
|
case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(expecedCell.getNumericCellValue());
|
||||||
|
case HSSFCell.CELL_TYPE_STRING: return expecedCell.getRichStringCellValue().getString();
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")");
|
||||||
|
}
|
||||||
|
private static String formatValue(CellValue actual) {
|
||||||
|
switch (actual.getCellType()) {
|
||||||
|
case HSSFCell.CELL_TYPE_BLANK: return "<blank>";
|
||||||
|
case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(actual.getBooleanValue());
|
||||||
|
case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(actual.getNumberValue());
|
||||||
|
case HSSFCell.CELL_TYPE_STRING: return actual.getRichTextStringValue().getString();
|
||||||
|
}
|
||||||
|
throw new RuntimeException("Unexpected cell type of evaluated value (" + actual.getCellType() + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void setUp() {
|
||||||
|
_evaluationFailureCount = 0;
|
||||||
|
_evaluationSuccessCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFunctionsFromTestSpreadsheet() {
|
||||||
|
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
|
||||||
|
|
||||||
|
processTestSheet(workbook, workbook.getSheetName(0));
|
||||||
|
|
||||||
|
// confirm results
|
||||||
|
String successMsg = "There were "
|
||||||
|
+ _evaluationSuccessCount + " function(s) without error";
|
||||||
|
if(_evaluationFailureCount > 0) {
|
||||||
|
String msg = _evaluationFailureCount + " evaluation(s) failed. " + successMsg;
|
||||||
|
throw new AssertionFailedError(msg);
|
||||||
|
}
|
||||||
|
if(false) { // normally no output for successful tests
|
||||||
|
System.out.println(getClass().getName() + ": " + successMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processTestSheet(HSSFWorkbook workbook, String sheetName) {
|
||||||
|
HSSFSheet sheet = workbook.getSheetAt(0);
|
||||||
|
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, workbook);
|
||||||
|
int maxRows = sheet.getLastRowNum()+1;
|
||||||
|
int result = Result.NO_EVALUATIONS_FOUND; // so far
|
||||||
|
|
||||||
|
for(int rowIndex=0; rowIndex<maxRows; rowIndex++) {
|
||||||
|
HSSFRow r = sheet.getRow(rowIndex);
|
||||||
|
if(r == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
HSSFCell c = r.getCell(SS.COLUMN_INDEX_EVALUATION);
|
||||||
|
if (c == null || c.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CellValue actualValue = evaluator.evaluate(c);
|
||||||
|
HSSFCell expectedValueCell = r.getCell(SS.COLUMN_INDEX_EXPECTED_RESULT);
|
||||||
|
|
||||||
|
String msgPrefix = formatTestCaseDetails(sheetName, r.getRowNum(), c);
|
||||||
|
try {
|
||||||
|
confirmExpectedResult(msgPrefix, expectedValueCell, actualValue);
|
||||||
|
_evaluationSuccessCount ++;
|
||||||
|
if(result != Result.SOME_EVALUATIONS_FAILED) {
|
||||||
|
result = Result.ALL_EVALUATIONS_SUCCEEDED;
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
_evaluationFailureCount ++;
|
||||||
|
printShortStackTrace(System.err, e);
|
||||||
|
result = Result.SOME_EVALUATIONS_FAILED;
|
||||||
|
} catch (AssertionFailedError e) {
|
||||||
|
_evaluationFailureCount ++;
|
||||||
|
printShortStackTrace(System.err, e);
|
||||||
|
result = Result.SOME_EVALUATIONS_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String formatTestCaseDetails(String sheetName, int rowNum, HSSFCell c) {
|
||||||
|
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
CellReference cr = new CellReference(sheetName, rowNum, c.getCellNum(), false, false);
|
||||||
|
sb.append(cr.formatAsString());
|
||||||
|
sb.append(" {=").append(c.getCellFormula()).append("}");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Useful to keep output concise when expecting many failures to be reported by this test case
|
||||||
|
*/
|
||||||
|
private static void printShortStackTrace(PrintStream ps, Throwable e) {
|
||||||
|
StackTraceElement[] stes = e.getStackTrace();
|
||||||
|
|
||||||
|
int startIx = 0;
|
||||||
|
// skip any top frames inside junit.framework.Assert
|
||||||
|
while(startIx<stes.length) {
|
||||||
|
if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
startIx++;
|
||||||
|
}
|
||||||
|
// skip bottom frames (part of junit framework)
|
||||||
|
int endIx = startIx+1;
|
||||||
|
while(endIx < stes.length) {
|
||||||
|
if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
endIx++;
|
||||||
|
}
|
||||||
|
if(startIx >= endIx) {
|
||||||
|
// something went wrong. just print the whole stack trace
|
||||||
|
e.printStackTrace(ps);
|
||||||
|
}
|
||||||
|
endIx -= 4; // skip 4 frames of reflection invocation
|
||||||
|
ps.println(e.toString());
|
||||||
|
for(int i=startIx; i<endIx; i++) {
|
||||||
|
ps.println("\tat " + stes[i].toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user