1 | /******************************************************************************* |
---|---|
2 | * Copyright (c) 2016, 2017 IBM Corporation and others. |
3 | * |
4 | * This program and the accompanying materials |
5 | * are made available under the terms of the Eclipse Public License 2.0 |
6 | * which accompanies this distribution, and is available at |
7 | * https://www.eclipse.org/legal/epl-2.0/ |
8 | * |
9 | * SPDX-License-Identifier: EPL-2.0 |
10 | * |
11 | * IBM Corporation - initial API and implementation |
12 | *******************************************************************************/ |
13 | package org.eclipse.jdt.core.dom; |
14 | |
15 | import java.util.List; |
16 | |
17 | /** |
18 | * Abstract base class of AST nodes that represent exports and opens directives (added in JLS9 API). |
19 | * |
20 | * <pre> |
21 | * ModulePackageAccess: |
22 | * {@link ExportsDirective} |
23 | * {@link OpensDirective} |
24 | * </pre> |
25 | * |
26 | * @noextend This class is not intended to be subclassed by clients. |
27 | * @since 3.14 |
28 | */ |
29 | @SuppressWarnings({"rawtypes", "unchecked"}) |
30 | public abstract class ModulePackageAccess extends ModuleDirective { |
31 | |
32 | /** |
33 | * The package name; lazily initialized; defaults to a unspecified, |
34 | * legal Java identifier. |
35 | */ |
36 | protected Name name = null; |
37 | |
38 | /** |
39 | * The target modules |
40 | * (element type: {@link Name}). |
41 | * Defaults to an empty list. (see constructor) |
42 | */ |
43 | protected ASTNode.NodeList modules = null; |
44 | |
45 | /** |
46 | * Returns structural property descriptor for the "modules" property |
47 | * of this node (element type: {@link Name}). |
48 | * |
49 | * @return the property descriptor |
50 | */ |
51 | abstract ChildListPropertyDescriptor internalModulesProperty(); |
52 | |
53 | /** |
54 | * Returns structural property descriptor for the "name" property |
55 | * of this node (child type: {@link Name}). |
56 | * |
57 | * @return the property descriptor |
58 | */ |
59 | abstract ChildPropertyDescriptor internalNameProperty(); |
60 | |
61 | /** |
62 | * Returns structural property descriptor for the "name" property |
63 | * of this node (child type: {@link Name}). |
64 | * |
65 | * @return the property descriptor |
66 | */ |
67 | public final ChildPropertyDescriptor getNameProperty() { |
68 | return internalNameProperty(); |
69 | } |
70 | |
71 | /** |
72 | * Creates and returns a structural property descriptor for the |
73 | * "name" property declared on the given concrete node type (child type: {@link Name}). |
74 | * |
75 | * @return the property descriptor |
76 | */ |
77 | static final ChildPropertyDescriptor internalNamePropertyFactory(Class nodeClass) { |
78 | return new ChildPropertyDescriptor(nodeClass, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ |
79 | } |
80 | |
81 | /** |
82 | * Creates and returns a structural property descriptor for the |
83 | * "modules" property declared on the given concrete node type (element type: {@link Name}). |
84 | * |
85 | * @return the property descriptor |
86 | */ |
87 | static final ChildListPropertyDescriptor internalModulesPropertyFactory(Class nodeClass) { |
88 | return new ChildListPropertyDescriptor(nodeClass, "modules", Name.class, NO_CYCLE_RISK); //$NON-NLS-1$ |
89 | } |
90 | |
91 | /** |
92 | * <p> |
93 | * N.B. This constructor is package-private; all subclasses must be |
94 | * declared in the same package; clients are unable to declare |
95 | * additional subclasses. |
96 | * </p> |
97 | * |
98 | * @param ast the AST that is to own this node |
99 | */ |
100 | ModulePackageAccess(AST ast) { |
101 | super(ast); |
102 | this.modules = new ASTNode.NodeList(internalModulesProperty()); |
103 | } |
104 | |
105 | @Override |
106 | final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { |
107 | if (property == internalNameProperty()) { |
108 | if (get) { |
109 | return getName(); |
110 | } else { |
111 | setName((Name) child); |
112 | return null; |
113 | } |
114 | } |
115 | // allow default implementation to flag the error |
116 | return super.internalGetSetChildProperty(property, get, child); |
117 | } |
118 | |
119 | @Override |
120 | final List internalGetChildListProperty(ChildListPropertyDescriptor property) { |
121 | if (property == internalModulesProperty()) { |
122 | return modules(); |
123 | } |
124 | // allow default implementation to flag the error |
125 | return super.internalGetChildListProperty(property); |
126 | } |
127 | |
128 | /** |
129 | * Returns the name of the package. |
130 | * |
131 | * @return the package name node |
132 | */ |
133 | public Name getName() { |
134 | if (this.name == null) { |
135 | // lazy init must be thread-safe for readers |
136 | synchronized (this) { |
137 | if (this.name == null) { |
138 | preLazyInit(); |
139 | this.name =this.ast.newQualifiedName( |
140 | new SimpleName(this.ast), new SimpleName(this.ast)); |
141 | ChildPropertyDescriptor p = internalNameProperty(); |
142 | postLazyInit(this.name, p); |
143 | } |
144 | } |
145 | } |
146 | return this.name; |
147 | } |
148 | |
149 | /** |
150 | * Sets the name of the package to the given name. |
151 | * |
152 | * @param name the new package name |
153 | * @exception IllegalArgumentException if: |
154 | * <ul> |
155 | * <li>the node belongs to a different AST</li> |
156 | * <li>the node already has a parent</li> |
157 | * </ul> |
158 | */ |
159 | public void setName(Name name) { |
160 | if (name == null) { |
161 | throw new IllegalArgumentException(); |
162 | } |
163 | ASTNode oldChild = this.name; |
164 | ChildPropertyDescriptor p = internalNameProperty(); |
165 | preReplaceChild(oldChild, name, p); |
166 | this.name = name; |
167 | postReplaceChild(oldChild, name, p); |
168 | } |
169 | |
170 | /** |
171 | * Returns the live ordered list of target modules for this |
172 | * directive. |
173 | * |
174 | * @return the live list of target modules |
175 | * (element type: {@link Name}) |
176 | */ |
177 | public List modules() { |
178 | return this.modules; |
179 | } |
180 | |
181 | protected ASTNode cloneHelper(AST target, ModulePackageAccess result) { |
182 | result.setSourceRange(getStartPosition(), getLength()); |
183 | result.setName((Name) getName().clone(target)); |
184 | result.modules().addAll(ASTNode.copySubtrees(target, modules())); |
185 | return result; |
186 | } |
187 | |
188 | protected void acceptVisitChildren(boolean visitChildren, ASTVisitor visitor) { |
189 | if (visitChildren) { |
190 | acceptChild(visitor, getName()); |
191 | acceptChildren(visitor, this.modules); |
192 | } |
193 | } |
194 | |
195 | @Override |
196 | int memSize() { |
197 | return BASE_NODE_SIZE + 2 * 4; |
198 | } |
199 | |
200 | @Override |
201 | int treeSize() { |
202 | return |
203 | memSize() |
204 | + (this.name == null ? 0 : getName().treeSize()) |
205 | + this.modules.listSize(); |
206 | } |
207 | } |
208 |
Members