Merge
authorlana
Mon, 04 Aug 2014 15:33:22 -0700
changeset 25849 5cc16d71dc7a
parent 25843 93411a4ee2bc (current diff)
parent 25848 3bc09f4676a9 (diff)
child 25850 c3d78c30da05
Merge
--- a/langtools/make/build.properties	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/make/build.properties	Mon Aug 04 15:33:22 2014 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -168,6 +168,8 @@
 sjavac.tests = \
         tools/sjavac
 
+crules.tests = ../make/test/crules
+
 #
 
 # The following files require the latest JDK to be available.
--- a/langtools/make/build.xml	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/make/build.xml	Mon Aug 04 15:33:22 2014 -0700
@@ -760,7 +760,8 @@
     **** crules targets.
     -->
 
-    <target name="build-crules" depends="-def-compilecrules,-def-build-jar-with-services">
+    <target name="build-crules"
+            depends="-def-compilecrules,-def-build-jar-with-services,build-bootstrap-javac,-create-import-jdk-stubs">
         <compilecrules/>
         <build-jar-with-services
                     name="crules"
@@ -770,13 +771,19 @@
                     jarmainclass=""
                     jarclasspath="crules.jar"
                     service.type="com.sun.source.util.Plugin"
-                    service.provider="crules.MutableFieldsAnalyzer"/>
+                    service.provider="crules.CodingRulesAnalyzerPlugin"/>
         <build-tool name="crules"/>
     </target>
 
+    <target name="jtreg-crules" depends="build-javac,build-crules,-def-jtreg">
+        <jtreg-tool name="crules"
+                    tests="${crules.tests}"
+                    extra.jvmargs="-Xbootclasspath/a:${build.toolclasses.dir}/crules.jar" />
+    </target>
+
     <target name="check-coding-rules" depends="build-bootstrap-javac,-create-import-jdk-stubs,build-crules">
         <build-classes includes="${javac.includes}"
-            plugin.options="-J-Xbootclasspath/a:${build.toolclasses.dir}/crules.jar -Xplugin:mutable_fields_analyzer" />
+            plugin.options="-J-Xbootclasspath/a:${build.toolclasses.dir}/crules.jar -Xplugin:coding_rules" />
     </target>
 
     <!--
@@ -1150,6 +1157,7 @@
             <attribute name="options" default="${other.jtreg.options}"/>
             <attribute name="keywords" default="-keywords:!ignore"/>
             <attribute name="jpda.jvmargs" default=""/>
+            <attribute name="extra.jvmargs" default=""/>
             <sequential>
                 <property name="coverage.options" value=""/>              <!-- default -->
                 <property name="coverage.classpath" value=""/>            <!-- default -->
@@ -1163,7 +1171,7 @@
                     samevm="@{samevm}" verbose="@{verbose}"
                     failonerror="false" resultproperty="jtreg.@{name}.result"
                     javacoptions="-g"
-                    vmoptions="${coverage.options} -Xbootclasspath/p:${coverage.classpath}${path.separator}${build.classes.dir} @{jpda.jvmargs}">
+                    vmoptions="${coverage.options} -Xbootclasspath/p:${coverage.classpath}${path.separator}${build.classes.dir} @{jpda.jvmargs} @{extra.jvmargs}">
                     <arg line="@{keywords}"/>
                     <arg line="@{options}"/>
                     <arg line="@{tests}"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/test/crules/CodingRulesAnalyzerPlugin/Test.java	Mon Aug 04 15:33:22 2014 -0700
