1 /*
2  * Copyright (c) 2009, 2019, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.tools.javac.code;
27 
28 import java.util.Collections;
29 import java.util.EnumSet;
30 import java.util.Locale;
31 import java.util.Set;
32 
33 import javax.lang.model.element.ModuleElement;
34 import javax.lang.model.element.ModuleElement.DirectiveVisitor;
35 
36 import com.sun.tools.javac.api.Messages;
37 import com.sun.tools.javac.code.Symbol.ClassSymbol;
38 import com.sun.tools.javac.code.Symbol.ModuleSymbol;
39 import com.sun.tools.javac.code.Symbol.PackageSymbol;
40 import com.sun.tools.javac.util.DefinedBy;
41 import com.sun.tools.javac.util.DefinedBy.Api;
42 import com.sun.tools.javac.util.List;
43 
44 
45 /**
46  *  Root class for the directives that may appear in module compilation units.
47  *
48  *  <p><b>This is NOT part of any supported API.
49  *  If you write code that depends on this, you do so at your own risk.
50  *  This code and its internal interfaces are subject to change or
51  *  deletion without notice.</b>
52  */
53 public abstract class Directive implements ModuleElement.Directive {
54 
55     /** Flags for RequiresDirective. */
56     public enum RequiresFlag {
57         TRANSITIVE(0x0020),
58         STATIC_PHASE(0x0040),
59         SYNTHETIC(0x1000),
60         MANDATED(0x8000),
61         EXTRA(0x10000);
62 
63         // overkill? move to ClassWriter?
value(Set<RequiresFlag> s)64         public static int value(Set<RequiresFlag> s) {
65             int v = 0;
66             for (RequiresFlag f: s)
67                 v |= f.value;
68             return v;
69         }
70 
RequiresFlag(int value)71         RequiresFlag(int value) {
72             this.value = value;
73         }
74 
75         public final int value;
76 
77         @Override
toString()78         public String toString() {
79             return String.format("ACC_%s (0x%04x", name(), value);
80         }
81     }
82 
83     /** Flags for ExportsDirective. */
84     public enum ExportsFlag {
85         SYNTHETIC(0x1000),
86         MANDATED(0x8000);
87 
88         // overkill? move to ClassWriter?
value(Set<ExportsFlag> s)89         public static int value(Set<ExportsFlag> s) {
90             int v = 0;
91             for (ExportsFlag f: s)
92                 v |= f.value;
93             return v;
94         }
95 
ExportsFlag(int value)96         ExportsFlag(int value) {
97             this.value = value;
98         }
99 
100         public final int value;
101     }
102 
103     /**
104      * 'exports' Package ';'
105      * 'exports' Package 'to' ModuleList ';'
106      */
107     public static class ExportsDirective extends Directive
108             implements ModuleElement.ExportsDirective {
109         public final PackageSymbol packge;
110         public final List<ModuleSymbol> modules;
111         public final Set<ExportsFlag> flags;
112 
ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules)113         public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
114             this(packge, modules, EnumSet.noneOf(ExportsFlag.class));
115         }
116 
ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<ExportsFlag> flags)117         public ExportsDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<ExportsFlag> flags) {
118             this.packge = packge;
119             this.modules = modules;
120             this.flags = flags;
121         }
122 
123         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getKind()124         public ModuleElement.DirectiveKind getKind() {
125             return ModuleElement.DirectiveKind.EXPORTS;
126         }
127 
128         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getPackage()129         public PackageSymbol getPackage() {
130             return packge;
131         }
132 
133         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getTargetModules()134         public java.util.List<ModuleSymbol> getTargetModules() {
135             return modules == null
136                     ? null
137                     : Collections.unmodifiableList(modules);
138         }
139 
140         @Override
toString()141         public String toString() {
142             if (modules == null)
143                 return "Exports[" + packge + "]";
144             else
145                 return "Exports[" + packge + ":" + modules + "]";
146         }
147 
148         @Override @DefinedBy(Api.LANGUAGE_MODEL)
accept(DirectiveVisitor<R, P> v, P p)149         public <R, P> R accept(DirectiveVisitor<R, P> v, P p) {
150             return v.visitExports(this, p);
151         }
152     }
153 
154     /** Flags for OpensDirective. */
155     public enum OpensFlag {
156         SYNTHETIC(0x1000),
157         MANDATED(0x8000);
158 
159         // overkill? move to ClassWriter?
value(Set<OpensFlag> s)160         public static int value(Set<OpensFlag> s) {
161             int v = 0;
162             for (OpensFlag f: s)
163                 v |= f.value;
164             return v;
165         }
166 
OpensFlag(int value)167         OpensFlag(int value) {
168             this.value = value;
169         }
170 
171         public final int value;
172     }
173 
174     /**
175      * 'opens' Package ';'
176      * 'opens' Package 'to' ModuleList ';'
177      */
178     public static class OpensDirective extends Directive
179             implements ModuleElement.OpensDirective {
180         public final PackageSymbol packge;
181         public final List<ModuleSymbol> modules;
182         public final Set<OpensFlag> flags;
183 
OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules)184         public OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules) {
185             this(packge, modules, EnumSet.noneOf(OpensFlag.class));
186         }
187 
OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<OpensFlag> flags)188         public OpensDirective(PackageSymbol packge, List<ModuleSymbol> modules, Set<OpensFlag> flags) {
189             this.packge = packge;
190             this.modules = modules;
191             this.flags = flags;
192         }
193 
194         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getKind()195         public ModuleElement.DirectiveKind getKind() {
196             return ModuleElement.DirectiveKind.OPENS;
197         }
198 
199         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getPackage()200         public PackageSymbol getPackage() {
201             return packge;
202         }
203 
204         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getTargetModules()205         public java.util.List<ModuleSymbol> getTargetModules() {
206             return modules == null
207                     ? null
208                     : Collections.unmodifiableList(modules);
209         }
210 
211         @Override
toString()212         public String toString() {
213             if (modules == null)
214                 return "Opens[" + packge + "]";
215             else
216                 return "Opens[" + packge + ":" + modules + "]";
217         }
218 
219         @Override @DefinedBy(Api.LANGUAGE_MODEL)
accept(DirectiveVisitor<R, P> v, P p)220         public <R, P> R accept(DirectiveVisitor<R, P> v, P p) {
221             return v.visitOpens(this, p);
222         }
223     }
224 
225     /**
226      * 'provides' ServiceName 'with' QualifiedIdentifier ';'
227      */
228     public static class ProvidesDirective extends Directive
229             implements ModuleElement.ProvidesDirective {
230         public final ClassSymbol service;
231         public final List<ClassSymbol> impls;
232 
ProvidesDirective(ClassSymbol service, List<ClassSymbol> impls)233         public ProvidesDirective(ClassSymbol service, List<ClassSymbol> impls) {
234             this.service = service;
235             this.impls = impls;
236         }
237 
238         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getKind()239         public ModuleElement.DirectiveKind getKind() {
240             return ModuleElement.DirectiveKind.PROVIDES;
241         }
242 
243         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getService()244         public ClassSymbol getService() {
245             return service;
246         }
247 
248         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getImplementations()249         public List<ClassSymbol> getImplementations() {
250             return impls;
251         }
252 
253         @Override
toString()254         public String toString() {
255             return "Provides[" + service + "," + impls + "]";
256         }
257 
258         @Override @DefinedBy(Api.LANGUAGE_MODEL)
accept(DirectiveVisitor<R, P> v, P p)259         public <R, P> R accept(DirectiveVisitor<R, P> v, P p) {
260             return v.visitProvides(this, p);
261         }
262 
263         // TODO: delete?
264         @Override
equals(Object obj)265         public boolean equals(Object obj) {
266             if (!(obj instanceof ProvidesDirective)) {
267                 return false;
268             }
269             ProvidesDirective other = (ProvidesDirective)obj;
270             return service == other.service && impls.equals(other.impls);
271         }
272 
273         // TODO: delete?
274         @Override
hashCode()275         public int hashCode() {
276             return service.hashCode() * 31 + impls.hashCode() * 37;
277         }
278     }
279 
280     /**
281      * 'requires' ('static' | 'transitive')* ModuleName ';'
282      */
283     public static class RequiresDirective extends Directive
284             implements ModuleElement.RequiresDirective {
285         public final ModuleSymbol module;
286         public final Set<RequiresFlag> flags;
287 
RequiresDirective(ModuleSymbol module)288         public RequiresDirective(ModuleSymbol module) {
289             this(module, EnumSet.noneOf(RequiresFlag.class));
290         }
291 
RequiresDirective(ModuleSymbol module, Set<RequiresFlag> flags)292         public RequiresDirective(ModuleSymbol module, Set<RequiresFlag> flags) {
293             this.module = module;
294             this.flags = flags;
295         }
296 
297         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getKind()298         public ModuleElement.DirectiveKind getKind() {
299             return ModuleElement.DirectiveKind.REQUIRES;
300         }
301 
302         @Override @DefinedBy(Api.LANGUAGE_MODEL)
isStatic()303         public boolean isStatic() {
304             return flags.contains(RequiresFlag.STATIC_PHASE);
305         }
306 
307         @Override @DefinedBy(Api.LANGUAGE_MODEL)
isTransitive()308         public boolean isTransitive() {
309             return flags.contains(RequiresFlag.TRANSITIVE);
310         }
311 
312         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getDependency()313         public ModuleSymbol getDependency() {
314             return module;
315         }
316 
317         @Override
toString()318         public String toString() {
319             return "Requires[" + flags + "," + module + "]";
320         }
321 
322         @Override @DefinedBy(Api.LANGUAGE_MODEL)
accept(DirectiveVisitor<R, P> v, P p)323         public <R, P> R accept(DirectiveVisitor<R, P> v, P p) {
324             return v.visitRequires(this, p);
325         }
326     }
327 
328     /**
329      * 'uses' ServiceName ';'
330      */
331     public static class UsesDirective extends Directive
332             implements ModuleElement.UsesDirective {
333         public final ClassSymbol service;
334 
UsesDirective(ClassSymbol service)335         public UsesDirective(ClassSymbol service) {
336             this.service = service;
337         }
338 
339         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getKind()340         public ModuleElement.DirectiveKind getKind() {
341             return ModuleElement.DirectiveKind.USES;
342         }
343 
344         @Override @DefinedBy(Api.LANGUAGE_MODEL)
getService()345         public ClassSymbol getService() {
346             return service;
347         }
348 
349         @Override
toString()350         public String toString() {
351             return "Uses[" + service + "]";
352         }
353 
354         @Override @DefinedBy(Api.LANGUAGE_MODEL)
accept(DirectiveVisitor<R, P> v, P p)355         public <R, P> R accept(DirectiveVisitor<R, P> v, P p) {
356             return v.visitUses(this, p);
357         }
358 
359         // TODO: delete?
360         @Override
equals(Object obj)361         public boolean equals(Object obj) {
362             if (!(obj instanceof UsesDirective)) {
363                 return false;
364             }
365             UsesDirective other = (UsesDirective)obj;
366             return service == other.service;
367         }
368 
369         // TODO: delete?
370         @Override
hashCode()371         public int hashCode() {
372             return service.hashCode() * 31;
373         }
374     }
375 }
376