### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java,v retrieving revision 1.61 diff -u -r1.61 AttachSourceTests.java --- src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java 8 Jul 2009 06:32:16 -0000 1.61 +++ src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java 18 Aug 2009 23:17:17 -0000 @@ -36,7 +36,7 @@ */ public class AttachSourceTests extends ModifyingResourceTests { static { -// TESTS_NAMES = new String[] { "testClassFileGetElementAt04" }; +// TESTS_NAMES = new String[] { "testClassFileBuffer" }; // TESTS_NUMBERS = new int[] { 5 }; // TESTS_RANGE = new int[] { 169, 180 }; } @@ -312,7 +312,8 @@ "Unexpected element", "V(inner.X, java.lang.String) [in V [in X$V.class [in inner [in innerClasses.jar [in AttachSourceTests]]]]]", element); -}/* +} +/* * Ensures that the source of a .class file is implicetely attached when prj=src=bin * (regression test for bug 41444 [navigation] error dialog on opening class file) */ @@ -1484,4 +1485,14 @@ assertFalse(SourceRange.isAvailable(null)); assertFalse(SourceRange.isAvailable(new SourceRange(-1, 0))); } +/* + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=285230 + */ +public void testClassFileBuffer() throws JavaModelException { + IClassFile classFile = this.innerClasses.getClassFile("X$V.class"); + IBuffer buffer = classFile.getBuffer(); + classFile = this.innerClasses.getClassFile("X.class"); + IBuffer buffer2 = classFile.getBuffer(); + assertTrue("Same buffer is not reused", buffer2 == buffer); +} } #P org.eclipse.jdt.core Index: model/org/eclipse/jdt/internal/core/SourceMapper.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java,v retrieving revision 1.141 diff -u -r1.141 SourceMapper.java --- model/org/eclipse/jdt/internal/core/SourceMapper.java 8 Jul 2009 06:32:32 -0000 1.141 +++ model/org/eclipse/jdt/internal/core/SourceMapper.java 18 Aug 2009 23:17:18 -0000 @@ -1208,7 +1208,10 @@ this.methodParameterNames = new char[1][][]; this.anonymousCounter = 0; - HashMap oldSourceRanges = (HashMap) this.sourceRanges.clone(); + HashMap oldSourceRanges = null; + if (elementToFind != null) { + oldSourceRanges = (HashMap) this.sourceRanges.clone(); + } try { IProblemFactory factory = new DefaultProblemFactory(); SourceElementParser parser = null; Index: model/org/eclipse/jdt/internal/core/ClassFile.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java,v retrieving revision 1.145 diff -u -r1.145 ClassFile.java --- model/org/eclipse/jdt/internal/core/ClassFile.java 8 Jul 2009 06:32:33 -0000 1.145 +++ model/org/eclipse/jdt/internal/core/ClassFile.java 18 Aug 2009 23:17:18 -0000 @@ -625,17 +625,24 @@ * @see Openable */ protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException { - SourceMapper mapper = getSourceMapper(); - if (mapper != null) { - return mapSource(mapper, info instanceof IBinaryType ? (IBinaryType) info : null); + // Check the cache for the top-level type first + IType outerMostEnclosingType = getOuterMostEnclosingType(); + IBuffer buffer = getBufferManager().getBuffer(outerMostEnclosingType.getClassFile()); + if (buffer == null) { + SourceMapper mapper = getSourceMapper(); + IBinaryType typeInfo = info instanceof IBinaryType ? (IBinaryType) info : null; + if (mapper != null) { + buffer = mapSource(mapper, typeInfo, outerMostEnclosingType.getClassFile()); + } } - return null; + return buffer; } -private IBuffer mapSource(SourceMapper mapper, IBinaryType info) { +/** Loads the buffer via SourceMapper, and maps it in SourceMapper */ +private IBuffer mapSource(SourceMapper mapper, IBinaryType info, IClassFile bufferOwner) { char[] contents = mapper.findSource(getType(), info); if (contents != null) { // create buffer - IBuffer buffer = BufferManager.createBuffer(this); + IBuffer buffer = BufferManager.createBuffer(bufferOwner); if (buffer == null) return null; BufferManager bufManager = getBufferManager(); bufManager.addBuffer(buffer); @@ -649,12 +656,12 @@ buffer.addBufferChangedListener(this); // do the source mapping - mapper.mapSource(getType(), contents, info); + mapper.mapSource(getOuterMostEnclosingType(), contents, info); return buffer; } else { // create buffer - IBuffer buffer = BufferManager.createNullBuffer(this); + IBuffer buffer = BufferManager.createNullBuffer(bufferOwner); if (buffer == null) return null; BufferManager bufManager = getBufferManager(); bufManager.addBuffer(buffer); @@ -674,6 +681,18 @@ else return simpleName; } + +/** Returns the type of the top-level declaring class used to find the source code */ +private IType getOuterMostEnclosingType() { + IType type = getType(); + IType enclosingType = type.getDeclaringType(); + while (enclosingType != null) { + type = enclosingType; + enclosingType = type.getDeclaringType(); + } + return type; +} + /** * Returns the Java Model representation of the given name * which is provided in diet class file format, or null