@@ -0,0 +1,11 @@
+/**@test /nodynamiccopyright/
+ * @compile/fail/ref=Test.out -Xplugin:coding_rules -XDrawDiagnostics Test.java
+ */
+
+import com.sun.tools.javac.util.Assert;
+
+public class Test {
+    public void check(String value) {
+        Assert.check(value.trim().length() > 0, "value=" + value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/test/crules/CodingRulesAnalyzerPlugin/Test.out	Mon Aug 04 15:33:22 2014 -0700
@@ -0,0 +1,2 @@
+Test.java:9:21: compiler.err.proc.messager: compiler.misc.crules.should.not.use.string.concatenation
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/test/crules/MutableFieldsAnalyzer/Test.java	Mon Aug 04 15:33:22 2014 -0700
@@ -0,0 +1,9 @@
+/**@test /nodynamiccopyright/
+ * @compile/fail/ref=Test.out -Xplugin:coding_rules -XDrawDiagnostics Test.java
+ */
+
+package com.sun.tools.javac;
+
+public class Test {
+    public static String mutable;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/test/crules/MutableFieldsAnalyzer/Test.out	Mon Aug 04 15:33:22 2014 -0700
@@ -0,0 +1,2 @@
+Test.java:8:26: compiler.err.proc.messager: compiler.misc.crules.err.var.must.be.final: public static String mutable
+1 error
--- a/langtools/make/tools/crules/AbstractCodingRulesAnalyzer.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/make/tools/crules/AbstractCodingRulesAnalyzer.java	Mon Aug 04 15:33:22 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,64 +27,43 @@
 import java.util.Locale;
 import java.util.ResourceBundle;
 
-import javax.lang.model.element.TypeElement;
-import javax.tools.JavaFileObject;
-
-import com.sun.source.tree.Tree;
 import com.sun.source.util.JavacTask;
-import com.sun.source.util.Plugin;
-import com.sun.source.util.TaskEvent;
-import com.sun.source.util.TaskListener;
-import com.sun.source.util.Trees;
 import com.sun.tools.javac.api.BasicJavacTask;
+import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.tree.TreeScanner;
 import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
 import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Options;
+import com.sun.tools.javac.util.RawDiagnosticFormatter;
 
 import static com.sun.source.util.TaskEvent.Kind;
 
-public abstract class AbstractCodingRulesAnalyzer implements Plugin {
+public abstract class AbstractCodingRulesAnalyzer {
 
-    protected Log log;
-    protected Trees trees;
+    private   final Log log;
+    private   final boolean rawDiagnostics;
+    private   final JCDiagnostic.Factory diags;
+    private   final Options options;
+    protected final Messages messages;
+    protected final Symtab syms;
     protected TreeScanner treeVisitor;
     protected Kind eventKind;
-    protected Messages messages;
 
-    public void init(JavacTask task, String... args) {
+    public AbstractCodingRulesAnalyzer(JavacTask task) {
         BasicJavacTask impl = (BasicJavacTask)task;
         Context context = impl.getContext();
         log = Log.instance(context);
-        trees = Trees.instance(task);
+        options = Options.instance(context);
+        rawDiagnostics = options.isSet("rawDiagnostics");
+        diags = JCDiagnostic.Factory.instance(context);
         messages = new Messages();
-        task.addTaskListener(new PostAnalyzeTaskListener());
+        syms = Symtab.instance(context);
     }
 
-    public class PostAnalyzeTaskListener implements TaskListener {
-
-        @Override
-        public void started(TaskEvent taskEvent) {}
-
-        @Override
-        public void finished(TaskEvent taskEvent) {
-            if (taskEvent.getKind().equals(eventKind)) {
-                TypeElement typeElem = taskEvent.getTypeElement();
-                Tree tree = trees.getTree(typeElem);
-                if (tree != null) {
-                    JavaFileObject prevSource = log.currentSourceFile();
-                    try {
-                        log.useSource(taskEvent.getCompilationUnit().getSourceFile());
-                        treeVisitor.scan((JCTree)tree);
-                    } finally {
-                        log.useSource(prevSource);
-                    }
-                }
-            }
-        }
-    }
-
-    class Messages {
+    protected class Messages {
         ResourceBundle bundle;
 
         Messages() {
@@ -93,7 +72,14 @@
         }
 
         public void error(JCTree tree, String code, Object... args) {
-            String msg = (code == null) ? (String) args[0] : localize(code, args);
+            String msg;
+            if (rawDiagnostics) {
+                RawDiagnosticFormatter f = new RawDiagnosticFormatter(options);
+                msg = f.formatMessage(diags.create(DiagnosticType.FRAGMENT, log.currentSource(),
+                                                   tree.pos(), code, args), null);
+            } else {
+                msg = (code == null) ? (String) args[0] : localize(code, args);
+            }
             log.error(tree, "proc.messager", msg.toString());
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/tools/crules/AssertCheckAnalyzer.java	Mon Aug 04 15:33:22 2014 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package crules;
+
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TaskEvent.Kind;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
+import com.sun.tools.javac.tree.JCTree.Tag;
+import com.sun.tools.javac.tree.TreeInfo;
+import com.sun.tools.javac.tree.TreeScanner;
+import com.sun.tools.javac.util.Assert;
+
+public class AssertCheckAnalyzer extends AbstractCodingRulesAnalyzer {
+
+    public AssertCheckAnalyzer(JavacTask task) {
+        super(task);
+        treeVisitor = new AssertCheckVisitor();
+        eventKind = Kind.ANALYZE;
+    }
+
+    class AssertCheckVisitor extends TreeScanner {
+
+        @Override
+        public void visitApply(JCMethodInvocation tree) {
+            Symbol method = TreeInfo.symbolFor(tree);
+            if (method != null &&
+                method.owner.getQualifiedName().contentEquals(Assert.class.getName()) &&
+                !method.name.contentEquals("error")) {
+                JCExpression lastParam = tree.args.last();
+                if (lastParam != null &&
+                    lastParam.type.tsym == syms.stringType.tsym &&
+                    lastParam.hasTag(Tag.PLUS)) {
+                    messages.error(tree, "crules.should.not.use.string.concatenation");
+                }
+            }
+
+            super.visitApply(tree);
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/tools/crules/CodingRulesAnalyzerPlugin.java	Mon Aug 04 15:33:22 2014 -0700
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package crules;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.lang.model.element.TypeElement;
+import javax.tools.JavaFileObject;
+
+import com.sun.source.tree.Tree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.Plugin;
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskEvent.Kind;
+import com.sun.source.util.TaskListener;
+import com.sun.source.util.Trees;
+import com.sun.tools.javac.api.BasicJavacTask;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+
+public class CodingRulesAnalyzerPlugin implements Plugin {
+
+    protected Log log;
+    protected Trees trees;
+
+    public void init(JavacTask task, String... args) {
+        BasicJavacTask impl = (BasicJavacTask)task;
+        Context context = impl.getContext();
+        log = Log.instance(context);
+        trees = Trees.instance(task);
+        task.addTaskListener(new PostAnalyzeTaskListener(
+                new MutableFieldsAnalyzer(task),
+                new AssertCheckAnalyzer(task)
+        ));
+    }
+
+    public class PostAnalyzeTaskListener implements TaskListener {
+        private final Map<Kind, List<AbstractCodingRulesAnalyzer>> analyzers = new HashMap<>();
+
+        public PostAnalyzeTaskListener(AbstractCodingRulesAnalyzer... analyzers) {
+            for (AbstractCodingRulesAnalyzer analyzer : analyzers) {
+                List<AbstractCodingRulesAnalyzer> currentAnalyzers = this.analyzers.get(analyzer.eventKind);
+
+                if (currentAnalyzers == null) {
+                    this.analyzers.put(analyzer.eventKind, currentAnalyzers = new ArrayList<>());
+                }
+
+                currentAnalyzers.add(analyzer);
+            }
+        }
+
+        @Override
+        public void started(TaskEvent taskEvent) {}
+
+        @Override
+        public void finished(TaskEvent taskEvent) {
+            List<AbstractCodingRulesAnalyzer> currentAnalyzers = this.analyzers.get(taskEvent.getKind());
+
+            if (currentAnalyzers != null) {
+                TypeElement typeElem = taskEvent.getTypeElement();
+                Tree tree = trees.getTree(typeElem);
+                if (tree != null) {
+                    JavaFileObject prevSource = log.currentSourceFile();
+                    try {
+                        log.useSource(taskEvent.getCompilationUnit().getSourceFile());
+                        for (AbstractCodingRulesAnalyzer analyzer : currentAnalyzers) {
+                            analyzer.treeVisitor.scan((JCTree)tree);
+                        }
+                    } finally {
+                        log.useSource(prevSource);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "coding_rules";
+    }
+
+}
--- a/langtools/make/tools/crules/MutableFieldsAnalyzer.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/make/tools/crules/MutableFieldsAnalyzer.java	Mon Aug 04 15:33:22 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,24 +28,25 @@
 import java.util.List;
 import java.util.Map;
 
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TaskEvent.Kind;
 import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
 import com.sun.tools.javac.tree.TreeScanner;
 
-import static com.sun.source.util.TaskEvent.Kind;
-import static com.sun.tools.javac.code.Flags.*;
-import static com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+import static com.sun.tools.javac.code.Flags.ENUM;
+import static com.sun.tools.javac.code.Flags.FINAL;
+import static com.sun.tools.javac.code.Flags.STATIC;
+import static com.sun.tools.javac.code.Flags.SYNTHETIC;
 
 public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer {
 
-    public MutableFieldsAnalyzer() {
+    public MutableFieldsAnalyzer(JavacTask task) {
+        super(task);
         treeVisitor = new MutableFieldsVisitor();
         eventKind = Kind.ANALYZE;
     }
 
-    public String getName() {
-        return "mutable_fields_analyzer";
-    }
-
     private boolean ignoreField(String className, String field) {
         List<String> currentFieldsToIgnore =
                 classFieldsToIgnoreMap.get(className);
@@ -89,7 +90,7 @@
     private static final String packageToCheck = "com.sun.tools.javac";
 
     private static final Map<String, List<String>> classFieldsToIgnoreMap =
-                new HashMap<String, List<String>>();
+                new HashMap<>();
 
     static {
         classFieldsToIgnoreMap.
--- a/langtools/make/tools/crules/resources/crules.properties	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/make/tools/crules/resources/crules.properties	Mon Aug 04 15:33:22 2014 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -26,3 +26,5 @@
 # 0: symbol
 crules.err.var.must.be.final=\
     Static variable {0} must be final
+crules.should.not.use.string.concatenation=\
+    Should not use string concatenation.
--- a/langtools/src/share/classes/com/sun/tools/javac/code/ClassFinder.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/ClassFinder.java	Mon Aug 04 15:33:22 2014 -0700
@@ -103,6 +103,10 @@
      */
     private final JavaFileManager fileManager;
 
+    /** Dependency tracker
+     */
+    private final Dependencies dependencies;
+
     /** Factory for diagnostics
      */
     JCDiagnostic.Factory diagFactory;
@@ -150,6 +154,7 @@
         names = Names.instance(context);
         syms = Symtab.instance(context);
         fileManager = context.get(JavaFileManager.class);
+        dependencies = Dependencies.instance(context);
         if (fileManager == null)
             throw new AssertionError("FileManager initialization error");
         diagFactory = JCDiagnostic.Factory.instance(context);
@@ -179,18 +184,23 @@
      */
     private void complete(Symbol sym) throws CompletionFailure {
         if (sym.kind == TYP) {
-            ClassSymbol c = (ClassSymbol)sym;
-            c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
-            annotate.enterStart();
             try {
-                completeOwners(c.owner);
-                completeEnclosing(c);
+                ClassSymbol c = (ClassSymbol) sym;
+                dependencies.push(c);
+                c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
+                annotate.enterStart();
+                try {
+                    completeOwners(c.owner);
+                    completeEnclosing(c);
+                } finally {
+                    // The flush needs to happen only after annotations
+                    // are filled in.
+                    annotate.enterDoneWithoutFlush();
+                }
+                fillIn(c);
             } finally {
-                // The flush needs to happen only after annotations
-                // are filled in.
-                annotate.enterDoneWithoutFlush();
+                dependencies.pop();
             }
-            fillIn(c);
         } else if (sym.kind == PCK) {
             PackageSymbol p = (PackageSymbol)sym;
             try {
@@ -257,7 +267,6 @@
                                                         + classfile.toUri());
                     }
                 }
-                return;
             } finally {
                 currentClassFile = previousClassFile;
             }
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Mon Aug 04 15:33:22 2014 -0700
@@ -66,7 +66,7 @@
                 flags &= ~flag.value;
             }
         }
-        Assert.check(flags == 0, "Flags parameter contains unknown flags " + flags);
+        Assert.check(flags == 0);
         return flagSet;
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java	Mon Aug 04 15:33:22 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,22 +67,19 @@
         private TypePathEntry(TypePathEntryKind tag) {
             Assert.check(tag == TypePathEntryKind.ARRAY ||
                     tag == TypePathEntryKind.INNER_TYPE ||
-                    tag == TypePathEntryKind.WILDCARD,
-                    "Invalid TypePathEntryKind: " + tag);
+                    tag == TypePathEntryKind.WILDCARD);
             this.tag = tag;
             this.arg = 0;
         }
 
         public TypePathEntry(TypePathEntryKind tag, int arg) {
-            Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT,
-                    "Invalid TypePathEntryKind: " + tag);
+            Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT);
             this.tag = tag;
             this.arg = arg;
         }
 
         public static TypePathEntry fromBinary(int tag, int arg) {
-            Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag,
-                    "Invalid TypePathEntry tag/arg: " + tag + "/" + arg);
+            Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag);
             switch (tag) {
             case 0:
                 return ARRAY;
@@ -351,7 +348,7 @@
         Iterator<Integer> iter = list.iterator();
         while (iter.hasNext()) {
             Integer fst = iter.next();
-            Assert.check(iter.hasNext(), "Could not decode type path: " + list);
+            Assert.check(iter.hasNext());
             Integer snd = iter.next();
             loc = loc.append(TypePathEntry.fromBinary(fst, snd));
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Aug 04 15:33:22 2014 -0700
@@ -49,6 +49,7 @@
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
 import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.Dependencies.AttributionKind;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
 import static com.sun.tools.javac.code.Flags.*;
@@ -94,6 +95,7 @@
     final Annotate annotate;
     final DeferredLintHandler deferredLintHandler;
     final TypeEnvs typeEnvs;
+    final Dependencies dependencies;
 
     public static Attr instance(Context context) {
         Attr instance = context.get(attrKey);
@@ -123,6 +125,7 @@
         annotate = Annotate.instance(context);
         deferredLintHandler = DeferredLintHandler.instance(context);
         typeEnvs = TypeEnvs.instance(context);
+        dependencies = Dependencies.instance(context);
 
         Options options = Options.instance(context);
 
@@ -254,7 +257,7 @@
      *  @param env    The current environment.
      */
     boolean isAssignableAsBlankFinal(VarSymbol v, Env<AttrContext> env) {
-        Symbol owner = owner(env);
+        Symbol owner = env.info.scope.owner;
            // owner refers to the innermost variable, method or
            // initializer block declaration at this point.
         return
@@ -269,41 +272,6 @@
              ((v.flags() & STATIC) != 0) == Resolve.isStatic(env));
     }
 
-    /**
-     * Return the innermost enclosing owner symbol in a given attribution context
-     */
-    Symbol owner(Env<AttrContext> env) {
-        while (true) {
-            switch (env.tree.getTag()) {
-                case VARDEF:
-                    //a field can be owner
-                    VarSymbol vsym = ((JCVariableDecl)env.tree).sym;
-                    if (vsym.owner.kind == TYP) {
-                        return vsym;
-                    }
-                    break;
-                case METHODDEF:
-                    //method def is always an owner
-                    return ((JCMethodDecl)env.tree).sym;
-                case CLASSDEF:
-                    //class def is always an owner
-                    return ((JCClassDecl)env.tree).sym;
-                case BLOCK:
-                    //static/instance init blocks are owner
-                    Symbol blockSym = env.info.scope.owner;
-                    if ((blockSym.flags() & BLOCK) != 0) {
-                        return blockSym;
-                    }
-                    break;
-                case TOPLEVEL:
-                    //toplevel is always an owner (for pkge decls)
-                    return env.info.scope.owner;
-            }
-            Assert.checkNonNull(env.next);
-            env = env.next;
-        }
-    }
-
     /** Check that variable can be assigned to.
      *  @param pos    The current source code position.
      *  @param v      The assigned varaible
@@ -695,6 +663,7 @@
      */
     void attribTypeVariables(List<JCTypeParameter> typarams, Env<AttrContext> env) {
         for (JCTypeParameter tvar : typarams) {
+            dependencies.push(AttributionKind.TVAR, tvar);
             TypeVar a = (TypeVar)tvar.type;
             a.tsym.flags_field |= UNATTRIBUTED;
             a.bound = Type.noType;
@@ -710,6 +679,7 @@
                 types.setBounds(a, List.of(syms.objectType));
             }
             a.tsym.flags_field &= ~UNATTRIBUTED;
+            dependencies.pop();
         }
         for (JCTypeParameter tvar : typarams) {
             chk.checkNonCyclic(tvar.pos(), (TypeVar)tvar.type);
@@ -3815,7 +3785,7 @@
             // and are subject to definite assignment checking.
             if ((env.info.enclVar == v || v.pos > tree.pos) &&
                 v.owner.kind == TYP &&
-                canOwnInitializer(owner(env)) &&
+                enclosingInitEnv(env) != null &&
                 v.owner == env.info.scope.owner.enclClass() &&
                 ((v.flags() & STATIC) != 0) == Resolve.isStatic(env) &&
                 (!env.tree.hasTag(ASSIGN) ||
@@ -3835,6 +3805,36 @@
         }
 
         /**
+         * Returns the enclosing init environment associated with this env (if any). An init env
+         * can be either a field declaration env or a static/instance initializer env.
+         */
+        Env<AttrContext> enclosingInitEnv(Env<AttrContext> env) {
+            while (true) {
+                switch (env.tree.getTag()) {
+                    case VARDEF:
+                        JCVariableDecl vdecl = (JCVariableDecl)env.tree;
+                        if (vdecl.sym.owner.kind == TYP) {
+                            //field
+                            return env;
+                        }
+                        break;
+                    case BLOCK:
+                        if (env.next.tree.hasTag(CLASSDEF)) {
+                            //instance/static initializer
+                            return env;
+                        }
+                        break;
+                    case METHODDEF:
+                    case CLASSDEF:
+                    case TOPLEVEL:
+                        return null;
+                }
+                Assert.checkNonNull(env.next);
+                env = env.next;
+            }
+        }
+
+        /**
          * Check for illegal references to static members of enum.  In
          * an enum type, constructors and initializers may not
          * reference its static members unless they are constant.
@@ -3887,17 +3887,6 @@
                    v.name != names._class;
         }
 
-        /** Can the given symbol be the owner of code which forms part
-         *  if class initialization? This is the case if the symbol is
-         *  a type or field, or if the symbol is the synthetic method.
-         *  owning a block.
-         */
-        private boolean canOwnInitializer(Symbol sym) {
-            return
-                (sym.kind & (VAR | TYP)) != 0 ||
-                (sym.kind == MTH && (sym.flags() & BLOCK) != 0);
-        }
-
     Warner noteWarner = new Warner();
 
     /**
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Aug 04 15:33:22 2014 -0700
@@ -2765,7 +2765,7 @@
     }
 
     public void validateTypeAnnotation(JCAnnotation a, boolean isTypeParameter) {
-        Assert.checkNonNull(a.type, "annotation tree hasn't been attributed yet: " + a);
+        Assert.checkNonNull(a.type);
         validateAnnotationTree(a);
 
         if (a.hasTag(TYPE_ANNOTATION) &&
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Aug 04 15:33:22 2014 -0700
@@ -29,6 +29,7 @@
 import com.sun.tools.javac.tree.JCTree.JCTypeCast;
 import com.sun.tools.javac.tree.TreeInfo;
 import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.GraphUtils.DottableNode;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.code.*;
@@ -40,9 +41,9 @@
 import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node;
 import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
 import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
-import com.sun.tools.javac.util.GraphUtils.TarjanNode;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumMap;
 import java.util.EnumSet;
@@ -50,6 +51,7 @@
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Map;
+import java.util.Properties;
 import java.util.Set;
 
 import static com.sun.tools.javac.code.TypeTag.*;
@@ -1607,11 +1609,6 @@
         private DependencyKind(String dotSyle) {
             this.dotSyle = dotSyle;
         }
-
-        @Override
-        public String getDotStyle() {
-            return dotSyle;
-        }
     }
 
     /**
@@ -1684,7 +1681,7 @@
              * updates on the structure of the graph this node belongs to (used to
              * keep dependencies in sync).
              */
-            class Node extends GraphUtils.TarjanNode<ListBuffer<Type>> {
+            class Node extends GraphUtils.TarjanNode<ListBuffer<Type>, Node> implements DottableNode<ListBuffer<Type>, Node> {
 
                 /** map listing all dependencies (grouped by kind) */
                 EnumMap<DependencyKind, Set<Node>> deps;
@@ -1699,33 +1696,12 @@
                     return DependencyKind.values();
                 }
 
-                @Override
-                public String getDependencyName(GraphUtils.Node<ListBuffer<Type>> to, GraphUtils.DependencyKind dk) {
-                    if (dk == DependencyKind.STUCK) return "";
-                    else {
-                        StringBuilder buf = new StringBuilder();
-                        String sep = "";
-                        for (Type from : data) {
-                            UndetVar uv = (UndetVar)inferenceContext.asUndetVar(from);
-                            for (Type bound : uv.getBounds(InferenceBound.values())) {
-                                if (bound.containsAny(List.from(to.data))) {
-                                    buf.append(sep);
-                                    buf.append(bound);
-                                    sep = ",";
-                                }
-                            }
-                        }
-                        return buf.toString();
-                    }
-                }
-
-                @Override
                 public Iterable<? extends Node> getAllDependencies() {
                     return getDependencies(DependencyKind.values());
                 }
 
                 @Override
-                public Iterable<? extends TarjanNode<ListBuffer<Type>>> getDependenciesByKind(GraphUtils.DependencyKind dk) {
+                public Collection<? extends Node> getDependenciesByKind(GraphUtils.DependencyKind dk) {
                     return getDependencies((DependencyKind)dk);
                 }
 
@@ -1855,6 +1831,36 @@
                         }
                     }
                 }
+
+                @Override
+                public Properties nodeAttributes() {
+                    Properties p = new Properties();
+                    p.put("label", toString());
+                    return p;
+                }
+
+                @Override
+                public Properties dependencyAttributes(Node sink, GraphUtils.DependencyKind dk) {
+                    Properties p = new Properties();
+                    p.put("style", ((DependencyKind)dk).dotSyle);
+                    if (dk == DependencyKind.STUCK) return p;
+                    else {
+                        StringBuilder buf = new StringBuilder();
+                        String sep = "";
+                        for (Type from : data) {
+                            UndetVar uv = (UndetVar)inferenceContext.asUndetVar(from);
+                            for (Type bound : uv.getBounds(InferenceBound.values())) {
+                                if (bound.containsAny(List.from(sink.data))) {
+                                    buf.append(sep);
+                                    buf.append(bound);
+                                    sep = ",";
+                                }
+                            }
+                        }
+                        p.put("label", buf.toString());
+                    }
+                    return p;
+                }
             }
 
             /** the nodes in the inference graph */
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Mon Aug 04 15:33:22 2014 -0700
@@ -55,6 +55,7 @@
 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
+import com.sun.tools.javac.util.Dependencies.AttributionKind;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 
@@ -90,6 +91,7 @@
     private final DeferredLintHandler deferredLintHandler;
     private final Lint lint;
     private final TypeEnvs typeEnvs;
+    private final Dependencies dependencies;
 
     public static MemberEnter instance(Context context) {
         MemberEnter instance = context.get(memberEnterKey);
@@ -116,6 +118,7 @@
         deferredLintHandler = DeferredLintHandler.instance(context);
         lint = Lint.instance(context);
         typeEnvs = TypeEnvs.instance(context);
+        dependencies = Dependencies.instance(context);
         allowTypeAnnos = source.allowTypeAnnotations();
     }
 
@@ -555,6 +558,7 @@
 
     // process the non-static imports and the static imports of types.
     public void visitImport(JCImport tree) {
+        dependencies.push(AttributionKind.IMPORT, tree);
         JCFieldAccess imp = (JCFieldAccess)tree.qualid;
         Name name = TreeInfo.name(imp);
 
@@ -581,6 +585,7 @@
                 importNamed(tree.pos(), c, env);
             }
         }
+        dependencies.pop();
     }
 
     public void visitMethodDef(JCMethodDecl tree) {
@@ -952,6 +957,8 @@
         JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
         DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
         try {
+            dependencies.push(c);
+
             // Save class environment for later member enter (2) processing.
             halfcompleted.append(env);
 
@@ -990,16 +997,21 @@
             Type supertype;
 
             if (tree.extending != null) {
-                supertype = attr.attribBase(tree.extending, baseEnv,
-                                            true, false, true);
-                if (sym.isAnonymous()) {
-                    annotate.annotateAnonClassDefLater(tree.extending,
-                                                       tree.mods.annotations,
-                                                       baseEnv, sym, tree.pos(),
-                                                       annotate.extendsCreator);
-                } else {
-                    annotate.annotateTypeLater(tree.extending, baseEnv, sym,
-                                               tree.pos(), annotate.extendsCreator);
+                dependencies.push(AttributionKind.EXTENDS, tree.extending);
+                try {
+                    supertype = attr.attribBase(tree.extending, baseEnv,
+                            true, false, true);
+                    if (sym.isAnonymous()) {
+                        annotate.annotateAnonClassDefLater(tree.extending,
+                                tree.mods.annotations,
+                                baseEnv, sym, tree.pos(),
+                                annotate.extendsCreator);
+                    } else {
+                        annotate.annotateTypeLater(tree.extending, baseEnv, sym,
+                                tree.pos(), annotate.extendsCreator);
+                    }
+                } finally {
+                    dependencies.pop();
                 }
             } else {
                 supertype = ((tree.mods.flags & Flags.ENUM) != 0)
@@ -1018,29 +1030,34 @@
             List<JCExpression> interfaceTrees = tree.implementing;
             int i = 0;
             for (JCExpression iface : interfaceTrees) {
-                Type it = attr.attribBase(iface, baseEnv, false, true, true);
-                if (it.hasTag(CLASS)) {
-                    interfaces.append(it);
-                    if (all_interfaces != null) all_interfaces.append(it);
-                    chk.checkNotRepeated(iface.pos(), types.erasure(it), interfaceSet);
-                } else {
-                    if (all_interfaces == null)
-                        all_interfaces = new ListBuffer<Type>().appendList(interfaces);
-                    all_interfaces.append(modelMissingTypes(it, iface, true));
+                dependencies.push(AttributionKind.IMPLEMENTS, iface);
+                try {
+                    Type it = attr.attribBase(iface, baseEnv, false, true, true);
+                    if (it.hasTag(CLASS)) {
+                        interfaces.append(it);
+                        if (all_interfaces != null) all_interfaces.append(it);
+                        chk.checkNotRepeated(iface.pos(), types.erasure(it), interfaceSet);
+                    } else {
+                        if (all_interfaces == null)
+                            all_interfaces = new ListBuffer<Type>().appendList(interfaces);
+                        all_interfaces.append(modelMissingTypes(it, iface, true));
 
+                    }
+                    if (sym.isAnonymous()) {
+                        // Note: if an anonymous class ever has more than
+                        // one supertype for some reason, this will
+                        // incorrectly attach tree.mods.annotations to ALL
+                        // supertypes, not just the first.
+                        annotate.annotateAnonClassDefLater(iface, tree.mods.annotations,
+                                baseEnv, sym, tree.pos(),
+                                annotate.implementsCreator(i++));
+                    } else {
+                        annotate.annotateTypeLater(iface, baseEnv, sym, tree.pos(),
+                                annotate.implementsCreator(i++));
+                    }
+                } finally {
+                    dependencies.pop();
                 }
-                if (sym.isAnonymous()) {
-                    // Note: if an anonymous class ever has more than
-                    // one supertype for some reason, this will
-                    // incorrectly attach tree.mods.annotations to ALL
-                    // supertypes, not just the first.
-                    annotate.annotateAnonClassDefLater(iface, tree.mods.annotations,
-                                                       baseEnv, sym, tree.pos(),
-                                                       annotate.implementsCreator(i++));
-                } else {
-                    annotate.annotateTypeLater(iface, baseEnv, sym, tree.pos(),
-                                               annotate.implementsCreator(i++));
-            }
             }
 
             if ((c.flags_field & ANNOTATION) != 0) {
@@ -1157,6 +1174,7 @@
         } finally {
             deferredLintHandler.setPos(prevLintPos);
             log.useSource(prev);
+            dependencies.pop();
         }
 
         // Enter all member fields and methods of a set of half completed
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java	Mon Aug 04 15:33:22 2014 -0700
@@ -488,6 +488,10 @@
                 }
             }
 
+            if (options.isSet("completionDeps")) {
+                Dependencies.GraphDependencies.preRegister(context);
+            }
+
             comp = JavaCompiler.instance(context);
 
             // FIXME: this code will not be invoked if using JavacTask.parse/analyze/generate
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Assert.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Assert.java	Mon Aug 04 15:33:22 2014 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,6 @@
 
 package com.sun.tools.javac.util;
 
-
 /**
  * Simple facility for unconditional assertions.
  * The methods in this class are described in terms of equivalent assert
@@ -87,7 +86,7 @@
     }
 
     /** Equivalent to
-     *   assert cond : value;
+     *   assert cond : msg;
      */
     public static void check(boolean cond, String msg) {
         if (!cond)
@@ -103,7 +102,7 @@
     }
 
     /** Equivalent to
-     *   assert (o == null) : value;
+     *   assert (o == null) : msg;
      */
     public static void checkNull(Object o, String msg) {
         if (o != null)
@@ -111,7 +110,7 @@
     }
 
     /** Equivalent to
-     *   assert (o != null) : value;
+     *   assert (o != null) : msg;
      */
     public static <T> T checkNonNull(T t, String msg) {
         if (t == null)
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java	Mon Aug 04 15:33:22 2014 -0700
@@ -183,7 +183,7 @@
      */
     public void incl(int x) {
         Assert.check(currentState != BitsState.UNKNOWN);
-        Assert.check(x >= 0, "Value of x " + x);
+        Assert.check(x >= 0);
         sizeTo((x >>> wordshift) + 1);
         bits[x >>> wordshift] = bits[x >>> wordshift] |
             (1 << (x & wordmask));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Dependencies.java	Mon Aug 04 15:33:22 2014 -0700
@@ -0,0 +1,559 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.util;
+
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.Completer;
+import com.sun.tools.javac.code.Symbol.CompletionFailure;
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.util.GraphUtils.DotVisitor;
+import com.sun.tools.javac.util.GraphUtils.NodeVisitor;
+
+import java.io.Closeable;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Stack;
+
+import javax.tools.JavaFileObject;
+
+/**
+ *  This class is used to track dependencies in the javac symbol completion process.
+ *
+ *  <p><b>This is NOT part of any supported API.
+ *  If you write code that depends on this, you do so at your own risk.
+ *  This code and its internal interfaces are subject to change or
+ *  deletion without notice.</b>
+ */
+public abstract class Dependencies {
+
+    protected static final Context.Key<Dependencies> dependenciesKey = new Context.Key<>();
+
+    public static Dependencies instance(Context context) {
+        Dependencies instance = context.get(dependenciesKey);
+        if (instance == null) {
+            //use a do-nothing implementation in case no other implementation has been set by preRegister
+            instance = new DummyDependencies(context);
+        }
+        return instance;
+    }
+
+    Dependencies(Context context) {
+        context.put(dependenciesKey, this);
+    }
+
+    /**
+     * This enum models different kinds of attribution actions triggered during
+     * symbol completion.
+     */
+    public enum AttributionKind {
+        /**
+         * Attribution of superclass (i.e. @{code extends} clause).
+         */
+        EXTENDS {
+            @Override
+            String format(JCTree tree) {
+                return "extends " + super.format(tree);
+            }
+        },
+        /**
+         * Attribution of superinterface (i.e. an type in the @{code interface} clause).
+         */
+        IMPLEMENTS {
+            @Override
+            String format(JCTree tree) {
+                return "implements " + super.format(tree);
+            }
+        },
+        /**
+         * Attribution of an import statement
+         */
+        IMPORT,
+        /**
+         * Attribution of type-variable bound
+         */
+        TVAR {
+            @Override
+            String format(JCTree tree) {
+                return "<" + super.format(tree) + ">";
+            }
+        };
+
+        String format(JCTree tree) {
+            return tree.toString();
+        }
+    }
+
+    /**
+     * Push a new completion node on the stack.
+     */
+    abstract public void push(ClassSymbol s);
+
+    /**
+     * Push a new attribution node on the stack.
+     */
+    abstract public void push(AttributionKind ak, JCTree t);
+
+    /**
+     * Remove current dependency node from the stack.
+     */
+    abstract public void pop();
+
+    /**
+     * This class creates a graph of all dependencies as symbols are completed;
+     * when compilation finishes, the resulting dependecy graph is then dumped
+     * onto a dot file. Several options are provided to customise the output of the graph.
+     */
+    public static class GraphDependencies extends Dependencies implements Closeable, Completer {
+
+        /**
+         * set of enabled dependencies modes
+         */
+        private EnumSet<DependenciesMode> dependenciesModes;
+
+        /**
+         * file in which the dependency graph should be written
+         */
+        private String dependenciesFile;
+
+        /**
+         * Register a Context.Factory to create a Dependencies.
+         */
+        public static void preRegister(final Context context) {
+            context.put(dependenciesKey, new Context.Factory<Dependencies>() {
+                public Dependencies make(Context c) {
+                    Dependencies deps = new GraphDependencies(context);
+                    return deps;
+                }
+            });
+        }
+
+        /**
+         * Build a Dependencies instance.
+         */
+        GraphDependencies(Context context) {
+            super(context);
+            Options options = Options.instance(context);
+            //fetch filename
+            String[] modes = options.get("completionDeps").split(",");
+            for (String mode : modes) {
+                if (mode.startsWith("file=")) {
+                    dependenciesFile = mode.substring(5);
+                }
+            }
+            //parse modes
+            dependenciesModes = DependenciesMode.getDependenciesModes(modes);
+            //add to closeables
+            JavaCompiler compiler = JavaCompiler.instance(context);
+            compiler.closeables = compiler.closeables.prepend(this);
+        }
+
+        enum DependenciesMode {
+            SOURCE("source"),
+            CLASS("class"),
+            REDUNDANT("redundant"),
+            SIDE_EFFECTS("side-effects");
+
+            final String opt;
+
+            private DependenciesMode(String opt) {
+                this.opt = opt;
+            }
+
+            /**
+             * This method is used to parse the {@code completionDeps} option.
+             * Possible modes are separated by colon; a mode can be excluded by
+             * prepending '-' to its name. Finally, the special mode 'all' can be used to
+             * add all modes to the resulting enum.
+             */
+            static EnumSet<DependenciesMode> getDependenciesModes(String[] modes) {
+                EnumSet<DependenciesMode> res = EnumSet.noneOf(DependenciesMode.class);
+                Collection<String> args = Arrays.asList(modes);
+                if (args.contains("all")) {
+                    res = EnumSet.allOf(DependenciesMode.class);
+                }
+                for (DependenciesMode mode : values()) {
+                    if (args.contains(mode.opt)) {
+                        res.add(mode);
+                    } else if (args.contains("-" + mode.opt)) {
+                        res.remove(mode);
+                    }
+                }
+                return res;
+            }
+        }
+
+        /**
+         * Class representing a node in the dependency graph. Nodes are of two main
+         * kinds: (i) symbol nodes, corresponding to symbol completion requests
+         * (either from source or classfile); (ii) attribution nodes, corresponding to
+         * attribution actions triggered during (source) completion.
+         */
+        static abstract class Node extends GraphUtils.AbstractNode<String, Node>
+                implements GraphUtils.DottableNode<String, Node> {
+
+            /**
+             * Model the dependencies between nodes.
+             */
+            enum DependencyKind implements GraphUtils.DependencyKind {
+                /**
+                 * standard dependency - i.e. completion of the source node depends
+                 * on completion of the sink node.
+                 */
+                REQUIRES("solid"),
+                /**
+                 * soft dependencies - i.e. completion of the source node depends
+                 * on side-effects of the source node. These dependencies are meant
+                 * to capture the order in which javac processes all dependants of a given node.
+                 */
+                SIDE_EFFECTS("dashed");
+
+                final String dotStyle;
+
+                DependencyKind(String dotStyle) {
+                    this.dotStyle = dotStyle;
+                }
+            }
+
+            /**
+             * dependant nodes grouped by kind
+             */
+            EnumMap<DependencyKind, List<Node>> depsByKind;
+
+            Node(String value) {
+                super(value);
+                this.depsByKind = new EnumMap<>(DependencyKind.class);
+                for (DependencyKind depKind : DependencyKind.values()) {
+                    depsByKind.put(depKind, new ArrayList<Node>());
+                }
+            }
+
+            void addDependency(DependencyKind depKind, Node dep) {
+                List<Node> deps = depsByKind.get(depKind);
+                if (!deps.contains(dep)) {
+                    deps.add(dep);
+                }
+            }
+
+            @Override
+            public boolean equals(Object obj) {
+                return obj instanceof Node &&
+                        data.equals(((Node) obj).data);
+            }
+
+            @Override
+            public int hashCode() {
+                return data.hashCode();
+            }
+
+            @Override
+            public GraphUtils.DependencyKind[] getSupportedDependencyKinds() {
+                return DependencyKind.values();
+            }
+
+            @Override
+            public java.util.Collection<? extends Node> getDependenciesByKind(GraphUtils.DependencyKind dk) {
+                List<Node> deps = depsByKind.get(dk);
+                if (dk == DependencyKind.REQUIRES) {
+                    return deps;
+                } else {
+                    Set<Node> temp = new HashSet<>(deps);
+                    temp.removeAll(depsByKind.get(DependencyKind.REQUIRES));
+                    return temp;
+                }
+            }
+
+            @Override
+            public Properties nodeAttributes() {
+                Properties p = new Properties();
+                p.put("label", DotVisitor.wrap(toString()));
+                return p;
+            }
+
+            @Override
+            public Properties dependencyAttributes(Node to, GraphUtils.DependencyKind dk) {
+                Properties p = new Properties();
+                p.put("style", ((DependencyKind) dk).dotStyle);
+                return p;
+            }
+        }
+
+        /**
+         * This is a dependency node used to model symbol completion requests.
+         * Completion requests can come from either source or class.
+         */
+        static class CompletionNode extends Node {
+
+            /**
+             * Completion kind (source vs. classfile)
+             */
+            enum Kind {
+                /**
+                 * Source completion request
+                 */
+                SOURCE("solid"),
+                /**
+                 * Classfile completion request
+                 */
+                CLASS("dotted");
+
+                final String dotStyle;
+
+                Kind(String dotStyle) {
+                    this.dotStyle = dotStyle;
+                }
+            }
+
+            final Kind ck;
+
+            CompletionNode(ClassSymbol sym) {
+                super(sym.getQualifiedName().toString());
+                //infer completion kind by looking at the symbol fields
+                boolean fromClass = (sym.classfile == null && sym.sourcefile == null) ||
+                        (sym.classfile != null && sym.classfile.getKind() == JavaFileObject.Kind.CLASS);
+                ck = fromClass ?
+                        CompletionNode.Kind.CLASS :
+                        CompletionNode.Kind.SOURCE;
+            }
+
+            @Override
+            public Properties nodeAttributes() {
+                Properties p = super.nodeAttributes();
+                p.put("style", ck.dotStyle);
+                p.put("shape", "ellipse");
+                return p;
+            }
+        }
+
+        /**
+         * This is a dependency node used to model attribution actions triggered during
+         * source symbol completion. The possible kinds of attribution actions are
+         * captured in {@link AttributionNode}.
+         */
+        static class AttributionNode extends Node {
+
+            AttributionNode(AttributionKind ak, JCTree tree) {
+                super(ak.format(tree));
+            }
+
+            @Override
+            public Properties nodeAttributes() {
+                Properties p = super.nodeAttributes();
+                p.put("shape", "box");
+                p.put("style", "solid");
+                return p;
+            }
+        }
+
+        /**
+         * stack of dependency nodes currently being processed
+         */
+        Stack<Node> nodeStack = new Stack<>();
+
+        /**
+         * map containing all dependency nodes seen so far
+         */
+        Map<String, Node> dependencyNodeMap = new LinkedHashMap<>();
+
+        @Override
+        public void push(ClassSymbol s) {
+            Node n = new CompletionNode(s);
+            if (n == push(n)) {
+                s.completer = this;
+            }
+        }
+
+        @Override
+        public void push(AttributionKind ak, JCTree t) {
+            push(new AttributionNode(ak, t));
+        }
+
+        /**
+         * Push a new dependency on the stack.
+         */
+        protected Node push(Node newNode) {
+            Node cachedNode = dependencyNodeMap.get(newNode.data);
+            if (cachedNode == null) {
+                dependencyNodeMap.put(newNode.data, newNode);
+            } else {
+                newNode = cachedNode;
+            }
+            if (!nodeStack.isEmpty()) {
+                Node currentNode = nodeStack.peek();
+                currentNode.addDependency(Node.DependencyKind.REQUIRES, newNode);
+            }
+            nodeStack.push(newNode);
+            return newNode;
+        }
+
+        @Override
+        public void pop() {
+            nodeStack.pop();
+        }
+
+        @Override
+        public void close() throws IOException {
+            if (dependenciesFile != null) {
+                if (!dependenciesModes.contains(DependenciesMode.REDUNDANT)) {
+                    //prune spurious edges
+                    new PruneVisitor().visit(dependencyNodeMap.values(), null);
+                }
+                if (!dependenciesModes.contains(DependenciesMode.CLASS)) {
+                    //filter class completions
+                    new FilterVisitor(CompletionNode.Kind.SOURCE).visit(dependencyNodeMap.values(), null);
+                }
+                if (!dependenciesModes.contains(DependenciesMode.SOURCE)) {
+                    //filter source completions
+                    new FilterVisitor(CompletionNode.Kind.CLASS).visit(dependencyNodeMap.values(), null);
+                }
+                if (dependenciesModes.contains(DependenciesMode.SIDE_EFFECTS)) {
+                    //add side-effects edges
+                    new SideEffectVisitor().visit(dependencyNodeMap.values(), null);
+                }
+                //write to file
+                try (FileWriter fw = new FileWriter(dependenciesFile)) {
+                    fw.append(GraphUtils.toDot(dependencyNodeMap.values(), "CompletionDeps", ""));
+                }
+            }
+        }
+
+        @Override
+        public void complete(Symbol sym) throws CompletionFailure {
+            push((ClassSymbol) sym);
+            pop();
+            sym.completer = this;
+        }
+
+        /**
+         * This visitor is used to generate the special side-effect dependencies
+         * given a graph containing only standard dependencies.
+         */
+        private static class SideEffectVisitor extends NodeVisitor<String, Node, Void> {
+            @Override
+            public void visitNode(Node node, Void arg) {
+                //do nothing
+            }
+
+            @Override
+            public void visitDependency(GraphUtils.DependencyKind dk, Node from, Node to, Void arg) {
+                //if we are adding multiple dependencies to same node
+                //make order explicit via special 'side-effect' dependencies
+                List<Node> deps = from.depsByKind.get(dk);
+                int pos = deps.indexOf(to);
+                if (dk == Node.DependencyKind.REQUIRES && pos > 0) {
+                    to.addDependency(Node.DependencyKind.SIDE_EFFECTS, deps.get(pos - 1));
+                }
+            }
+        }
+
+        /**
+         * This visitor is used to prune the graph from spurious edges using some heuristics.
+         */
+        private static class PruneVisitor extends NodeVisitor<String, Node, Void> {
+            @Override
+            public void visitNode(Node node, Void arg) {
+                //do nothing
+            }
+
+            @Override
+            public void visitDependency(GraphUtils.DependencyKind dk, Node from, Node to, Void arg) {
+                //heuristic - skips dependencies that are likely to be fake
+                if (from.equals(to) ||
+                        from.depsByKind.get(Node.DependencyKind.REQUIRES).contains(to)) {
+                    to.depsByKind.get(dk).remove(from);
+                }
+            }
+        }
+
+        /**
+         * This visitor is used to retain only completion nodes with given kind.
+         */
+        private class FilterVisitor extends NodeVisitor<String, Node, Void> {
+
+            CompletionNode.Kind ck;
+
+            private FilterVisitor(CompletionNode.Kind ck) {
+                this.ck = ck;
+            }
+
+            @Override
+            public void visitNode(Node node, Void arg) {
+                if (node instanceof CompletionNode) {
+                    if (((CompletionNode) node).ck != ck) {
+                        dependencyNodeMap.remove(node.data);
+                    }
+                }
+            }
+
+            @Override
+            public void visitDependency(GraphUtils.DependencyKind dk, Node from, Node to, Void arg) {
+                if (to instanceof CompletionNode) {
+                    if (((CompletionNode) to).ck != ck) {
+                        from.depsByKind.get(dk).remove(to);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Dummy class to be used when dependencies options are not set. This keeps
+     * performance cost of calling push/pop methods during completion marginally low.
+     */
+    private static class DummyDependencies extends Dependencies {
+
+        private DummyDependencies(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void push(ClassSymbol s) {
+            //do nothing
+        }
+
+        @Override
+        public void push(AttributionKind ak, JCTree t) {
+            //do nothing
+        }
+
+        @Override
+        public void pop() {
+            //do nothing
+        }
+    }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/util/GraphUtils.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/GraphUtils.java	Mon Aug 04 15:33:22 2014 -0700
@@ -25,6 +25,10 @@
 
 package com.sun.tools.javac.util;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Properties;
+
 /** <p><b>This is NOT part of any supported API.
  *  If you write code that depends on this, you do so at your own risk.
  *  This code and its internal interfaces are subject to change or
@@ -33,25 +37,65 @@
 public class GraphUtils {
 
     /**
-     * Basic interface for defining various dependency kinds. All dependency kinds
-     * must at least support basic capabilities to tell the DOT engine how to render them.
+     * Basic interface for defining various dependency kinds.
+     */
+    public interface DependencyKind { }
+
+    /**
+     * Common superinterfaces to all graph nodes.
      */
-    public interface DependencyKind {
+    public interface Node<D, N extends Node<D, N>> {
+        /**
+         * visitor method.
+         */
+        <A> void accept(NodeVisitor<D, N, A> visitor, A arg);
+    }
+
+    /**
+     * Visitor for graph nodes.
+     */
+    static abstract class NodeVisitor<D, N extends Node<D, N>, A> {
+        /**
+         * Visitor action for nodes.
+         */
+        public abstract void visitNode(N node, A arg);
         /**
-         * Returns the DOT representation (to be used in a {@code style} attribute
-         * that's most suited for this dependency kind.
+         * Visitor action for a dependency between 'from' and 'to' with given kind.
+         */
+        public abstract void visitDependency(DependencyKind dk, N from, N to, A arg);
+
+        /**
+         * Visitor entry point.
          */
-        String getDotStyle();
+        public void visit(Collection<? extends N> nodes, A arg) {
+            for (N n : new ArrayList<>(nodes)) {
+                n.accept(this, arg);
+            }
+        }
+    }
+
+    /**
+     * Optional interface for nodes supporting dot-based representation.
+     */
+    public interface DottableNode<D, N extends DottableNode<D, N>> extends Node<D, N> {
+        /**
+         * Retrieves the set of dot attributes associated with the node.
+         */
+        Properties nodeAttributes();
+        /**
+         * Retrieves the set of dot attributes associated with a given dependency.
+         */
+        Properties dependencyAttributes(N to, DependencyKind dk);
     }
 
     /**
      * This class is a basic abstract class for representing a node.
      * A node is associated with a given data.
      */
-    public static abstract class Node<D> {
+    public static abstract class AbstractNode<D, N extends AbstractNode<D, N>> implements Node<D, N> {
         public final D data;
 
-        public Node(D data) {
+        public AbstractNode(D data) {
             this.data = data;
         }
 
@@ -61,26 +105,32 @@
         public abstract DependencyKind[] getSupportedDependencyKinds();
 
         /**
-         * Get all dependencies, regardless of their kind.
+         * Get all dependencies of a given kind
          */
-        public abstract Iterable<? extends Node<D>> getAllDependencies();
-
-        /**
-         * Get a name for the dependency (of given kind) linking this node to a given node
-         */
-        public abstract String getDependencyName(Node<D> to, DependencyKind dk);
+        public abstract Collection<? extends N> getDependenciesByKind(DependencyKind dk);
 
         @Override
         public String toString() {
             return data.toString();
         }
+
+        @SuppressWarnings("unchecked")
+        public <A> void accept(NodeVisitor<D, N, A> visitor, A arg) {
+            visitor.visitNode((N)this, arg);
+            for (DependencyKind dk : getSupportedDependencyKinds()) {
+                for (N dep : new ArrayList<>(getDependenciesByKind(dk))) {
+                    visitor.visitDependency(dk, (N)this, dep, arg);
+                }
+            }
+        }
     }
 
     /**
      * This class specialized Node, by adding elements that are required in order
      * to perform Tarjan computation of strongly connected components.
      */
-    public static abstract class TarjanNode<D> extends Node<D> implements Comparable<TarjanNode<D>> {
+    public static abstract class TarjanNode<D, N extends TarjanNode<D, N>> extends AbstractNode<D, N>
+            implements Comparable<N> {
         int index = -1;
         int lowlink;
         boolean active;
@@ -89,11 +139,9 @@
             super(data);
         }
 
-        public abstract Iterable<? extends TarjanNode<D>> getAllDependencies();
+        public abstract Iterable<? extends N> getAllDependencies();
 
-        public abstract Iterable<? extends TarjanNode<D>> getDependenciesByKind(DependencyKind dk);
-
-        public int compareTo(TarjanNode<D> o) {
+        public int compareTo(N o) {
             return (index < o.index) ? -1 : (index == o.index) ? 0 : 1;
         }
     }
@@ -102,7 +150,7 @@
      * Tarjan's algorithm to determine strongly connected components of a
      * directed graph in linear time. Works on TarjanNode.
      */
-    public static <D, N extends TarjanNode<D>> List<? extends List<? extends N>> tarjan(Iterable<? extends N> nodes) {
+    public static <D, N extends TarjanNode<D, N>> List<? extends List<? extends N>> tarjan(Iterable<? extends N> nodes) {
         ListBuffer<List<N>> cycles = new ListBuffer<>();
         ListBuffer<N> stack = new ListBuffer<>();
         int index = 0;
@@ -114,15 +162,13 @@
         return cycles.toList();
     }
 
-    private static <D, N extends TarjanNode<D>> int tarjan(N v, int index, ListBuffer<N> stack, ListBuffer<List<N>> cycles) {
+    private static <D, N extends TarjanNode<D, N>> int tarjan(N v, int index, ListBuffer<N> stack, ListBuffer<List<N>> cycles) {
         v.index = index;
         v.lowlink = index;
         index++;
         stack.prepend(v);
         v.active = true;
-        for (TarjanNode<D> nd: v.getAllDependencies()) {
-            @SuppressWarnings("unchecked")
-            N n = (N)nd;
+        for (N n: v.getAllDependencies()) {
             if (n.index == -1) {
                 tarjan(n, index, stack, cycles);
                 v.lowlink = Math.min(v.lowlink, n.lowlink);
@@ -149,24 +195,45 @@
      * and {@code Node.printDependency} to display edge labels. The resulting
      * representation is also customizable with a graph name and a header.
      */
-    public static <D> String toDot(Iterable<? extends TarjanNode<D>> nodes, String name, String header) {
+    public static <D, N extends DottableNode<D, N>> String toDot(Collection<? extends N> nodes, String name, String header) {
         StringBuilder buf = new StringBuilder();
         buf.append(String.format("digraph %s {\n", name));
-        buf.append(String.format("label = \"%s\";\n", header));
-        //dump nodes
-        for (TarjanNode<D> n : nodes) {
-            buf.append(String.format("%s [label = \"%s\"];\n", n.hashCode(), n.toString()));
-        }
-        //dump arcs
-        for (TarjanNode<D> from : nodes) {
-            for (DependencyKind dk : from.getSupportedDependencyKinds()) {
-                for (TarjanNode<D> to : from.getDependenciesByKind(dk)) {
-                    buf.append(String.format("%s -> %s [label = \" %s \" style = %s ];\n",
-                            from.hashCode(), to.hashCode(), from.getDependencyName(to, dk), dk.getDotStyle()));
-                }
-            }
-        }
+        buf.append(String.format("label = %s;\n", DotVisitor.wrap(header)));
+        DotVisitor<D, N> dotVisitor = new DotVisitor<>();
+        dotVisitor.visit(nodes, buf);
         buf.append("}\n");
         return buf.toString();
     }
+
+    /**
+     * This visitor is used to dump the contents of a set of nodes of type {@link DottableNode}
+     * onto a string builder.
+     */
+    public static class DotVisitor<D, N extends DottableNode<D, N>> extends NodeVisitor<D, N, StringBuilder> {
+
+        @Override
+        public void visitDependency(DependencyKind dk, N from, N to, StringBuilder buf) {
+            buf.append(String.format("%s -> %s", from.hashCode(), to.hashCode()));
+            buf.append(formatProperties(from.dependencyAttributes(to, dk)));
+            buf.append('\n');
+        }
+
+        @Override
+        public void visitNode(N node, StringBuilder buf) {
+            buf.append(String.format("%s ", node.hashCode()));
+            buf.append(formatProperties(node.nodeAttributes()));
+            buf.append('\n');
+        }
+
+        protected String formatProperties(Properties p) {
+            return p.toString().replaceAll(",", " ")
+                .replaceAll("\\{", "[")
+                .replaceAll("\\}", "]");
+        }
+
+        protected static String wrap(String s) {
+            String res = "\"" + s + "\"";
+            return res.replaceAll("\n", "");
+        }
+    }
 }
--- a/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javap/JavapTask.java	Mon Aug 04 15:33:22 2014 -0700
@@ -575,6 +575,9 @@
                 }
                 reportError("err.ioerror", className, msg);
                 result = EXIT_ERROR;
+            } catch (OutOfMemoryError e) {
+                reportError("err.nomem");
+                result = EXIT_ERROR;
             } catch (Throwable t) {
                 StringWriter sw = new StringWriter();
                 PrintWriter pw = new PrintWriter(sw);
--- a/langtools/src/share/classes/com/sun/tools/javap/resources/javap.properties	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javap/resources/javap.properties	Mon Aug 04 15:33:22 2014 -0700
@@ -18,6 +18,7 @@
 err.no.SourceFile.attribute=no SourceFile attribute
 err.source.file.not.found=source file not found
 err.bad.innerclasses.attribute=bad InnerClasses attribute for {0}
+err.nomem=Insufficient memory. To increase memory use -J-Xmx option.
 
 main.usage.summary=\
 Usage: {0} <options> <classes>\n\
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/all/RunCodingRules.java	Mon Aug 04 15:33:22 2014 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8043643
+ * @summary Run the langtools coding rules over the langtools source code.
+ */
+
+
+import java.io.*;
+import java.nio.file.Files;
+import java.util.*;
+import java.util.stream.Collectors;
+
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import com.sun.tools.javac.util.Assert;
+
+public class RunCodingRules {
+    public static void main(String... args) throws Exception {
+        new RunCodingRules().run();
+    }
+
+    public void run() throws Exception {
+        File testSrc = new File(System.getProperty("test.src", "."));
+        File targetDir = new File(System.getProperty("test.classes", "."));
+        File sourceDir = null;
+        File crulesDir = null;
+        for (File d = testSrc; d != null; d = d.getParentFile()) {
+            if (new File(d, "TEST.ROOT").exists()) {
+                d = d.getParentFile();
+                File f = new File(d, "src/share/classes");
+                if (f.exists()) {
+                    sourceDir = f;
+                    f = new File(d, "make/tools");
+                    if (f.exists())
+                        crulesDir = f;
+                    break;
+                }
+            }
+        }
+
+        if (sourceDir == null || crulesDir == null) {
+            System.err.println("Warning: sources not found, test skipped.");
+            return ;
+        }
+
+        JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null);
+        DiagnosticListener<JavaFileObject> noErrors = diagnostic -> {
+            Assert.check(diagnostic.getKind() != Diagnostic.Kind.ERROR, diagnostic.toString());
+        };
+
+        List<File> crulesFiles = Files.walk(crulesDir.toPath())
+                                      .map(entry -> entry.toFile())
+                                      .filter(entry -> entry.getName().endsWith(".java"))
+                                      .filter(entry -> entry.getParentFile().getName().equals("crules"))
+                                      .collect(Collectors.toList());
+
+        File crulesTarget = new File(targetDir, "crules");
+        crulesTarget.mkdirs();
+        List<String> crulesOptions = Arrays.asList("-d", crulesTarget.getAbsolutePath());
+        javaCompiler.getTask(null, fm, noErrors, crulesOptions, null,
+                fm.getJavaFileObjectsFromFiles(crulesFiles)).call();
+        File registration = new File(crulesTarget, "META-INF/services/com.sun.source.util.Plugin");
+        registration.getParentFile().mkdirs();
+        try (Writer metaInfServices = new FileWriter(registration)) {
+            metaInfServices.write("crules.CodingRulesAnalyzerPlugin\n");
+        }
+
+        List<File> sources = Files.walk(sourceDir.toPath())
+                                  .map(entry -> entry.toFile())
+                                  .filter(entry -> entry.getName().endsWith(".java"))
+                                  .collect(Collectors.toList());
+
+        File sourceTarget = new File(targetDir, "classes");
+        sourceTarget.mkdirs();
+        String processorPath = crulesTarget.getAbsolutePath() + File.pathSeparator +
+                crulesDir.getAbsolutePath();
+        List<String> options = Arrays.asList("-d", sourceTarget.getAbsolutePath(),
+                "-processorpath", processorPath, "-Xplugin:coding_rules");
+        javaCompiler.getTask(null, fm, noErrors, options, null,
+                fm.getJavaFileObjectsFromFiles(sources)).call();
+    }
+}
--- a/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTestBase.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/test/tools/javac/classfiles/attributes/LocalVariableTable/LocalVariableTestBase.java	Mon Aug 04 15:33:22 2014 -0700
@@ -36,14 +36,26 @@
 import static java.lang.String.format;
 import static java.util.stream.Collectors.*;
 
-
+/**
+ * Base class for LocalVariableTable and LocalVariableTypeTable attributes tests.
+ * To add tests cases you should extend this class.
+ * Then implement {@link #getVariableTables} to get LocalVariableTable or LocalVariableTypeTable attribute.
+ * Then add method with local variables.
+ * Finally, annotate method with information about expected variables and their types
+ * by several {@link LocalVariableTestBase.ExpectedLocals} annotations.
+ * To run test invoke {@link #test()} method.
+ * If there are variables with the same name, set different scopes for them.
+ *
+ * @see #test()
+ */
 public abstract class LocalVariableTestBase extends TestBase {
     public static final int DEFAULT_SCOPE = 0;
     private final ClassFile classFile;
     private final Class<?> clazz;
 
-    protected abstract List<VariableTable> getVariableTables(Code_attribute codeAttribute);
-
+    /**
+     * @param clazz class to test. Must contains annotated methods with expected results.
+     */
     public LocalVariableTestBase(Class<?> clazz) {
         this.clazz = clazz;
         try {
@@ -53,8 +65,12 @@
         }
     }
 
+    protected abstract List<VariableTable> getVariableTables(Code_attribute codeAttribute);
 
-    //info in the LocalVariableTable attribute is compared against expected info stored in annotations
+    /**
+     * Finds expected variables with their type in VariableTable.
+     * Also does consistency checks, like variables from the same scope must point to different indexes.
+     */
     public void test() throws IOException {
         List<java.lang.reflect.Method> testMethods = Stream.of(clazz.getDeclaredMethods())
                 .filter(m -> m.getAnnotationsByType(ExpectedLocals.class).length > 0)
@@ -198,7 +214,10 @@
         }
     }
 
-
+    /**
+     * LocalVariableTable and LocalVariableTypeTable are similar.
+     * VariableTable interface is introduced to test this attributes in the same way without code duplication.
+     */
     interface VariableTable {
 
         int localVariableTableLength();
@@ -231,14 +250,23 @@
         }
     }
 
+    /**
+     * Used to store expected results in sources
+     */
     @Retention(RetentionPolicy.RUNTIME)
     @Repeatable(Container.class)
     @interface ExpectedLocals {
+        /**
+         * @return name of a local variable
+         */
         String name();
 
+        /**
+         * @return type of local variable in the internal format.
+         */
         String type();
 
-        //variables from different scopes can share local variable table index and/or name.
+        //variables from different scopes can share the local variable table index and/or name.
         int scope() default DEFAULT_SCOPE;
     }
 
--- a/langtools/test/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/test/tools/javac/classfiles/attributes/SourceFile/SourceFileTestBase.java	Mon Aug 04 15:33:22 2014 -0700
@@ -30,18 +30,41 @@
 import java.util.Map;
 import javax.tools.JavaFileObject;
 
+/**
+ * Base class for Source file attribute tests. Checks expected file name for specified classes in the SourceFile attribute.
+ * To add new tests you should extend the SourceFileTestBase class and invoke {@link #test} for static sources
+ * or {@link #compileAndTest} for generated sources. For more information see corresponding methods.
+ *
+ * @see #test
+ * @see #compileAndTest
+ */
 public class SourceFileTestBase extends TestBase {
-
+    /**
+     * Checks expected fileName for the specified class in the SourceFile attribute.
+     *
+     * @param classToTest class to check its SourceFile attribute
+     * @param fileName    expected name of the file from which the test file is compiled.
+     */
     protected void test(Class<?> classToTest, String fileName) throws Exception {
         assertAttributePresent(ClassFile.read(getClassFile(classToTest)), fileName);
     }
 
+    /**
+     * Checks expected fileName for the specified class in the SourceFile attribute.
+     *
+     * @param classToTest class name to check its SourceFile attribute
+     * @param fileName    expected name of the file from which the test file is compiled.
+     */
     protected void test(String classToTest, String fileName) throws Exception {
         assertAttributePresent(ClassFile.read(getClassFile(classToTest + ".class")), fileName);
     }
 
     /**
-     * Compile sourceCode and for all "classesToTest" checks SourceFile attribute.
+     * Compiles sourceCode and for each specified class name checks the SourceFile attribute.
+     * The file name is extracted from source code.
+     *
+     * @param sourceCode    source code to compile
+     * @param classesToTest class names to check their SourceFile attribute.
      */
     protected void compileAndTest(String sourceCode, String... classesToTest) throws Exception {
 
--- a/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java	Fri Aug 01 14:09:22 2014 -0700
+++ b/langtools/test/tools/javac/classfiles/attributes/lib/TestBase.java	Mon Aug 04 15:33:22 2014 -0700
@@ -23,11 +23,14 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.io.PrintStream;
-import java.util.*;
+import java.util.List;
+import java.util.Objects;
 import java.util.function.Function;
 import java.util.stream.Stream;
-import javax.tools.*;
+import javax.tools.DiagnosticCollector;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.ToolProvider;
 
 import static java.lang.String.format;
 import static java.lang.System.lineSeparator;
@@ -36,6 +39,11 @@
 import static java.util.stream.Collectors.joining;
 import static java.util.stream.Collectors.toList;
 
+/**
+ * Base class for class file attribute tests.
+ * Contains methods for compiling generated sources in memory,
+ * for reading files from disk and a lot of assert* methods.
+ */
 public class TestBase {
 
     public static final String LINE_SEPARATOR = lineSeparator();
@@ -66,35 +74,48 @@
         }
     }
 
+    /**
+     * Compiles sources in memory.
+     *
+     * @param sources to compile.
+     * @return memory file manager which contains class files and class loader.
+     */
     public InMemoryFileManager compile(String... sources)
             throws IOException, CompilationException {
         return compile(emptyList(), sources);
     }
 
     /**
-     * @param options - compiler options
-     * @param sources
+     * Compiles sources in memory.
+     *
+     * @param options compiler options.
+     * @param sources sources to compile.
      * @return map where key is className, value is corresponding ClassFile.
-     * @throws IOException
      */
-    public InMemoryFileManager compile(List<String> options, String...sources)
+    public InMemoryFileManager compile(List<String> options, String... sources)
             throws IOException, CompilationException {
         return compile(options, ToolBox.JavaSource::new, asList(sources));
     }
 
+    /**
+     * Compiles sources in memory.
+     *
+     * @param sources sources[i][0] - name of file, sources[i][1] - sources.
+     * @return map where key is className, value is corresponding ClassFile.
+     */
     public InMemoryFileManager compile(String[]... sources) throws IOException,
             CompilationException {
         return compile(emptyList(), sources);
     }
 
     /**
-     * @param options -  compiler options
-     * @param sources - sources[i][0] - name of file, sources[i][1] - sources
+     * Compiles sources in memory.
+     *
+     * @param options compiler options
+     * @param sources sources[i][0] - name of file, sources[i][1] - sources.
      * @return map where key is className, value is corresponding ClassFile.
-     * @throws IOException
-     * @throws CompilationException
      */
-    public InMemoryFileManager compile(List<String> options, String[]...sources)
+    public InMemoryFileManager compile(List<String> options, String[]... sources)
             throws IOException, CompilationException {
         return compile(options, src -> new ToolBox.JavaSource(src[0], src[1]), asList(sources));
     }
@@ -142,11 +163,22 @@
         return getClassFile(clazz.getName().replace(".", "/") + ".class");
     }
 
+    /**
+     * Prints message to standard error. New lines are converted to system dependent NL.
+     *
+     * @param message string to print.
+     */
     public void echo(String message) {
         System.err.println(message.replace("\n", LINE_SEPARATOR));
     }
 
-    public void printf(String template, Object...args) {
+    /**
+     * Substitutes args in template and prints result to standard error. New lines are converted to system dependent NL.
+     *
+     * @param template template in standard String.format(...) format.
+     * @param args arguments to substitute in template.
+     */
+    public void printf(String template, Object... args) {
         System.err.printf(template, Stream.of(args)
                 .map(Objects::toString)
                 .map(m -> m.replace("\n", LINE_SEPARATOR))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8051958/T8051958.java	Mon Aug 04 15:33:22 2014 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8051958
+ * @summary Cannot assign a value to final variable in lambda
+ * @compile T8051958.java
+ */
+
+class T8051958 {
+    Runnable inst_r = ()-> {
+        final int x;
+        x = 1;
+    };
+
+    Runnable static_r = ()-> {
+        final int x;
+        x = 1;
+    };
+
+    {
+        Runnable inst_r = ()-> {
+            final int x;
+            x = 1;
+        };
+    }
+
+    static {
+        Runnable static_r = ()-> {
+            final int x;
+            x = 1;
+        };
+    }
+
+    void instTest() {
+        Runnable static_r = ()-> {
+            final int x;
+            x = 1;
+        };
+    }
+
+    static void staticTest() {
+        Runnable static_r = ()-> {
+            final int x;
+            x = 1;
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javap/BadAttributeLength.java	Mon Aug 04 15:33:22 2014 -0700
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8047072
+ * @summary javap OOM on fuzzed classfile
+ * @run main BadAttributeLength
+ */
+
+
+import java.io.*;
+
+public class BadAttributeLength {
+
+    public static String source = "public class Test {\n" +
+                                  "    public static void main(String[] args) {}\n" +
+                                  "}";
+
+    public static void main(String[] args) throws Exception {
+        final File sourceFile = new File("Test.java");
+        if (sourceFile.exists()) {
+            if (!sourceFile.delete()) {
+                throw new IOException("Can't override the Test.java file. " +
+                        "Check permissions.");
+            }
+        }
+        try (FileWriter fw = new FileWriter(sourceFile)) {
+            fw.write(source);
+        }
+
+        final String[] javacOpts = {"Test.java"};
+
+        if (com.sun.tools.javac.Main.compile(javacOpts) != 0) {
+            throw new Exception("Can't compile embedded test.");
+        }
+
+        RandomAccessFile raf = new RandomAccessFile("Test.class", "rw");
+        long attPos = getFirstAttributePos(raf);
+        if (attPos < 0) {
+            throw new Exception("The class file contains no attributes at all.");
+        }
+        raf.seek(attPos + 2); // Jump to the attribute length
+        raf.writeInt(Integer.MAX_VALUE - 1);
+        raf.close();
+
+        String[] opts = { "-v", "Test.class" };
+        StringWriter sw = new StringWriter();
+        PrintWriter pout = new PrintWriter(sw);
+
+        com.sun.tools.javap.Main.run(opts, pout);
+        pout.flush();
+
+        if (sw.getBuffer().indexOf("OutOfMemoryError") != -1) {
+            throw new Exception("javap exited with OutOfMemoryError " +
+                    "instead of giving the proper error message.");
+        }
+    }
+
+    private static long getFirstAttributePos(RandomAccessFile cfile) throws Exception {
+        cfile.seek(0);
+        int v1, v2;
+        v1 = cfile.readInt();
+        // System.out.println("Magic: " + String.format("%X", v1));
+
+        v1 = cfile.readUnsignedShort();
+        v2 = cfile.readUnsignedShort();
+        // System.out.println("Version: " + String.format("%d.%d", v1, v2));
+
+        v1 = cfile.readUnsignedShort();
+        // System.out.println("CPool size: " + v1);
+        // Exhaust the constant pool
+        for (; v1 > 1; v1--) {
+            // System.out.print(".");
+            byte tag = cfile.readByte();
+            switch (tag) {
+                case 7  : // Class
+                case 8  : // String
+                    // Data is 2 bytes long
+                    cfile.skipBytes(2);
+                    break;
+                case 3  : // Integer
+                case 4  : // Float
+                case 9  : // FieldRef
+                case 10 : // MethodRef
+                case 11 : // InterfaceMethodRef
+                case 12 : // Name and Type
+                    // Data is 4 bytes long
+                    cfile.skipBytes(4);
+                    break;
+                case 5  : // Long
+                case 6  : // Double
+                    // Data is 8 bytes long
+                    cfile.skipBytes(8);
+                    break;
+                case 1  : // Utf8
+                    v2 = cfile.readUnsignedShort(); // Read buffer size
+                    cfile.skipBytes(v2); // Skip buffer
+                    break;
+                default :
+                    throw new Exception("Unexpected tag in CPool: [" + tag + "] at "
+                            + Long.toHexString(cfile.getFilePointer()));
+            }
+        }
+        // System.out.println();
+
+        cfile.skipBytes(6); // Access flags, this_class and super_class
+        v1 = cfile.readUnsignedShort(); // Number of interfaces
+        // System.out.println("Interfaces: " + v1);
+        cfile.skipBytes(3 * v1); // Each interface_info record is 3 bytes long
+        v1 = cfile.readUnsignedShort(); // Number of fields
+        // System.out.println("Fields: " + v1);
+        // Exhaust the fields table
+        for (; v1 > 0; v1--) {
+            // System.out.print(".");
+            cfile.skipBytes(6); // Skip access_flags, name_index and descriptor_index
+            v2 = cfile.readUnsignedShort(); // Field attributes count
+            if (v2 > 0) {
+                // This field has some attributes - suits our needs
+                // System.out.println();
+                return cfile.getFilePointer();
+            }
+        }
+        // System.out.println();
+        v1 = cfile.readUnsignedShort(); // Number of methods
+        // System.out.println("Methods: " + v1);
+        // Exhaust the methods table
+        for (; v1 > 0; v1--) {
+            // System.out.print(".");
+            cfile.skipBytes(6); // Skip access_flags, name_index and descriptor_index
+            v2 = cfile.readUnsignedShort(); // Method attributes count
+            if (v2 > 0) {
+                // This method got attributes - Ok with us,
+                // return position of the first one
+                // System.out.println();
+                return cfile.getFilePointer();
+            }
+        }
+        // System.out.println();
+        // Class attributes section
+        v1 = cfile.readUnsignedShort(); // Counts of attributes in class
+        if (v1 > 0) {
+            // Class has some attributes, return position of the first one
+            return cfile.getFilePointer();
+        }
+        // Bummer! No attributes in the entire class file. Not fair!
+        return -1L;
+    }
+}