1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8242293 8246774 27 * @summary allow for local interfaces and enums plus nested records, interfaces and enums 28 * @enablePreview 29 * @library /tools/javac/lib 30 * @modules jdk.compiler/com.sun.tools.javac.api 31 * jdk.compiler/com.sun.tools.javac.file 32 * jdk.compiler/com.sun.tools.javac.util 33 * @build combo.ComboTestHelper 34 * @run main LocalStaticDeclarations 35 */ 36 37 import javax.lang.model.element.Element; 38 import javax.tools.Diagnostic; 39 import javax.tools.JavaFileObject; 40 41 import com.sun.tools.javac.util.Assert; 42 43 import com.sun.tools.javac.api.ClientCodeWrapper; 44 import com.sun.tools.javac.util.JCDiagnostic; 45 import com.sun.tools.javac.util.List; 46 import combo.ComboInstance; 47 import combo.ComboParameter; 48 import combo.ComboTask; 49 import combo.ComboTask.Result; 50 import combo.ComboTestHelper; 51 52 /** this test checks two thinks: 53 * 1 - that static declarations are allowed inside inner classes 54 * 2 - and in addtion that non-static variables can't be captured 55 * by static contexts 56 */ 57 58 public class LocalStaticDeclarations extends ComboInstance<LocalStaticDeclarations> { 59 60 static final String sourceTemplate = 61 """ 62 import java.lang.annotation.*; 63 class Test { 64 int INSTANCE_FIELD = 0; 65 static int STATIC_FIELD = 0; 66 // instance initializer 67 { 68 int LOCAL_VARIABLE = 0; 69 #{CONTAINER} 70 } 71 Test() { 72 int LOCAL_VARIABLE = 0; 73 #{CONTAINER} 74 } 75 void m() { 76 int LOCAL_VARIABLE = 0; 77 #{CONTAINER} 78 } 79 static void foo() { 80 int LOCAL_VARIABLE = 0; 81 #{CONTAINER} 82 } 83 } 84 """; 85 86 enum Container implements ComboParameter { 87 NO_CONTAINER("#{STATIC_LOCAL}"), 88 INTERFACE("interface CI { #{STATIC_LOCAL} }"), 89 ANONYMOUS( 90 """ 91 new Object() { 92 // instance initializer 93 { 94 #{STATIC_LOCAL} 95 } 96 97 void m() { 98 #{STATIC_LOCAL} 99 } 100 }; 101 """ 102 ), 103 RECORD("record CR() { #{STATIC_LOCAL} }"), 104 CLASS("class CC { #{STATIC_LOCAL} }"), 105 ENUM("enum CE { CE1; #{STATIC_LOCAL} }"), 106 LAMBDA("Runnable run = () -> { #{STATIC_LOCAL} };"); 107 108 String container; 109 110 Container(String container) { 111 this.container = container; 112 } 113 114 public String expand(String optParameter) { 115 return container; 116 } 117 } 118 119 enum StaticLocalDecl implements ComboParameter { 120 ENUM("enum E { E1; #{MEMBER} }"), 121 RECORD("record R() { #{MEMBER} }"), 122 INTERFACE("interface I { #{MEMBER} }"); 123 124 String localDecl; 125 126 StaticLocalDecl(String localDecl) { 127 this.localDecl = localDecl; 128 } 129 130 public String expand(String optParameter) { 131 return localDecl; 132 } 133 } 134 135 enum Member implements ComboParameter { 136 METHOD("int foo() { return #{EXPR}; }"), 137 DEFAULT_METHOD("default int foo() { return #{EXPR}; }"); 138 139 String member; 140 141 Member(String member) { 142 this.member = member; 143 } 144 145 public String expand(String optParameter) { 146 return member; 147 } 148 } 149 150 enum Expression implements ComboParameter { 151 LITERAL("1"), 152 STATIC_FIELD("STATIC_FIELD"), 153 LOCAL_VARIABLE("LOCAL_VARIABLE"), 154 INSTANCE_FIELD("INSTANCE_FIELD"); 155 156 String expr; 157 158 Expression(String expr) { 159 this.expr = expr; 160 } 161 162 public String expand(String optParameter) { 163 return expr; 164 } 165 } 166 167 public static void main(String... args) throws Exception { 168 new combo.ComboTestHelper<LocalStaticDeclarations>() 169 .withFilter(LocalStaticDeclarations::notTriviallyIncorrect) 170 .withDimension("CONTAINER", (x, t) -> { x.container = t; }, Container.values()) 171 .withDimension("STATIC_LOCAL", (x, t) -> { x.decl = t; }, StaticLocalDecl.values()) 172 .withDimension("MEMBER", (x, t) -> { x.member = t; }, Member.values()) 173 .withDimension("EXPR", (x, expr) -> x.expr = expr, Expression.values()) 174 .run(LocalStaticDeclarations::new); 175 } 176 177 Container container; 178 StaticLocalDecl decl; 179 Member member; 180 Expression expr; 181 182 @Override 183 public void doWork() throws Throwable { 184 newCompilationTask() 185 .withSourceFromTemplate("Test", sourceTemplate) 186 .generate(this::check); 187 } 188 189 boolean notTriviallyIncorrect() { 190 return decl == StaticLocalDecl.INTERFACE && member == Member.DEFAULT_METHOD || 191 decl != StaticLocalDecl.INTERFACE && member == Member.METHOD; 192 } 193 194 void check(ComboTask.Result<Iterable<? extends JavaFileObject>> result) { 195 if (shouldFail()) { 196 Assert.check(result.hasErrors(), "unexpected compilation\n" + result.compilationInfo()); 197 if (!expectedDiagFound(result)) { 198 fail("test failing with unexpected error message\n" + result.compilationInfo()); 199 } 200 } else { 201 Assert.check(!result.hasErrors(), result.compilationInfo()); 202 } 203 } 204 205 boolean shouldFail() { 206 return (expr == Expression.LOCAL_VARIABLE || expr == Expression.INSTANCE_FIELD); 207 } 208 209 boolean acceptableExpr() { 210 return (expr == Expression.LITERAL || expr == Expression.STATIC_FIELD); 211 } 212 213 boolean expectedDiagFound(ComboTask.Result<Iterable<? extends JavaFileObject>> result) { 214 if (expr == Expression.LOCAL_VARIABLE || expr == Expression.INSTANCE_FIELD) { 215 return result.containsKey("compiler.err.non-static.cant.be.ref"); 216 } 217 return false; 218 } 219 }