diff options
27 files changed, 427 insertions, 224 deletions
@@ -676,6 +676,7 @@ <exclude name="com/android/jack/frontend/test014/jack/ExtendingInnerInStaticContext.java"/> <exclude name="com/android/jack/frontend/test015/jack/WithOuterContextButStatic.java"/> <exclude name="com/android/jack/frontend/test016/jack/WithDuplicated.java"/> + <exclude name="com/android/jack/frontend/test017/jack/InvalidQualification.java"/> <exclude name="com/android/jack/nopackage/jack/**"/> <exclude name="com/android/jack/java7/boxing/**"/> <exclude name="com/android/jack/java7/switches/**"/> @@ -721,6 +722,7 @@ <exclude name="com/android/jack/frontend/test014/jack/ExtendingInnerInStaticContext.java"/> <exclude name="com/android/jack/frontend/test015/jack/WithOuterContextButStatic.java"/> <exclude name="com/android/jack/frontend/test016/jack/WithDuplicated.java"/> + <exclude name="com/android/jack/frontend/test017/jack/InvalidQualification.java"/> <exclude name="com/android/jack/nopackage/jack/**"/> <exclude name="com/android/jack/java7/boxing/**"/> <exclude name="com/android/jack/java7/switches/**"/> diff --git a/dx/src/com/android/jack/dx/dex/file/DexFile.java b/dx/src/com/android/jack/dx/dex/file/DexFile.java index 2de5c9cc..c52ee124 100644 --- a/dx/src/com/android/jack/dx/dex/file/DexFile.java +++ b/dx/src/com/android/jack/dx/dex/file/DexFile.java @@ -22,7 +22,7 @@ import com.android.jack.dx.rop.cst.Constant; import com.android.jack.dx.rop.cst.CstBaseMethodRef; import com.android.jack.dx.rop.cst.CstEnumRef; import com.android.jack.dx.rop.cst.CstFieldRef; -import com.android.jack.dx.rop.cst.CstIndexMap; +import com.android.jack.dx.rop.cst.CstMethodRef; import com.android.jack.dx.rop.cst.CstString; import com.android.jack.dx.rop.cst.CstType; import com.android.jack.dx.rop.type.Type; @@ -35,9 +35,11 @@ import java.io.Writer; import java.security.DigestException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.util.List; +import java.util.Collection; import java.util.zip.Adler32; +import javax.annotation.Nonnull; + /** * Representation of an entire {@code .dex} (Dalvik EXecutable) * file, which itself consists of a set of Dalvik classes. @@ -493,20 +495,39 @@ public final class DexFile { * particular offsets. */ public void prepare() { - prepare(null); + prepare(null, null, null, null); } /** * Prepares this instance for writing. This performs any necessary prerequisites, including * particularly adding stuff to other sections and places all the items in this instance at * particular offsets. - * - * @param cstIndexMaps list used to map offsets from a dex file to this instance - */ - public void prepare(List<CstIndexMap> cstIndexMaps) { - if (cstIndexMaps != null) { - for (CstIndexMap cstIndexMap : cstIndexMaps) { - cstIndexMap.mergeConstantsIntoDexFile(this); + * @param cstStrings Collection of CstString to intern + * @param cstFieldRefs Collection of CstFieldRef to intern + * @param cstMethodRefs Collection of CstMethodRef to intern + * @param cstTypes Collection of CstType to intern + */ + public void prepare(@Nonnull Collection<CstString> cstStrings, + @Nonnull Collection<CstFieldRef> cstFieldRefs, + @Nonnull Collection<CstMethodRef> cstMethodRefs, @Nonnull Collection<CstType> cstTypes) { + if (cstStrings != null) { + for (CstString cst : cstStrings) { + stringIds.intern(cst); + } + } + if (cstFieldRefs != null) { + for (CstFieldRef cst : cstFieldRefs) { + fieldIds.intern(cst); + } + } + if (cstMethodRefs != null) { + for (CstMethodRef cst : cstMethodRefs) { + methodIds.intern(cst); + } + } + if (cstTypes != null) { + for (CstType cst : cstTypes) { + typeIds.intern(cst); } } diff --git a/dx/src/com/android/jack/dx/io/DexBuffer.java b/dx/src/com/android/jack/dx/io/DexBuffer.java index 8f3c7c39..88840075 100644 --- a/dx/src/com/android/jack/dx/io/DexBuffer.java +++ b/dx/src/com/android/jack/dx/io/DexBuffer.java @@ -45,6 +45,9 @@ import java.util.NoSuchElementException; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; + /** * The bytes of a dex file in memory for reading and writing. All int offsets * are unsigned. @@ -64,7 +67,8 @@ public final class DexBuffer { @Override public ProtoId get(int index) { checkBounds(index, tableOfContents.protoIds.size); - return open(tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * index)).readProtoId(); + return openInternal(tableOfContents.protoIds.off + (SizeOf.PROTO_ID_ITEM * index)) + .readProtoId(); } @Override @@ -77,11 +81,15 @@ public final class DexBuffer { private final List<MethodId> methodIds; + @Nonnull + private final Section internalSection; + /** * Creates a new dex buffer defining no classes. */ public DexBuffer() { this.data = new byte[0]; + this.internalSection = new Section(0); this.strings = Collections.emptyList(); this.typeIds = Collections.emptyList(); this.typeNames = Collections.emptyList(); @@ -95,6 +103,7 @@ public final class DexBuffer { */ public DexBuffer(byte[] data) { this.data = data; + this.internalSection = new Section(0); this.length = data.length; this.tableOfContents.readFrom(this); this.strings = readStrings(); @@ -109,6 +118,7 @@ public final class DexBuffer { */ public DexBuffer(InputStream in) throws IOException { loadFrom(in); + this.internalSection = new Section(0); this.strings = readStrings(); this.typeIds = readTypeIds(); this.typeNames = readTypeNames(this.strings, this.typeIds); @@ -135,6 +145,7 @@ public final class DexBuffer { } else { throw new DexException("unknown output extension: " + file); } + this.internalSection = new Section(0); this.strings = readStrings(); this.typeIds = readTypeIds(); this.typeNames = readTypeNames(this.strings, this.typeIds); @@ -143,7 +154,7 @@ public final class DexBuffer { } private List<String> readStrings() { - Section strings = open(tableOfContents.stringIds.off); + Section strings = openInternal(tableOfContents.stringIds.off); String[] result = new String[tableOfContents.stringIds.size]; for (int i = 0; i < tableOfContents.stringIds.size; ++i) { result[i] = strings.readString(); @@ -152,7 +163,7 @@ public final class DexBuffer { } private List<Integer> readTypeIds() { - Section typeIds = open(tableOfContents.typeIds.off); + Section typeIds = openInternal(tableOfContents.typeIds.off); Integer[] result = new Integer[tableOfContents.typeIds.size]; for (int i = 0; i < tableOfContents.typeIds.size; ++i) { result[i] = Integer.valueOf(typeIds.readInt()); @@ -169,7 +180,7 @@ public final class DexBuffer { } private List<FieldId> readFieldIds() { - Section fieldIds = open(tableOfContents.fieldIds.off); + Section fieldIds = openInternal(tableOfContents.fieldIds.off); FieldId[] result = new FieldId[tableOfContents.fieldIds.size]; for (int i = 0; i < tableOfContents.fieldIds.size; ++i) { result[i] = fieldIds.readFieldId(); @@ -178,7 +189,7 @@ public final class DexBuffer { } private List<MethodId> readMethodIds() { - Section methodIds = open(tableOfContents.methodIds.off); + Section methodIds = openInternal(tableOfContents.methodIds.off); MethodId[] result = new MethodId[tableOfContents.methodIds.size]; for (int i = 0; i < tableOfContents.methodIds.size; ++i) { result[i] = methodIds.readMethodId(); @@ -221,6 +232,12 @@ public final class DexBuffer { return tableOfContents; } + @Nonnull + private Section openInternal(@Nonnegative int position) { + internalSection.initialPosition = internalSection.position = position; + return internalSection; + } + public Section open(int position) { if (position < 0 || position > length) { throw new IllegalArgumentException("position=" + position + " length=" + length); @@ -313,7 +330,7 @@ public final class DexBuffer { if (offset == 0) { return TypeList.EMPTY; } - return open(offset).readTypeList(); + return openInternal(offset).readTypeList(); } public ClassData readClassData(ClassDef classDef) { @@ -321,7 +338,7 @@ public final class DexBuffer { if (offset == 0) { throw new IllegalArgumentException("offset == 0"); } - return open(offset).readClassData(); + return openInternal(offset).readClassData(); } public Code readCode(ClassData.Method method) { @@ -329,7 +346,7 @@ public final class DexBuffer { if (offset == 0) { throw new IllegalArgumentException("offset == 0"); } - return open(offset).readCode(); + return openInternal(offset).readCode(); } /** @@ -339,7 +356,7 @@ public final class DexBuffer { private final String name; private int position; private final int limit; - private final int initialPosition; + private int initialPosition; private Section(String name, int position, int limit) { this.name = name; @@ -496,10 +513,11 @@ public final class DexBuffer { * Unfortunately they're in the opposite order in the dex file * so we need to read them out-of-order. */ - Section triesSection = open(position); + int savedPosition = position; skip(triesSize * SizeOf.TRY_ITEM); catchHandlers = readCatchHandlers(); - tries = triesSection.readTries(triesSize, catchHandlers); + position = savedPosition; + tries = readTries(triesSize, catchHandlers); } else { tries = new Try[0]; catchHandlers = new CatchHandler[0]; diff --git a/dx/src/com/android/jack/dx/rop/cst/CstIndexMap.java b/dx/src/com/android/jack/dx/rop/cst/CstIndexMap.java index c4ec624b..9f29bf9f 100644 --- a/dx/src/com/android/jack/dx/rop/cst/CstIndexMap.java +++ b/dx/src/com/android/jack/dx/rop/cst/CstIndexMap.java @@ -98,29 +98,6 @@ public class CstIndexMap { } /** - * Merge all {@link TypedConstant} of one dex file into another. - * @param dex The dex file where values are merged. - */ - public void mergeConstantsIntoDexFile(DexFile dex) { - for (CstString cst : strings) { - dex.getStringIds().intern(cst); - } - - for (CstBaseMethodRef cst : methods) { - dex.getMethodIds().intern(cst); - } - - for (CstFieldRef cst : fields) { - dex.getFieldIds().intern(cst); - } - - for (CstType cst : types) { - dex.getTypeIds().intern(cst); - } - } - - - /** * Return the remapped index of a {@code CstString} into {@code file}. * @param file The file where the remapped index apply to. * @param index The old index to remap into {@code file}. diff --git a/dx/src/com/android/jack/dx/ssa/Optimizer.java b/dx/src/com/android/jack/dx/ssa/Optimizer.java index 7101be01..c690fd7d 100644 --- a/dx/src/com/android/jack/dx/ssa/Optimizer.java +++ b/dx/src/com/android/jack/dx/ssa/Optimizer.java @@ -147,30 +147,21 @@ public class Optimizer { } private static void runSsaFormSteps(SsaMethod ssaMeth, EnumSet<OptionalStep> steps) { - boolean needsDeadCodeRemover = true; if (steps.contains(OptionalStep.SCCP)) { SCCP.process(ssaMeth); - DeadCodeRemover.process(ssaMeth); - needsDeadCodeRemover = false; } if (steps.contains(OptionalStep.LITERAL_UPGRADE)) { LiteralOpUpgrader.process(ssaMeth); - DeadCodeRemover.process(ssaMeth); - needsDeadCodeRemover = false; } if (steps.contains(OptionalStep.CONST_COLLECTOR)) { ConstCollector.process(ssaMeth); - DeadCodeRemover.process(ssaMeth); - needsDeadCodeRemover = false; } // dead code remover must be run before phi type resolver - if (needsDeadCodeRemover) { - DeadCodeRemover.process(ssaMeth); - } + DeadCodeRemover.process(ssaMeth); PhiTypeResolver.process(ssaMeth); } diff --git a/jack-tests/.classpath b/jack-tests/.classpath index 03ac40ae..e451b2d9 100644 --- a/jack-tests/.classpath +++ b/jack-tests/.classpath @@ -2,7 +2,7 @@ <classpath> <classpathentry kind="src" path="src"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> - <classpathentry excluding="com/android/jack/classpath/test002/lib1override/|com/android/jack/compiletime/test*/**|com/android/jack/enums/test003/link/Other.java|com/android/jack/enums/test003/link/Values.java|com/android/jack/error/test001/jack/A.java|com/android/jack/error/test002/jack/A.java|com/android/jack/jarjar/test003/dontcompile/|com/android/jack/java7/boxing/|com/android/jack/java7/exceptions/|com/android/jack/java7/parser/|com/android/jack/java7/switches/|com/android/jack/java7/trywithresources/|com/android/jack/lookup/test001/liboverride/|com/android/jack/nopackage/test*/**|com/android/jack/frontend/test002/jack/PackageName/ClassInConflictingPackage.java|com/android/jack/frontend/test005/jack/|com/android/jack/frontend/test006/jack/|com/android/jack/frontend/test007/jack/|com/android/jack/frontend/test007/jackduplicate/|com/android/jack/frontend/test008/jack/NoOuterContext.java|com/android/jack/frontend/test010/jack/UnusedLocalVar.java|com/android/jack/frontend/test013/jack/ExtendingInnerOnly.java|com/android/jack/frontend/test014/jack/ExtendingInnerInStaticContext.java|com/android/jack/frontend/test015/jack/WithOuterContextButStatic.java|com/android/jack/frontend/test016/jack/WithDuplicated.java" kind="src" path="tests"/> + <classpathentry excluding="com/android/jack/classpath/test002/lib1override/|com/android/jack/compiletime/test*/**|com/android/jack/enums/test003/link/Other.java|com/android/jack/enums/test003/link/Values.java|com/android/jack/error/test001/jack/A.java|com/android/jack/error/test002/jack/A.java|com/android/jack/jarjar/test003/dontcompile/|com/android/jack/java7/boxing/|com/android/jack/java7/exceptions/|com/android/jack/java7/parser/|com/android/jack/java7/switches/|com/android/jack/java7/trywithresources/|com/android/jack/lookup/test001/liboverride/|com/android/jack/nopackage/test*/**|com/android/jack/frontend/test002/jack/PackageName/ClassInConflictingPackage.java|com/android/jack/frontend/test005/jack/|com/android/jack/frontend/test006/jack/|com/android/jack/frontend/test007/jack/|com/android/jack/frontend/test007/jackduplicate/|com/android/jack/frontend/test008/jack/NoOuterContext.java|com/android/jack/frontend/test010/jack/UnusedLocalVar.java|com/android/jack/frontend/test013/jack/ExtendingInnerOnly.java|com/android/jack/frontend/test014/jack/ExtendingInnerInStaticContext.java|com/android/jack/frontend/test015/jack/WithOuterContextButStatic.java|com/android/jack/frontend/test016/jack/WithDuplicated.java|com/android/jack/frontend/test017/jack/InvalidQualification.java" kind="src" path="tests"/> <classpathentry kind="lib" path="libs/junit4.jar"/> <classpathentry kind="lib" path="libs/antlr-runtime-lib.jar"/> <classpathentry kind="lib" path="libs/dx-ref.jar"/> diff --git a/jack-tests/tests/com/android/jack/frontend/FrontEndTests.java b/jack-tests/tests/com/android/jack/frontend/FrontEndTests.java index 875a4b6f..aec76594 100644 --- a/jack-tests/tests/com/android/jack/frontend/FrontEndTests.java +++ b/jack-tests/tests/com/android/jack/frontend/FrontEndTests.java @@ -16,6 +16,7 @@ package com.android.jack.frontend; +import com.android.jack.Options; import com.android.jack.category.ExtraTests; import com.android.jack.test.category.KnownBugs; import com.android.jack.test.toolchain.AbstractTestTools; @@ -78,6 +79,7 @@ public class FrontEndTests { ByteArrayOutputStream err = new ByteArrayOutputStream(); toolchain.setOutputStream(out); toolchain.setErrorStream(err); + toolchain.addProperty(Options.INPUT_FILTER.getName(), "ordered-filter"); try { toolchain.addToClasspath(toolchain.getDefaultBootClasspath()) @@ -333,12 +335,11 @@ public class FrontEndTests { */ @Test @Category(ExtraTests.class) - public void testUnusedLocalVar002() throws Exception { + public void testQualifedNew001() throws Exception { File outDir = AbstractTestTools.createTempDir(); IToolchain toolchain = AbstractTestTools.getCandidateToolchain(); - - toolchain.addToClasspath(toolchain.getDefaultBootClasspath()) + toolchain.addToClasspath(toolchain.getDefaultBootClasspath()) .srcToLib( outDir, /* zipFiles= */ false, @@ -362,4 +363,34 @@ public class FrontEndTests { AbstractTestTools.getTestRootDir("com.android.jack.frontend.test012.jack")); } + /** + * Test that Jack is neither failing nor dropping the error in this case. + */ + @Test + @Category(ExtraTests.class) + public void testUnusedLocalVar004() throws Exception { + File outDir = AbstractTestTools.createTempDir(); + + IToolchain toolchain = + AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayOutputStream err = new ByteArrayOutputStream(); + toolchain.setOutputStream(out); + toolchain.setErrorStream(err); + + try { + toolchain.addToClasspath(toolchain.getDefaultBootClasspath()) + .srcToLib( + outDir, + /* zipFiles= */ false, + AbstractTestTools.getTestRootDir("com.android.jack.frontend.test017.jack")); + Assert.fail(); + } catch (FrontendCompilationException e) { + Assert.assertEquals(0, out.size()); + String errString = err.toString(); + Assert.assertTrue(errString.contains("ERROR:")); + Assert.assertTrue(errString.contains("InvalidQualification")); + } + } + } diff --git a/jack-tests/tests/com/android/jack/frontend/test011/jack/UnusedLocalVar.java b/jack-tests/tests/com/android/jack/frontend/test011/jack/QualifedNew.java index 6abaebf8..9fecd3d7 100644 --- a/jack-tests/tests/com/android/jack/frontend/test011/jack/UnusedLocalVar.java +++ b/jack-tests/tests/com/android/jack/frontend/test011/jack/QualifedNew.java @@ -16,7 +16,7 @@ package com.android.jack.frontend.test011.jack; -public class UnusedLocalVar extends ClassWithInner { +public class QualifedNew extends ClassWithInner { public Object get() { ClassWithInner outer = new ClassWithInner(); diff --git a/jack-tests/tests/com/android/jack/frontend/test017/jack/InvalidQualification.java b/jack-tests/tests/com/android/jack/frontend/test017/jack/InvalidQualification.java new file mode 100644 index 00000000..1443c8a1 --- /dev/null +++ b/jack-tests/tests/com/android/jack/frontend/test017/jack/InvalidQualification.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed 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 com.android.jack.frontend.test017.jack; + +public class InvalidQualification { + + public static InvalidQualification get() { + InvalidQualification unused = new InvalidQualification(); + return unused.new InvalidQualification(); + } + +} diff --git a/jack-tests/tests/com/android/jack/shrob/ShrinkTests.java b/jack-tests/tests/com/android/jack/shrob/ShrinkTests.java index 6ffa637c..c5fcfd6a 100644 --- a/jack-tests/tests/com/android/jack/shrob/ShrinkTests.java +++ b/jack-tests/tests/com/android/jack/shrob/ShrinkTests.java @@ -85,6 +85,58 @@ public class ShrinkTests extends AbstractTest { candidateNodeListing)); } + private void runTestWithLib(@Nonnull String testNumber, @Nonnull String flagNumber, + boolean importLib) throws Exception { + File testFolder = new File(shrobTestsDir, "test" + testNumber); + + File libOut = AbstractTestTools.createTempDir(); + JackApiToolchainBase toolchainLib = + AbstractTestTools.getCandidateToolchain(JackApiToolchainBase.class); + toolchainLib.addToClasspath(toolchainLib.getDefaultBootClasspath()).srcToLib(libOut, + /* zipFiles = */false, new File(shrobTestsDir, "test" + testNumber + "/lib")); + + JackBasedToolchain toolchain = + AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class); + + File refFolder = new File(testFolder, "refsShrinking"); + + File candidateNodeListing = AbstractTestTools.createTempFile("nodeListing", ".txt"); + toolchain.addProperty(ShrinkStructurePrinter.STRUCTURE_PRINTING.getName(), "true"); + toolchain.addProperty(ShrinkStructurePrinter.STRUCTURE_PRINTING_FILE.getName(), + candidateNodeListing.getPath()); + toolchain.addProperty(Options.METHOD_FILTER.getName(), "supported-methods"); + toolchain.disableDxOptimizations(); + if (importLib) { + toolchain.addStaticLibs(libOut); + } else { + toolchain.addToClasspath(libOut); + } + + File outFolder = AbstractTestTools.createTempDir(); + + SourceToDexComparisonTestHelper env = + new SourceToDexComparisonTestHelper(new File(testFolder, "jack")); + + env.setWithDebugInfo(true); + env.setCandidateTestTools(toolchain); + env.setReferenceTestTools(new DummyToolchain()); + env.setProguardFlags(dontObfuscateFlagFile, + new ProguardFlags(testFolder, "proguard.flags" + flagNumber)); + + env.runTest(new ComparatorMapping(new File(refFolder, "expected-" + flagNumber + ".txt"), + candidateNodeListing)); + } + + @Test + public void test003_001() throws Exception { + runTestWithLib("003", "001", false); + } + + @Test + public void test003_002() throws Exception { + runTestWithLib("003", "002", true); + } + @Test public void test020() throws Exception { File libOut = AbstractTestTools.createTempDir(); diff --git a/jack/src/com/android/jack/Jack.java b/jack/src/com/android/jack/Jack.java index aba7be93..7f4fd581 100644 --- a/jack/src/com/android/jack/Jack.java +++ b/jack/src/com/android/jack/Jack.java @@ -69,7 +69,7 @@ import com.android.jack.frontend.VirtualMethodsMarker; import com.android.jack.frontend.java.JackBatchCompiler; import com.android.jack.frontend.java.JackBatchCompiler.TransportExceptionAroundEcjError; import com.android.jack.frontend.java.JackBatchCompiler.TransportJUEAroundEcjError; -import com.android.jack.incremental.Incremental; +import com.android.jack.incremental.GenerateLibraryFromIncrementalFolder; import com.android.jack.ir.JackFormatIr; import com.android.jack.ir.JavaSourceIr; import com.android.jack.ir.ast.JClass; @@ -265,8 +265,6 @@ import com.android.sched.util.log.LoggerFactory; import com.android.sched.util.log.Tracer; import com.android.sched.util.log.TracerFactory; import com.android.sched.vfs.Container; -import com.android.sched.vfs.VFS; -import com.android.sched.vfs.VFSToVFSWrapper; import org.antlr.runtime.RecognitionException; @@ -517,8 +515,8 @@ public abstract class Jack { if (config.get(MultiDexLegacy.MULTIDEX_LEGACY).booleanValue()) { request.addFeature(MultiDexLegacy.class); } - if (config.get(Options.INCREMENTAL_MODE).booleanValue()) { - request.addFeature(Incremental.class); + if (config.get(Options.GENERATE_LIBRARY_FROM_INCREMENTAL_FOLDER).booleanValue()) { + request.addFeature(GenerateLibraryFromIncrementalFolder.class); } request.addInitialTagsOrMarkers(getJavaSourceInitialTagSet()); @@ -606,18 +604,6 @@ public abstract class Jack { && config.get(Options.DEX_OUTPUT_CONTAINER_TYPE) == Container.ZIP) { config.get(Options.DEX_OUTPUT_ZIP).close(); } - - if (config.get(Options.GENERATE_LIBRARY_FROM_INCREMENTAL_FOLDER).booleanValue()) { - VFS incrementalFolder = config.get(Options.LIBRARY_OUTPUT_DIR); - Event timeToZip = - TracerFactory.getTracer().start(JackEventType.ZIP_JACK_LIBRARY_IN_INCREMENTAL); - try { - new VFSToVFSWrapper(incrementalFolder, config.get(Options.LIBRARY_OUTPUT_ZIP)) - .close(); - } finally { - timeToZip.end(); - } - } } catch (LibraryIOException e) { throw new AssertionError(e); } catch (IOException e) { @@ -881,7 +867,6 @@ public abstract class Jack { FeatureSet features = planBuilder.getRequest().getFeatures(); ProductionSet productions = planBuilder.getRequest().getTargetProductions(); boolean hasSanityChecks = features.contains(SanityChecks.class); - Config config = ThreadConfig.getConfig(); // TODO(jack-team): Remove this hack boolean preDexing = !getSession().getImportedLibraries().isEmpty(); @@ -1027,12 +1012,10 @@ public abstract class Jack { { SubPlanBuilder<JDefinedClassOrInterface> typePlan; // In incremental library mode, Jayce files must be copied into output library - if (features.contains(Incremental.class) - && ((!config.get(Options.GENERATE_JACK_LIBRARY).booleanValue()) - || config.get(Options.LIBRARY_OUTPUT_CONTAINER_TYPE) != Container.ZIP)) { - typePlan = planBuilder.appendSubPlan(ExcludeTypeFromLibWithBinaryAdapter.class); - } else { + if (features.contains(GenerateLibraryFromIncrementalFolder.class)) { typePlan = planBuilder.appendSubPlan(JDefinedClassOrInterfaceAdapter.class); + } else { + typePlan = planBuilder.appendSubPlan(ExcludeTypeFromLibWithBinaryAdapter.class); } if (productions.contains(JayceInLibraryProduct.class)) { typePlan.append(JayceInLibraryWriter.class); @@ -1182,12 +1165,10 @@ public abstract class Jack { { SubPlanBuilder<JDefinedClassOrInterface> typePlan; // In incremental library mode, dex files must be copied into output library - if (features.contains(Incremental.class) - && ((!config.get(Options.GENERATE_JACK_LIBRARY).booleanValue()) - || config.get(Options.LIBRARY_OUTPUT_CONTAINER_TYPE) != Container.ZIP)) { - typePlan = planBuilder.appendSubPlan(ExcludeTypeFromLibWithBinaryAdapter.class); - } else { + if (features.contains(GenerateLibraryFromIncrementalFolder.class)) { typePlan = planBuilder.appendSubPlan(JDefinedClassOrInterfaceAdapter.class); + } else { + typePlan = planBuilder.appendSubPlan(ExcludeTypeFromLibWithBinaryAdapter.class); } if (productions.contains(DexInLibraryProduct.class)) { typePlan.append(DexInLibraryWriter.class); diff --git a/jack/src/com/android/jack/Options.java b/jack/src/com/android/jack/Options.java index a96ccf07..78005d2c 100644 --- a/jack/src/com/android/jack/Options.java +++ b/jack/src/com/android/jack/Options.java @@ -840,13 +840,13 @@ public class Options { if (incrementalFolder != null) { if (multiDexKind == MultiDexKind.LEGACY) { LoggerFactory.getLogger().log(Level.WARNING, - "Incremental mode is disable due to multi-dex legacy mode"); + "Incremental mode is disabled due to multi-dex legacy mode"); } else if (flags != null) { LoggerFactory.getLogger().log(Level.WARNING, - "Incremental mode is disable due to usage of shrink or obfuscation"); + "Incremental mode is disabled due to usage of shrinking or obfuscation"); } else if (jarjarRulesFile != null) { LoggerFactory.getLogger().log(Level.WARNING, - "Incremental mode is disable due to usage of jarjar"); + "Incremental mode is disabled due to usage of jarjar"); } else { configBuilder.set(Options.INCREMENTAL_MODE, true); configBuilder.setString(Options.INPUT_FILTER, "incremental"); @@ -1042,7 +1042,6 @@ public class Options { this.standardOutput = standardOutput; } - //STOPSHIP: Hack to handle working directory with proguard flags file public List<File> getProguardFlagsFile() { List<File> proguardFlagsFileFromWorkingDir = new ArrayList<File>(proguardFlagsFiles.size()); for (File proguardFlagsFile : proguardFlagsFiles) { diff --git a/jack/src/com/android/jack/api/v01/impl/Api01ConfigImpl.java b/jack/src/com/android/jack/api/v01/impl/Api01ConfigImpl.java index ce57d80c..2ec3070d 100644 --- a/jack/src/com/android/jack/api/v01/impl/Api01ConfigImpl.java +++ b/jack/src/com/android/jack/api/v01/impl/Api01ConfigImpl.java @@ -65,7 +65,7 @@ public class Api01ConfigImpl implements Api01Config { @Override @Nonnull public Api01CompilationTask getTask() throws ConfigurationException { - RunnableHooks configHooks = new RunnableHooks(); //STOPSHIP: run configHooks + RunnableHooks configHooks = new RunnableHooks(); try { Jack.check(options, configHooks); } catch (com.android.sched.util.config.ConfigurationException e) { @@ -116,8 +116,7 @@ public class Api01ConfigImpl implements Api01Config { if (e instanceof RuntimeException) { throw (RuntimeException) e; } else { - throw new RuntimeException(e); //STOPSHIP: we have Throwables here that we can't throw as - //is + throw new RuntimeException(e); } } finally { runSessionHooks.runHooks(); diff --git a/jack/src/com/android/jack/frontend/java/JAstBuilder.java b/jack/src/com/android/jack/frontend/java/JAstBuilder.java index 0d628196..e5f7a3e0 100644 --- a/jack/src/com/android/jack/frontend/java/JAstBuilder.java +++ b/jack/src/com/android/jack/frontend/java/JAstBuilder.java @@ -27,6 +27,7 @@ import com.android.jack.ir.ast.JSession; import com.android.jack.ir.impl.EcjSourceTypeLoader; import com.android.jack.ir.impl.JackIrBuilder; import com.android.jack.ir.impl.ReferenceMapper; +import com.android.jack.ir.impl.SourceCompilationException; import com.android.sched.util.location.FileLocation; import com.android.sched.util.log.Event; import com.android.sched.util.log.Tracer; @@ -132,6 +133,8 @@ class JAstBuilder extends JavaParser { List<JDefinedClassOrInterface> types; try { types = astBuilder.process(unit); + } catch (SourceCompilationException e) { + return; } finally { jackIrBuilderEvent.end(); } diff --git a/jack/src/com/android/jack/incremental/Incremental.java b/jack/src/com/android/jack/incremental/GenerateLibraryFromIncrementalFolder.java index cc791a2b..276c77a6 100644 --- a/jack/src/com/android/jack/incremental/Incremental.java +++ b/jack/src/com/android/jack/incremental/GenerateLibraryFromIncrementalFolder.java @@ -20,8 +20,8 @@ import com.android.sched.item.Description; import com.android.sched.item.Feature; /** - * A {@link Feature} that represents incremental support. + * A {@link Feature} specifying that a library is generated with incremental support. */ -@Description("Incremental support") -public class Incremental implements Feature { +@Description("Generate library with incremental support") +public class GenerateLibraryFromIncrementalFolder implements Feature { } diff --git a/jack/src/com/android/jack/incremental/IncrementalInputFilter.java b/jack/src/com/android/jack/incremental/IncrementalInputFilter.java index 5d5a3d24..f925926c 100644 --- a/jack/src/com/android/jack/incremental/IncrementalInputFilter.java +++ b/jack/src/com/android/jack/incremental/IncrementalInputFilter.java @@ -53,6 +53,7 @@ import com.android.sched.util.log.stats.Counter; import com.android.sched.util.log.stats.CounterImpl; import com.android.sched.util.log.stats.StatisticId; import com.android.sched.vfs.InputVFile; +import com.android.sched.vfs.ReadWriteZipFS; import com.android.sched.vfs.VFS; import com.android.sched.vfs.VPath; @@ -467,11 +468,19 @@ public class IncrementalInputFilter extends CommonFilter implements InputFilter @Override @Nonnull public OutputJackLibrary getOutputJackLibrary() { - if (incrementalInputLibrary == null) { - return getOutputJackLibraryFromVfs(); + if (ThreadConfig.get(Options.GENERATE_LIBRARY_FROM_INCREMENTAL_FOLDER).booleanValue()) { + VFS dirVFS = ThreadConfig.get(Options.LIBRARY_OUTPUT_DIR); + ReadWriteZipFS zipVFS = (ReadWriteZipFS) ThreadConfig.get(Options.LIBRARY_OUTPUT_ZIP); + zipVFS.setWorkVFS(dirVFS); + return JackLibraryFactory.getOutputLibrary(zipVFS, Jack.getEmitterId(), + Jack.getVersion().getVerboseVersion()); + } else { + if (incrementalInputLibrary == null) { + return getOutputJackLibraryFromVfs(); + } else { + return (JackLibraryFactory.getOutputLibrary(ThreadConfig.get(Options.LIBRARY_OUTPUT_DIR), + Jack.getEmitterId(), Jack.getVersion().getVerboseVersion())); + } } - - return (JackLibraryFactory.getOutputLibrary(ThreadConfig.get(Options.LIBRARY_OUTPUT_DIR), - Jack.getEmitterId(), Jack.getVersion().getVerboseVersion())); } } diff --git a/jack/src/com/android/jack/ir/impl/JackIrBuilder.java b/jack/src/com/android/jack/ir/impl/JackIrBuilder.java index e45298c0..83f942ed 100644 --- a/jack/src/com/android/jack/ir/impl/JackIrBuilder.java +++ b/jack/src/com/android/jack/ir/impl/JackIrBuilder.java @@ -841,20 +841,8 @@ public class JackIrBuilder { ReferenceBinding superClass = x.binding.declaringClass; boolean nestedSuper = isNested(superClass); - if (x.qualification != null - && (!x.qualification.resolvedType.isCompatibleWith(superClass.enclosingType()) - || !nestedSuper)) { - // JLS 8.8.7.1. Explicit Constructor Invocations - // Let C be the class being instantiated, and let S be the direct superclass of C. - // Let O be the innermost lexically enclosing class of S - // If invocation is qualified, it is a compile-time error if the type of qualified - // expression is not O or a subclass of O - scope.problemReporter().unnecessaryEnclosingInstanceSpecification( - x.qualification, - superClass); - } if (nestedSuper) { - processSuperCallThisArgs(superClass, call, qualifier, x.qualification); + processSuperCallThisArgs(superClass, call, qualifier, x); } call.addArgs(callArgs); if (nestedSuper) { @@ -1291,7 +1279,7 @@ public class JackIrBuilder { ReferenceBinding targetType = scope.enclosingSourceType().enclosingTypeAt( (x.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); - receiver = makeThisReference(info, targetType, true, scope); + receiver = makeThisReference(info, targetType, true, scope, x); } } @@ -1488,7 +1476,7 @@ public class JackIrBuilder { try { SourceInfo info = makeSourceInfo(x); ReferenceBinding targetType = (ReferenceBinding) x.qualification.resolvedType; - push(makeThisReference(info, targetType, true, scope)); + push(makeThisReference(info, targetType, true, scope, x)); } catch (JTypeLookupException e) { throw translateException(x, e); } catch (RuntimeException e) { @@ -1861,6 +1849,22 @@ public class JackIrBuilder { @Override public boolean visit(ExplicitConstructorCall explicitConstructor, BlockScope scope) { + ReferenceBinding allocated = explicitConstructor.binding.declaringClass; + if (explicitConstructor.isSuperAccess() && explicitConstructor.qualification != null + && !explicitConstructor.qualification.resolvedType.isCompatibleWith( + allocated.enclosingType())) { + // JLS 8.8.7.1. Explicit Constructor Invocations + // Let C be the class being instantiated, and let S be the direct superclass of C. + // Let O be the innermost lexically enclosing class of S + // If invocation is qualified, it is a compile-time error if the type of qualified + // expression is not O or a subclass of O + scope.problemReporter().unnecessaryEnclosingInstanceSpecification( + explicitConstructor.qualification, + allocated); + throw new FrontendCompilationError(); + } + // STOPSHIP Check other cases and report error to the user + scope.methodScope().isConstructorCall = true; return true; } @@ -2026,6 +2030,13 @@ public class JackIrBuilder { return visit(typeDecl); } + @Override + public boolean visit(QualifiedAllocationExpression allocation, BlockScope scope) { + ReferenceBinding allocated = allocation.binding.declaringClass; + // STOPSHIP Check error cases and report error to the user + return super.visit(allocation, scope); + } + protected void endVisit(TypeDeclaration x) { assert !JackIrBuilder.hasError(x); try { @@ -2476,11 +2487,38 @@ public class JackIrBuilder { return new JThisRef(info, jThis); } + @Nonnull + private Object[] getEmulationPath(@Nonnull BlockScope scope, + @Nonnull ReferenceBinding targetType, + boolean exactMatch, + boolean denyEnclosingArgInConstructorCall, + ASTNode node) { + Object[] path = scope.getEmulationPath(targetType, exactMatch, + denyEnclosingArgInConstructorCall); + // STOPSHIP Check other cases and report error to the user + if (path == null) { + throw new FrontendCompilationError(); + } + return path; + } + + @Nonnull + private VariableBinding[] getEmulationPath(@Nonnull BlockScope scope, + @Nonnull LocalVariableBinding localVariable, + ASTNode node) { + VariableBinding[] path = scope.getEmulationPath(localVariable); + // STOPSHIP Report error to the user + if (path == null) { + throw new FrontendCompilationError(); + } + return path; + } + private JExpression makeThisReference(SourceInfo info, ReferenceBinding targetType, - boolean exactMatch, BlockScope scope) throws JTypeLookupException { + boolean exactMatch, BlockScope scope, ASTNode node) throws JTypeLookupException { targetType = (ReferenceBinding) targetType.erasure(); - Object[] path = scope.getEmulationPath(targetType, exactMatch, false); - assert path != null : "No emulation path."; + Object[] path = getEmulationPath(scope, targetType, exactMatch, + /* denyEnclosingArgInConstructorCall = */ false, node); if (path == BlockScope.EmulationPathToImplicitThis) { return makeThisRef(info); } @@ -2627,15 +2665,16 @@ public class JackIrBuilder { } private void processSuperCallThisArgs(ReferenceBinding superClass, JMethodCall call, - JExpression qualifier, Expression qualification) throws JTypeLookupException { + JExpression qualifier, ExplicitConstructorCall expression) throws JTypeLookupException { if (superClass.syntheticEnclosingInstanceTypes() != null) { + Expression qualification = expression.qualification; for (ReferenceBinding targetType : superClass.syntheticEnclosingInstanceTypes()) { if (qualification != null && superClass.enclosingType() == targetType) { assert qualification.resolvedType.erasure().isCompatibleWith(targetType); call.addArg(qualifier); } else { call.addArg(makeThisReference(call.getSourceInfo(), targetType, false, - curMethod.scope)); + curMethod.scope, expression)); } } } @@ -2760,15 +2799,6 @@ public class JackIrBuilder { targetBinding.isAnonymousType() ? (ReferenceBinding) targetBinding.superclass() .erasure() : targetBinding; - if (qualifier != null - && (!isNested || checkedTargetType.isStatic())) { - // If the class is not an inner class or is declared in a static context, - // a compile-time error occurs - curClass.scope.problemReporter().unnecessaryEnclosingInstanceSpecification(qualifier, - checkedTargetType); - return; - } - if (isNested) { // Synthetic this args for inner classes if (targetBinding.syntheticEnclosingInstanceTypes() != null) { @@ -2797,16 +2827,13 @@ public class JackIrBuilder { JMultiExpression multiExpr = new JMultiExpression(info, exprs); call.addArg(multiExpr); } else { - JExpression thisRef = makeThisReference(info, argType, false, scope); + JExpression thisRef = makeThisReference(info, argType, false, scope, x); call.addArg(thisRef); - Object[] emulationPath = scope.getEmulationPath( + Object[] emulationPath = getEmulationPath(scope, argType, false /* onlyExactMatch */, - true /* denyEnclosingArgInConstructorCall */); - if (emulationPath == BlockScope.NoEnclosingInstanceInConstructorCall) { - scope.problemReporter().noSuchEnclosingInstance(checkedTargetType, - x.concreteStatement(), true); - } + true /* denyEnclosingArgInConstructorCall */, + x); } } } @@ -2900,16 +2927,7 @@ public class JackIrBuilder { if (binding instanceof LocalVariableBinding) { LocalVariableBinding b = (LocalVariableBinding) binding; if ((x.bits & ASTNode.DepthMASK) != 0) { - VariableBinding[] path = scope.getEmulationPath(b); - if (path == null) { - /* - * Don't like this, but in rare cases (e.g. the variable is only - * ever used as an unnecessary qualifier) JDT provides no emulation - * to the desired variable. - */ - // throw new InternalCompilerException("No emulation path."); - return null; - } + VariableBinding[] path = getEmulationPath(scope, b, x); assert path.length == 1; if (curMethod.scope.isInsideInitializer() && path[0] instanceof SyntheticArgumentBinding) { @@ -2948,7 +2966,7 @@ public class JackIrBuilder { ReferenceBinding targetType = scope.enclosingSourceType().enclosingTypeAt( (x.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); - thisRef = makeThisReference(info, targetType, true /* exactMatch */, scope); + thisRef = makeThisReference(info, targetType, true /* exactMatch */, scope, x); } else { thisRef = makeThisRef(info); } @@ -3266,6 +3284,15 @@ public class JackIrBuilder { } } + private static class FrontendCompilationError extends Error { + + private static final long serialVersionUID = 1L; + + public FrontendCompilationError() { + super(); + } + } + private static final String ARRAY_LENGTH_FIELD = "length"; /** @@ -3395,7 +3422,8 @@ public class JackIrBuilder { return typeMap; } - public List<JDefinedClassOrInterface> process(CompilationUnitDeclaration cud) { + public List<JDefinedClassOrInterface> process(CompilationUnitDeclaration cud) + throws SourceCompilationException { if (cud.types == null) { return Collections.emptyList(); } @@ -3425,9 +3453,18 @@ public class JackIrBuilder { // Create fields and empty methods. createMembers(typeDecl); } + boolean hasErrors = false; for (TypeDeclaration typeDecl : cud.types) { - // Build the code. - typeDecl.traverse(astVisitor, cud.scope); + try { + // Build the code. + typeDecl.traverse(astVisitor, cud.scope); + } catch (FrontendCompilationError e) { + hasErrors = true; + } + } + + if (hasErrors) { + throw new SourceCompilationException(); } List<JDefinedClassOrInterface> result = newTypes; diff --git a/jack/src/com/android/jack/ir/impl/SourceCompilationException.java b/jack/src/com/android/jack/ir/impl/SourceCompilationException.java new file mode 100644 index 00000000..0c8ae1a8 --- /dev/null +++ b/jack/src/com/android/jack/ir/impl/SourceCompilationException.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed 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 com.android.jack.ir.impl; + +/** + * Thrown when an error in a method body is detected. This exception is thrown after reporting to + * the user. + */ +public class SourceCompilationException extends Exception { + + private static final long serialVersionUID = 1L; + +} diff --git a/jack/src/com/android/jack/reporting/CommonReporter.java b/jack/src/com/android/jack/reporting/CommonReporter.java index b2bdd24d..549837f1 100644 --- a/jack/src/com/android/jack/reporting/CommonReporter.java +++ b/jack/src/com/android/jack/reporting/CommonReporter.java @@ -20,6 +20,7 @@ import com.android.jack.Jack; import com.android.jack.Options; import com.android.jack.Options.VerbosityLevel; import com.android.jack.frontend.java.EcjProblem; +import com.android.jack.ir.sourceinfo.SourceInfo; import com.android.jack.reporting.Reportable.ProblemLevel; import com.android.sched.util.config.ThreadConfig; import com.android.sched.util.file.OutputStreamFile; @@ -32,7 +33,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.LinkedBlockingDeque; -import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -92,14 +92,18 @@ abstract class CommonReporter implements Reporter { if (reportable instanceof EcjProblem) { assert severity == Severity.NON_FATAL; CategorizedProblem problem = ((EcjProblem) reportable).getProblem(); + SourceInfo sourceInfo; + + if (problem.getOriginatingFileName() == null) { + sourceInfo = SourceInfo.UNKNOWN; + } else { + sourceInfo = Jack.getSession().getSourceInfoFactory().create(problem.getSourceLineNumber(), + SourceInfo.UNKNOWN_LINE_NUMBER, String.valueOf(problem.getOriginatingFileName())); + } + printFilteredProblem(reportable.getDefaultProblemLevel(), - reportable.getMessage(), - problem.getOriginatingFileName() != null ? - String.valueOf(problem.getOriginatingFileName()) : null, - problem.getSourceLineNumber(), - -1 /* endLine */, - problem.getSourceEnd(), - -1 /* endColumn */); + reportable.getMessage(), sourceInfo); + } else { // default behavior if (severity == Severity.FATAL) { @@ -111,16 +115,11 @@ abstract class CommonReporter implements Reporter { } private void printFilteredProblem(@Nonnull ProblemLevel problemLevel, @Nonnull String message) { - printFilteredProblem(problemLevel, message, null /* fileName */, -1, -1, -1, -1); + printFilteredProblem(problemLevel, message, SourceInfo.UNKNOWN); } protected abstract void printFilteredProblem(@Nonnull ProblemLevel problemLevel, - @Nonnull String message, - @CheckForNull String fileName, - int startLine, - int endLine, - int startColumn, - int endColumn); + @Nonnull String message, @Nonnull SourceInfo sourceInfo); class RunReporter implements Runnable { diff --git a/jack/src/com/android/jack/reporting/DefaultReporter.java b/jack/src/com/android/jack/reporting/DefaultReporter.java index 83718787..c68f7cd7 100644 --- a/jack/src/com/android/jack/reporting/DefaultReporter.java +++ b/jack/src/com/android/jack/reporting/DefaultReporter.java @@ -16,12 +16,12 @@ package com.android.jack.reporting; +import com.android.jack.ir.sourceinfo.SourceInfo; import com.android.jack.reporting.Reportable.ProblemLevel; import com.android.sched.util.codec.ImplementationName; import java.io.PrintStream; -import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -32,22 +32,18 @@ import javax.annotation.Nonnull; public class DefaultReporter extends CommonReporter { @Override - protected void printFilteredProblem(@Nonnull ProblemLevel problemLevel, - @Nonnull String message, - @CheckForNull String fileName, - int startLine, - int endLine, - int startColumn, - int endColumn) { + protected void printFilteredProblem(@Nonnull ProblemLevel problemLevel, @Nonnull String message, + @Nonnull SourceInfo sourceInfo) { StringBuffer messageBuffer = new StringBuffer(problemLevel.toString()); - if (fileName != null) { + if (sourceInfo != SourceInfo.UNKNOWN) { messageBuffer.append(": "); - messageBuffer.append(fileName); - if (startLine >= 0) { + messageBuffer.append(sourceInfo.getFileName()); + if (sourceInfo.getStartLine() >= 0) { messageBuffer.append(":"); - messageBuffer.append(startLine); + messageBuffer.append(sourceInfo.getStartLine()); } } + messageBuffer.append(": "); messageBuffer.append(message); diff --git a/jack/src/com/android/jack/reporting/SdkReporter.java b/jack/src/com/android/jack/reporting/SdkReporter.java index c72eab3e..f7df277a 100644 --- a/jack/src/com/android/jack/reporting/SdkReporter.java +++ b/jack/src/com/android/jack/reporting/SdkReporter.java @@ -16,12 +16,13 @@ package com.android.jack.reporting; +import com.android.jack.ir.sourceinfo.SourceInfo; import com.android.jack.reporting.Reportable.ProblemLevel; import com.android.sched.util.codec.ImplementationName; +import java.io.File; import java.io.PrintStream; -import javax.annotation.CheckForNull; import javax.annotation.Nonnull; @@ -31,39 +32,42 @@ import javax.annotation.Nonnull; @ImplementationName(iface = Reporter.class, name = "sdk") public class SdkReporter extends CommonReporter { - private static final char MESSAGE_SEPARATOR = ':'; - @Override protected void printFilteredProblem(@Nonnull ProblemLevel problemLevel, - @Nonnull String message, - @CheckForNull String fileName, - int startLine, - int endLine, - int startColumn, - int endColumn) { - StringBuffer messageBuffer = new StringBuffer(problemLevel.toString()); - messageBuffer.append(MESSAGE_SEPARATOR); - if (fileName != null) { - messageBuffer.append(fileName); - } - messageBuffer.append(MESSAGE_SEPARATOR); - if (startLine >= 0) { - messageBuffer.append(startLine); - } - messageBuffer.append(MESSAGE_SEPARATOR); - if (endLine >= 0) { - messageBuffer.append(endLine); - } - messageBuffer.append(MESSAGE_SEPARATOR); - if (startColumn >= 0) { - messageBuffer.append(startColumn); - } - messageBuffer.append(MESSAGE_SEPARATOR); - if (endColumn >= 0) { - messageBuffer.append(endColumn); + @Nonnull String message, @Nonnull SourceInfo sourceInfo) { + StringBuffer messageBuffer = new StringBuffer("MESSAGE:{"); + + messageBuffer.append("\"kind\":\"").append(convertLevelName(problemLevel)).append("\","); + messageBuffer.append("\"text\":\"").append(message).append("\","); + messageBuffer.append("\"sources\":[{"); + + if (sourceInfo != SourceInfo.UNKNOWN) { + String fileName = new File(sourceInfo.getFileName()).getAbsolutePath(); + + messageBuffer.append("\"file\":\"").append(fileName).append("\","); + messageBuffer.append("\"position\":{"); + + // Convert unknown values to match sdk expectations + int startLine = sourceInfo.getStartLine() == SourceInfo.UNKNOWN_LINE_NUMBER ? -1 + : sourceInfo.getStartLine(); + int startColumn = sourceInfo.getStartColumn() == SourceInfo.UNKNOWN_COLUMN_NUMBER ? -1 + : sourceInfo.getStartColumn(); + int endLine = + sourceInfo.getEndLine() == SourceInfo.UNKNOWN_LINE_NUMBER ? -1 : sourceInfo.getEndLine(); + int endColumn = sourceInfo.getEndColumn() == SourceInfo.UNKNOWN_COLUMN_NUMBER ? -1 + : sourceInfo.getEndColumn(); + + messageBuffer.append("\"startLine\":").append(startLine).append(','); + messageBuffer.append("\"startColumn\":").append(startColumn).append(','); + messageBuffer.append("\"startOffset\":-1,"); + messageBuffer.append("\"endLine\":").append(endLine).append(','); + messageBuffer.append("\"endColumn\":").append(endColumn).append(','); + messageBuffer.append("\"endOffset\":-1"); + + messageBuffer.append('}'); } - messageBuffer.append(MESSAGE_SEPARATOR); - messageBuffer.append(message); + + messageBuffer.append("}]}"); PrintStream printer = streamByLevel.get(problemLevel); if (printer == null) { @@ -72,4 +76,18 @@ public class SdkReporter extends CommonReporter { printer.println(messageBuffer.toString()); } + + private String convertLevelName(@Nonnull ProblemLevel problemLevel) { + switch (problemLevel) { + case ERROR: + return "ERROR"; + case WARNING: + return "WARNING"; + case INFO: + return "INFO"; + default: + throw new AssertionError("Unkown problem level: '" + problemLevel.name() + "'"); + } + } + } diff --git a/jack/src/com/android/jack/tools/merger/ConstantManager.java b/jack/src/com/android/jack/tools/merger/ConstantManager.java index e56be8c0..ef1fc3eb 100644 --- a/jack/src/com/android/jack/tools/merger/ConstantManager.java +++ b/jack/src/com/android/jack/tools/merger/ConstantManager.java @@ -15,6 +15,7 @@ */ package com.android.jack.tools.merger; +import com.android.jack.Jack; import com.android.jack.dx.dex.DexFormat; import com.android.jack.dx.dex.file.DexFile; import com.android.jack.dx.io.DexBuffer; @@ -30,6 +31,7 @@ import com.android.jack.dx.rop.cst.CstType; import com.android.jack.dx.rop.type.Type; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -58,7 +60,24 @@ public class ConstantManager extends MergerTools { private final Map<String, CstString> protoStr2CstString = new HashMap<String, CstString>(); @Nonnull - private final List<CstIndexMap> cstIndexMaps = new ArrayList<CstIndexMap>(); + public Collection<CstString> getCstStrings() { + return Jack.getUnmodifiableCollections().getUnmodifiableCollection(string2CstStrings.values()); + } + + @Nonnull + public Collection<CstFieldRef> getCstFieldRefs() { + return Jack.getUnmodifiableCollections().getUnmodifiableCollection(cstFieldRefs); + } + + @Nonnull + public Collection<CstMethodRef> getCstMethodRefs() { + return Jack.getUnmodifiableCollections().getUnmodifiableCollection(cstMethodRefs); + } + + @Nonnull + public Collection<CstType> getCstTypes() { + return Jack.getUnmodifiableCollections().getUnmodifiableCollection(cstTypes); + } @Nonnull public CstIndexMap addDexFile(@Nonnull DexBuffer dexBuffer) throws MergingOverflowException { @@ -164,8 +183,6 @@ public class ConstantManager extends MergerTools { throw new TypeIdOverflowException(); } - cstIndexMaps.add(cstIndexMap); - return cstIndexMap; } @@ -178,11 +195,6 @@ public class ConstantManager extends MergerTools { cstTypes.removeAll(cstTypesToRemove); } - @Nonnull - public List<CstIndexMap> getCstIndexMaps() { - return cstIndexMaps; - } - public boolean validate(@Nonnull DexFile dexFile) { return ((dexFile.getStringIds().items().size() == string2CstStrings.size()) && (dexFile.getFieldIds().items().size() == cstFieldRefs.size()) diff --git a/jack/src/com/android/jack/tools/merger/JackMerger.java b/jack/src/com/android/jack/tools/merger/JackMerger.java index 01108b3a..8462763f 100644 --- a/jack/src/com/android/jack/tools/merger/JackMerger.java +++ b/jack/src/com/android/jack/tools/merger/JackMerger.java @@ -144,7 +144,8 @@ public class JackMerger extends MergerTools { } public void finish(@Nonnull OutputStream out) throws IOException { - dexResult.prepare(cstManager.getCstIndexMaps()); + dexResult.prepare(cstManager.getCstStrings(), cstManager.getCstFieldRefs(), + cstManager.getCstMethodRefs(), cstManager.getCstTypes()); if (!cstManager.validate(dexResult)) { throw new AssertionError(); } diff --git a/sched/.settings/org.eclipse.jdt.core.prefs b/sched/.settings/org.eclipse.jdt.core.prefs index 34af0151..58cab3f5 100644 --- a/sched/.settings/org.eclipse.jdt.core.prefs +++ b/sched/.settings/org.eclipse.jdt.core.prefs @@ -98,9 +98,6 @@ org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.processAnnotations=enabled org.eclipse.jdt.core.compiler.source=1.6 -org.eclipse.jdt.core.compiler.taskCaseSensitive=enabled -org.eclipse.jdt.core.compiler.taskPriorities=NORMAL,LOW,HIGH,HIGH,LOW -org.eclipse.jdt.core.compiler.taskTags=TODO(jplesot)\:,TODO,FIXME,XXX,FINDBUGS org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field=1585 org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field.count_dependent=1585|-1|1585 diff --git a/sched/src/com/android/sched/vfs/ReadWriteZipFS.java b/sched/src/com/android/sched/vfs/ReadWriteZipFS.java index 7664e4c8..956c908e 100644 --- a/sched/src/com/android/sched/vfs/ReadWriteZipFS.java +++ b/sched/src/com/android/sched/vfs/ReadWriteZipFS.java @@ -203,4 +203,8 @@ public class ReadWriteZipFS extends BaseVFS<BaseVDir, BaseVFile> implements VFS Location getVDirLocation(@Nonnull BaseVDir parent, @Nonnull VPath path) { return vfs.getVDirLocation(parent, path); } + + public void setWorkVFS(@Nonnull VFS workVFS) { + vfs.setWorkVFS(workVFS); + } } diff --git a/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java b/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java index 7ee1c220..322fa48c 100644 --- a/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java +++ b/sched/src/com/android/sched/vfs/VFSToVFSWrapper.java @@ -42,7 +42,7 @@ import javax.annotation.Nonnull; public class VFSToVFSWrapper extends BaseVFS<BaseVDir, BaseVFile> implements VFS { @Nonnull - private final BaseVFS<BaseVDir, BaseVFile> workVFS; + private BaseVFS<BaseVDir, BaseVFile> workVFS; @Nonnull private final BaseVFS<BaseVDir, BaseVFile> finalVFS; @Nonnull @@ -254,4 +254,8 @@ public class VFSToVFSWrapper extends BaseVFS<BaseVDir, BaseVFile> implements VFS return workVFS.getVDirLocation(parent, path); } + @SuppressWarnings("unchecked") + public void setWorkVFS(@Nonnull VFS temporaryVFS) { + workVFS = (BaseVFS<BaseVDir, BaseVFile>) temporaryVFS; + } } diff --git a/sched/tests/com/android/sched/vfs/VFSTest.java b/sched/tests/com/android/sched/vfs/VFSTest.java index 23953fcd..40d97205 100644 --- a/sched/tests/com/android/sched/vfs/VFSTest.java +++ b/sched/tests/com/android/sched/vfs/VFSTest.java @@ -629,7 +629,6 @@ public class VFSTest { new OutputZipFile(path, null, Existence.MAY_EXIST, ChangePermission.NOCHANGE))); testOutputVFS(zipVFS); testDelete(zipVFS); - //STOPSHIP: should be a ZipLocation but is currently a FileOrDirLocation // checkZipLocations(zipVFS); testInputVFS(zipVFS); zipVFS.close(); |