001    /* Copyright (c) 2005-2008, Torbjorn Ekman
002     * All rights reserved.
003     *
004     * Redistribution and use in source and binary forms, with or without
005     * modification, are permitted provided that the following conditions are met:
006     *
007     * 1. Redistributions of source code must retain the above copyright notice,
008     * this list of conditions and the following disclaimer.
009     *
010     * 2. Redistributions in binary form must reproduce the above copyright notice,
011     * this list of conditions and the following disclaimer in the documentation
012     * and/or other materials provided with the distribution.
013     *
014     * 3. Neither the name of the copyright holder nor the names of its
015     * contributors may be used to endorse or promote products derived from this
016     * software without specific prior written permission.
017     *
018     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
022     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028     * POSSIBILITY OF SUCH DAMAGE.
029     */
030    
031    aspect Modifiers {
032      void ASTNode.checkModifiers() {
033      }
034    
035      syn lazy boolean TypeDecl.hasAbstract() = false;
036    
037      syn lazy Collection TypeDecl.unimplementedMethods() = Collections.EMPTY_LIST;
038      eq ClassDecl.unimplementedMethods() {
039        Collection c = new ArrayList();
040        for (Iterator iter = interfacesMethodsIterator(); iter.hasNext(); ) {
041          MethodDecl m = (MethodDecl) iter.next();
042          boolean implemented = false;
043          SimpleSet set = (SimpleSet) localMethodsSignature(m.signature());
044          if (set.size() == 1) {
045            MethodDecl n = (MethodDecl) set.iterator().next();
046            if (!n.isAbstract()) {
047              implemented = true;
048            }
049          }
050          if (!implemented) {
051            set = ancestorMethods(m.signature());
052            for (Iterator i2 = set.iterator(); i2.hasNext(); ) {
053              MethodDecl n = (MethodDecl) i2.next();
054              if (!n.isAbstract() && n.isPublic()) {
055                implemented = true;
056                break;
057              }
058            }
059          }
060          if (!implemented) {
061            c.add(m);
062          }
063        }
064    
065        if (hasSuperclass()) {
066          for (Iterator iter = superclass().unimplementedMethods().iterator(); iter.hasNext(); ) {
067            MethodDecl m = (MethodDecl) iter.next();
068            SimpleSet set = (SimpleSet) localMethodsSignature(m.signature());
069            if (set.size() == 1) {
070              MethodDecl n = (MethodDecl) set.iterator().next();
071              if (n.isAbstract() || !n.overrides(m)) {
072                c.add(m);
073              }
074            } else {
075              c.add(m);
076            }
077          }
078        }
079    
080        for (Iterator iter = localMethodsIterator(); iter.hasNext(); ) {
081          MethodDecl m = (MethodDecl) iter.next();
082          if (m.isAbstract()) {
083            c.add(m);
084          }
085        }
086        return c;
087      }
088    
089      eq ClassDecl.hasAbstract() = !unimplementedMethods().isEmpty();
090    
091      public void TypeDecl.checkModifiers() {
092        super.checkModifiers();
093        // 8.1.1
094        if (isPublic() && !isTopLevelType() && !isMemberType()) {
095          error("public pertains only to top level types and member types");
096        }
097    
098        // 8.1.1
099        if ((isProtected() || isPrivate()) && !(isMemberType() && enclosingType().isClassDecl())) {
100          error("protected and private may only be used on member types within a directly enclosing class declaration");
101        }
102    
103        // 8.1.1
104        if (isStatic() && !isMemberType()) {
105          error("static pertains only to member types");
106        }
107    
108    
109        // 8.4.3.1
110        // 8.1.1.1
111        if (!isAbstract() && hasAbstract()) {
112          StringBuilder sb = new StringBuilder();
113          sb.append("" + name() + " is not declared abstract but contains abstract members: \n");
114          for (Iterator iter = unimplementedMethods().iterator(); iter.hasNext(); ) {
115            MethodDecl m = (MethodDecl) iter.next();
116            sb.append("  " + m.signature() + " in " + m.hostType().typeName() + "\n");
117          }
118          error(sb.toString());
119        }
120      }
121    
122     public void ClassDecl.checkModifiers() {
123        super.checkModifiers();
124        // 8.1.1.2 final Classes
125        TypeDecl typeDecl = superclass();
126        if (!typeDecl.isUnknown() && typeDecl.isFinal()) {
127          errorf("class %s may not extend final class %s", fullName(), typeDecl.fullName());
128        }
129    
130      }
131    
132      public void InterfaceDecl.checkModifiers() {
133        super.checkModifiers();
134      }
135    
136      public void ConstructorDecl.checkModifiers() {
137        super.checkModifiers();
138      }
139    
140      public void FieldDeclaration.checkModifiers() {
141        super.checkModifiers();
142        if (hostType().isInterfaceDecl()) {
143          if (isProtected()) {
144            error("an interface field may not be protected");
145          }
146          if (isPrivate()) {
147            error("an interface field may not be private");
148          }
149          if (isTransient()) {
150            error("an interface field may not be transient");
151          }
152          if (isVolatile()) {
153            error("an interface field may not be volatile");
154          }
155        }
156      }
157    
158      // 8.4.3
159      public void MethodDecl.checkModifiers() {
160        super.checkModifiers();
161        if (hostType().isClassDecl()) {
162          // 8.4.3.1
163          if (isAbstract() && !hostType().isAbstract()) {
164            error("class must be abstract to include abstract methods");
165          }
166          // 8.4.3.1
167          if (isAbstract() && isPrivate()) {
168            error("method may not be abstract and private");
169          }
170          // 8.4.3.1
171          // 8.4.3.2
172          if (isAbstract() && isStatic()) {
173            error("method may not be abstract and static");
174          }
175          if (isAbstract() && isSynchronized()) {
176            error("method may not be abstract and synchronized");
177          }
178          // 8.4.3.4
179          if (isAbstract() && isNative()) {
180            error("method may not be abstract and native");
181          }
182          if (isAbstract() && isStrictfp()) {
183            error("method may not be abstract and strictfp");
184          }
185          if (isNative() && isStrictfp()) {
186            error("method may not be native and strictfp");
187          }
188        }
189        if (hostType().isInterfaceDecl()) {
190          // 9.4
191          if (isStatic()) {
192            errorf("interface method %s in %s may not be static", signature(), hostType().typeName());
193          }
194          if (isStrictfp()) {
195            errorf("interface method %s in %s may not be strictfp", signature(), hostType().typeName());
196          }
197          if (isNative()) {
198            errorf("interface method %s in %s may not be native", signature(), hostType().typeName());
199          }
200          if (isSynchronized()) {
201            errorf("interface method %s in %s may not be synchronized", signature(),
202                hostType().typeName());
203          }
204          if (isProtected()) {
205            errorf("interface method %s in %s may not be protected", signature(),
206                hostType().typeName());
207          }
208          if (isPrivate()) {
209            errorf("interface method %s in %s may not be private", signature(), hostType().typeName());
210          } else if (isFinal()) {
211            errorf("interface method %s in %s may not be final", signature(), hostType().typeName());
212          }
213        }
214      }
215    
216      // 8.1.2
217      public void StaticInitializer.checkModifiers() {
218        super.checkModifiers();
219        if (hostType().isInnerClass()) {
220          error("*** Inner classes may not declare static initializers");
221        }
222      }
223    
224      // 8.1.2
225      public void MemberInterfaceDecl.checkModifiers() {
226        super.checkModifiers();
227        if (hostType().isInnerClass()) {
228          error("*** Inner classes may not declare member interfaces");
229        }
230      }
231    
232      public void MemberDecl.checkModifiers() {
233        if (!isSynthetic()) {
234          super.checkModifiers();
235          if (isStatic() && hostType().isInnerClass() && !isConstant()) {
236            error("*** Inner classes may not declare static members, unless they are compile-time constant fields");
237          }
238        }
239      }
240    
241      syn lazy boolean TypeDecl.isPublic() = getModifiers().isPublic() || isMemberType() && enclosingType().isInterfaceDecl();
242      //eq InterfaceDecl.isPublic() = !isProtected() && !isPrivate();
243      syn boolean TypeDecl.isPrivate() = getModifiers().isPrivate();
244      syn boolean TypeDecl.isProtected() = getModifiers().isProtected();
245      syn boolean TypeDecl.isAbstract() = getModifiers().isAbstract();
246      eq InterfaceDecl.isAbstract() = true;
247      syn lazy boolean TypeDecl.isStatic() = getModifiers().isStatic() || isMemberType() && enclosingType().isInterfaceDecl();
248      // 8.5.2
249      eq InterfaceDecl.isStatic() = getModifiers().isStatic() || isMemberType();
250      syn boolean TypeDecl.isFinal() = getModifiers().isFinal();
251      syn boolean TypeDecl.isStrictfp() = getModifiers().isStrictfp();
252    
253      syn boolean TypeDecl.isSynthetic() = getModifiers().isSynthetic();
254    
255      syn boolean MemberDecl.isSynthetic() = false;
256      eq MethodDecl.isSynthetic() = getModifiers().isSynthetic();
257      eq FieldDeclaration.isSynthetic() = getModifiers().isSynthetic();
258      syn boolean ConstructorDecl.isSynthetic() = getModifiers().isSynthetic();
259    
260      syn boolean VariableDeclaration.isSynthetic() = getModifiers().isSynthetic();
261      syn boolean ParameterDeclaration.isSynthetic() = getModifiers().isSynthetic();
262    
263      syn boolean MemberDecl.isStatic();
264    
265      syn boolean MethodDecl.isPublic() = getModifiers().isPublic() || hostType().isInterfaceDecl();
266      syn boolean MethodDecl.isPrivate() = getModifiers().isPrivate();
267      syn boolean MethodDecl.isProtected() = getModifiers().isProtected();
268      syn boolean MethodDecl.isAbstract() = getModifiers().isAbstract() || hostType().isInterfaceDecl();
269      syn boolean MethodDecl.isStatic() = getModifiers().isStatic();
270      // 8.4.3.3
271      syn boolean MethodDecl.isFinal() = getModifiers().isFinal() || hostType().isFinal() || isPrivate();
272      syn boolean MethodDecl.isSynchronized() = getModifiers().isSynchronized();
273      syn boolean MethodDecl.isNative() = getModifiers().isNative();
274      syn boolean MethodDecl.isStrictfp() = getModifiers().isStrictfp();
275    
276      syn boolean ConstructorDecl.isPublic() = getModifiers().isPublic();
277      syn boolean ConstructorDecl.isPrivate() = getModifiers().isPrivate();
278      syn boolean ConstructorDecl.isProtected() = getModifiers().isProtected();
279    
280      syn boolean FieldDeclaration.isPublic() = getModifiers().isPublic() || hostType().isInterfaceDecl();
281      syn boolean FieldDeclaration.isPrivate() = getModifiers().isPrivate();
282      syn boolean FieldDeclaration.isProtected() = getModifiers().isProtected();
283      syn boolean FieldDeclaration.isStatic() = getModifiers().isStatic() || hostType().isInterfaceDecl();
284      syn boolean FieldDecl.isStatic() = getModifiers().isStatic();
285      syn boolean FieldDeclaration.isFinal() = getModifiers().isFinal() || hostType().isInterfaceDecl();
286      syn boolean FieldDeclaration.isTransient() = getModifiers().isTransient();
287      syn boolean FieldDeclaration.isVolatile() = getModifiers().isVolatile();
288    
289      eq MemberTypeDecl.isStatic() = typeDecl().isStatic();
290    
291      // 8.1.1 & 9.1.1
292      eq TypeDecl.getModifiers().mayBePublic() = true;
293      eq TypeDecl.getModifiers().mayBeProtected() = true;
294      eq TypeDecl.getModifiers().mayBePrivate() = true;
295      eq TypeDecl.getModifiers().mayBeAbstract() = true;
296      eq TypeDecl.getModifiers().mayBeStatic() = true;
297      eq TypeDecl.getModifiers().mayBeStrictfp() = true;
298    
299      // 8.1.1
300      eq ClassDecl.getModifiers().mayBeFinal() = true;
301    
302      // 8.3.1
303      eq FieldDeclaration.getModifiers().mayBePublic() = true;
304      eq FieldDeclaration.getModifiers().mayBeProtected() = true;
305      eq FieldDeclaration.getModifiers().mayBePrivate() = true;
306      eq FieldDeclaration.getModifiers().mayBeStatic() = true;
307      eq FieldDeclaration.getModifiers().mayBeFinal() = true;
308      eq FieldDeclaration.getModifiers().mayBeTransient() = true;
309      eq FieldDeclaration.getModifiers().mayBeVolatile() = true;
310    
311      // 8.4.3
312      eq MethodDecl.getModifiers().mayBePublic() = true;
313      eq MethodDecl.getModifiers().mayBeProtected() = true;
314      eq MethodDecl.getModifiers().mayBePrivate() = true;
315      eq MethodDecl.getModifiers().mayBeAbstract() = true;
316      eq MethodDecl.getModifiers().mayBeStatic() = true;
317      eq MethodDecl.getModifiers().mayBeFinal() = true;
318      eq MethodDecl.getModifiers().mayBeSynchronized() = true;
319      eq MethodDecl.getModifiers().mayBeNative() = true;
320      eq MethodDecl.getModifiers().mayBeStrictfp() = true;
321    
322      // 8.8.3
323      eq ConstructorDecl.getModifiers().mayBePublic() = true;
324      eq ConstructorDecl.getModifiers().mayBeProtected() = true;
325      eq ConstructorDecl.getModifiers().mayBePrivate() = true;
326    
327      eq VariableDeclaration.getModifiers().mayBeFinal() = true;
328    
329      eq ParameterDeclaration.getModifiers().mayBeFinal() = true;
330    
331      eq Program.getChild().mayBePublic() = false;
332      eq Program.getChild().mayBeProtected() = false;
333      eq Program.getChild().mayBePrivate() = false;
334      eq Program.getChild().mayBeStatic() = false;
335      eq Program.getChild().mayBeFinal() = false;
336      eq Program.getChild().mayBeAbstract() = false;
337      eq Program.getChild().mayBeVolatile() = false;
338      eq Program.getChild().mayBeTransient() = false;
339      eq Program.getChild().mayBeStrictfp() = false;
340      eq Program.getChild().mayBeSynchronized() = false;
341      eq Program.getChild().mayBeNative() = false;
342      eq TypeDecl.getBodyDecl().mayBePublic() = false;
343      eq TypeDecl.getBodyDecl().mayBeProtected() = false;
344      eq TypeDecl.getBodyDecl().mayBePrivate() = false;
345      eq TypeDecl.getBodyDecl().mayBeStatic() = false;
346      eq TypeDecl.getBodyDecl().mayBeFinal() = false;
347      eq TypeDecl.getBodyDecl().mayBeAbstract() = false;
348      eq TypeDecl.getBodyDecl().mayBeVolatile() = false;
349      eq TypeDecl.getBodyDecl().mayBeTransient() = false;
350      eq TypeDecl.getBodyDecl().mayBeStrictfp() = false;
351      eq TypeDecl.getBodyDecl().mayBeSynchronized() = false;
352      eq TypeDecl.getBodyDecl().mayBeNative() = false;
353    
354      // 8.4.3
355      public void Modifiers.checkModifiers() {
356        super.checkModifiers();
357        if (numProtectionModifiers() > 1) {
358          error("only one public, protected, private allowed");
359        }
360        if (numModifier("static") > 1) {
361          error("only one static allowed");
362        }
363        // 8.4.3.1
364        // 8.4.3.2
365        // 8.1.1.2
366        if (numCompletenessModifiers() > 1) {
367          error("only one of final, abstract, volatile allowed");
368        }
369        if (numModifier("synchronized") > 1) {
370          error("only one synchronized allowed");
371        }
372        if (numModifier("transient") > 1) {
373          error("only one transient allowed");
374        }
375        if (numModifier("native") > 1) {
376          error("only one native allowed");
377        }
378        if (numModifier("strictfp") > 1) {
379          error("only one strictfp allowed");
380        }
381    
382        if (isPublic() && !mayBePublic()) {
383          error("modifier public not allowed in this context");
384        }
385        if (isPrivate() && !mayBePrivate()) {
386          error("modifier private not allowed in this context");
387        }
388        if (isProtected() && !mayBeProtected()) {
389          error("modifier protected not allowed in this context");
390        }
391        if (isStatic() && !mayBeStatic()) {
392          error("modifier static not allowed in this context");
393        }
394        if (isFinal() && !mayBeFinal()) {
395          error("modifier final not allowed in this context");
396        }
397        if (isAbstract() && !mayBeAbstract()) {
398          error("modifier abstract not allowed in this context");
399        }
400        if (isVolatile() && !mayBeVolatile()) {
401          error("modifier volatile not allowed in this context");
402        }
403        if (isTransient() && !mayBeTransient()) {
404          error("modifier transient not allowed in this context");
405        }
406        if (isStrictfp() && !mayBeStrictfp()) {
407          error("modifier strictfp not allowed in this context");
408        }
409        if (isSynchronized() && !mayBeSynchronized()) {
410          error("modifier synchronized not allowed in this context");
411        }
412        if (isNative() && !mayBeNative()) {
413          error("modifier native not allowed in this context");
414        }
415      }
416    
417      inh TypeDecl Modifiers.hostType();
418    
419      inh boolean Modifiers.mayBePublic();
420      inh boolean Modifiers.mayBePrivate();
421      inh boolean Modifiers.mayBeProtected();
422      inh boolean Modifiers.mayBeStatic();
423      inh boolean Modifiers.mayBeFinal();
424      inh boolean Modifiers.mayBeAbstract();
425      inh boolean Modifiers.mayBeVolatile();
426      inh boolean Modifiers.mayBeTransient();
427      inh boolean Modifiers.mayBeStrictfp();
428      inh boolean Modifiers.mayBeSynchronized();
429      inh boolean Modifiers.mayBeNative();
430    
431      syn lazy boolean Modifiers.isPublic() = numModifier("public") != 0;
432      syn lazy boolean Modifiers.isPrivate() = numModifier("private") != 0;
433      syn lazy boolean Modifiers.isProtected() = numModifier("protected") != 0;
434      syn lazy boolean Modifiers.isStatic() = numModifier("static") != 0;
435      syn lazy boolean Modifiers.isFinal() = numModifier("final") != 0;
436      syn lazy boolean Modifiers.isAbstract() = numModifier("abstract") != 0;
437      syn lazy boolean Modifiers.isVolatile() = numModifier("volatile") != 0;
438      syn lazy boolean Modifiers.isTransient() = numModifier("transient") != 0;
439      syn lazy boolean Modifiers.isStrictfp() = numModifier("strictfp") != 0;
440      syn lazy boolean Modifiers.isSynchronized() = numModifier("synchronized") != 0;
441      syn lazy boolean Modifiers.isNative() = numModifier("native") != 0;
442    
443      syn lazy boolean Modifiers.isSynthetic() = numModifier("synthetic") != 0;
444    
445      syn int Modifiers.numProtectionModifiers() =
446          numModifier("public") + numModifier("protected") + numModifier("private");
447    
448      syn int Modifiers.numCompletenessModifiers() =
449          numModifier("abstract") + numModifier("final") + numModifier("volatile");
450    
451      syn lazy int Modifiers.numModifier(String name) {
452        int n = 0;
453        for (int i = 0; i < getNumModifier(); i++) {
454          String s = getModifier(i).getID();
455          if (s.equals(name)) {
456            n++;
457          }
458        }
459        return n;
460      }
461    
462    }