001    /*
002     * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered
003     * by the modified BSD License. You should have received a copy of the
004     * modified BSD license with this compiler.
005     * 
006     * Copyright (c) 2005-2008, Torbjorn Ekman
007     * All rights reserved.
008     */
009    
010    aspect Modifiers {
011      void ASTNode.checkModifiers() {
012      }
013    
014      syn lazy boolean TypeDecl.hasAbstract() = false;
015    
016      syn lazy Collection TypeDecl.unimplementedMethods() = Collections.EMPTY_LIST;
017      eq ClassDecl.unimplementedMethods() {
018        Collection c = new ArrayList();
019        for(Iterator iter = interfacesMethodsIterator(); iter.hasNext(); ) {
020          MethodDecl m = (MethodDecl)iter.next();
021          boolean implemented = false;
022          SimpleSet set = (SimpleSet)localMethodsSignature(m.signature());
023          if(set.size() == 1) {
024            MethodDecl n = (MethodDecl)set.iterator().next();
025            if(!n.isAbstract())
026              implemented = true;
027          }
028          if(!implemented) {
029            set = (SimpleSet)ancestorMethods(m.signature());
030            for(Iterator i2 = set.iterator(); i2.hasNext(); ) {
031              MethodDecl n = (MethodDecl)i2.next();
032              if(!n.isAbstract()) {
033                implemented = true;
034                break;
035              }
036            }
037          }
038          if(!implemented) {
039            c.add(m);
040          }
041        }
042    
043        if(hasSuperclass()) {
044          for(Iterator iter = superclass().unimplementedMethods().iterator(); iter.hasNext(); ) {
045            MethodDecl m = (MethodDecl)iter.next();
046            SimpleSet set = (SimpleSet)localMethodsSignature(m.signature());
047            if(set.size() == 1) {
048              MethodDecl n = (MethodDecl)set.iterator().next();
049              if(n.isAbstract() || !n.overrides(m))
050                c.add(m);
051            }
052            else
053              c.add(m);
054          }
055        }
056    
057        for(Iterator iter = localMethodsIterator(); iter.hasNext(); ) {
058          MethodDecl m = (MethodDecl)iter.next();
059          if(m.isAbstract()) {
060            c.add(m);
061          }
062        }
063        return c;
064      }
065    
066      eq ClassDecl.hasAbstract() = !unimplementedMethods().isEmpty();
067    
068      public void TypeDecl.checkModifiers() {
069        super.checkModifiers();
070        // 8.1.1
071        if(isPublic() && !isTopLevelType() && !isMemberType())
072          error("public pertains only to top level types and member types");
073    
074        // 8.1.1
075        if((isProtected() || isPrivate()) && !(isMemberType() && enclosingType().isClassDecl()))
076          error("protected and private may only be used on member types within a directly enclosing class declaration");
077    
078        // 8.1.1
079        if(isStatic() && !isMemberType())
080          error("static pertains only to member types");
081        
082        
083        // 8.4.3.1
084        // 8.1.1.1
085        if(!isAbstract() && hasAbstract()) {
086          StringBuffer s = new StringBuffer();
087          s.append("" + name() + " is not declared abstract but contains abstract members: \n");
088          for(Iterator iter = unimplementedMethods().iterator(); iter.hasNext(); ) {
089            MethodDecl m = (MethodDecl)iter.next();
090            s.append("  " + m.signature() + " in " + m.hostType().typeName() + "\n");
091          }
092          error(s.toString());
093        }
094      }
095      
096     public void ClassDecl.checkModifiers() {
097        super.checkModifiers();
098        // 8.1.1.2 final Classes
099        TypeDecl typeDecl = hasSuperclass() ? superclass() : null;
100        if(typeDecl != null && typeDecl.isFinal()) {
101          error("class " + fullName() + " may not extend final class " + typeDecl.fullName());
102        }
103    
104      }
105      
106      public void InterfaceDecl.checkModifiers() {
107        super.checkModifiers();
108      }
109     
110      public void ConstructorDecl.checkModifiers() {
111        super.checkModifiers();
112      }
113     
114      public void FieldDeclaration.checkModifiers() {
115        super.checkModifiers();
116        if(hostType().isInterfaceDecl()) {
117          if(isProtected())
118            error("an interface field may not be protected");
119          if(isPrivate())
120            error("an interface field may not be private");
121          if(isTransient())
122            error("an interface field may not be transient");
123          if(isVolatile())
124            error("an interface field may not be volatile");
125        }
126      }
127      
128      // 8.4.3
129      public void MethodDecl.checkModifiers() {
130        super.checkModifiers();
131        if(hostType().isClassDecl()) {
132          // 8.4.3.1
133          if(isAbstract() && !hostType().isAbstract())
134            error("class must be abstract to include abstract methods");
135          // 8.4.3.1
136          if(isAbstract() && isPrivate())
137            error("method may not be abstract and private");
138          // 8.4.3.1
139          // 8.4.3.2
140          if(isAbstract() && isStatic())
141            error("method may not be abstract and static");
142          if(isAbstract() && isSynchronized())
143            error("method may not be abstract and synchronized");
144          // 8.4.3.4
145          if(isAbstract() && isNative())
146            error("method may not be abstract and native");
147          if(isAbstract() && isStrictfp())
148            error("method may not be abstract and strictfp");
149          if(isNative() && isStrictfp())
150            error("method may not be native and strictfp");
151        }
152        if(hostType().isInterfaceDecl()) {
153          // 9.4
154          if(isStatic())
155            error("interface method " + signature() + " in " +
156                hostType().typeName() +  " may not be static");
157          if(isStrictfp())
158            error("interface method " + signature() + " in " +
159                hostType().typeName() +  " may not be strictfp");
160          if(isNative())
161            error("interface method " + signature() + " in " +
162                hostType().typeName() +  " may not be native");
163          if(isSynchronized())
164            error("interface method " + signature() + " in " +
165                hostType().typeName() +  " may not be synchronized");
166          if(isProtected())
167            error("interface method " + signature() + " in " +
168                hostType().typeName() +  " may not be protected");
169          if(isPrivate())
170            error("interface method " + signature() + " in " +
171                hostType().typeName() +  " may not be private");
172          else if(isFinal())
173            error("interface method " + signature() + " in " +
174                hostType().typeName() +  " may not be final");
175        }
176      }
177    
178      // 8.1.2
179      public void StaticInitializer.checkModifiers() {
180        super.checkModifiers();
181        if(hostType().isInnerClass())
182          error("*** Inner classes may not declare static initializers");
183      }
184     
185      // 8.1.2
186      public void MemberInterfaceDecl.checkModifiers() {
187        super.checkModifiers();
188        if(hostType().isInnerClass())
189          error("*** Inner classes may not declare member interfaces");
190      }
191       
192      public void MemberDecl.checkModifiers() {
193        if(!isSynthetic()) {
194          super.checkModifiers();
195          if(isStatic() && hostType().isInnerClass() && !isConstant())
196            error("*** Inner classes may not declare static members, unless they are compile-time constant fields");
197        }
198      }
199    
200      syn lazy boolean TypeDecl.isPublic() = getModifiers().isPublic() || isMemberType() && enclosingType().isInterfaceDecl();
201      //eq InterfaceDecl.isPublic() = !isProtected() && !isPrivate();
202      syn boolean TypeDecl.isPrivate() = getModifiers().isPrivate();
203      syn boolean TypeDecl.isProtected() = getModifiers().isProtected();
204      syn boolean TypeDecl.isAbstract() = getModifiers().isAbstract();
205      eq InterfaceDecl.isAbstract() = true;
206      syn lazy boolean TypeDecl.isStatic() = getModifiers().isStatic() || isMemberType() && enclosingType().isInterfaceDecl();
207      // 8.5.2
208      eq InterfaceDecl.isStatic() = getModifiers().isStatic() || isMemberType();
209      syn boolean TypeDecl.isFinal() = getModifiers().isFinal();
210      syn boolean TypeDecl.isStrictfp() = getModifiers().isStrictfp();
211    
212      syn boolean TypeDecl.isSynthetic() = getModifiers().isSynthetic();
213      
214      syn boolean MemberDecl.isSynthetic() = false;
215      eq MethodDecl.isSynthetic() = getModifiers().isSynthetic();
216      eq FieldDeclaration.isSynthetic() = getModifiers().isSynthetic();
217      syn boolean ConstructorDecl.isSynthetic() = getModifiers().isSynthetic();
218    
219      syn boolean VariableDeclaration.isSynthetic() = getModifiers().isSynthetic();
220      syn boolean ParameterDeclaration.isSynthetic() = getModifiers().isSynthetic();
221    
222      syn boolean MemberDecl.isStatic(); 
223      
224      syn boolean MethodDecl.isPublic() = getModifiers().isPublic() || hostType().isInterfaceDecl();
225      syn boolean MethodDecl.isPrivate() = getModifiers().isPrivate();
226      syn boolean MethodDecl.isProtected() = getModifiers().isProtected();
227      syn boolean MethodDecl.isAbstract() = getModifiers().isAbstract() || hostType().isInterfaceDecl();
228      syn boolean MethodDecl.isStatic() = getModifiers().isStatic();
229      // 8.4.3.3
230      syn boolean MethodDecl.isFinal() = getModifiers().isFinal() || hostType().isFinal() || isPrivate();
231      syn boolean MethodDecl.isSynchronized() = getModifiers().isSynchronized();
232      syn boolean MethodDecl.isNative() = getModifiers().isNative();
233      syn boolean MethodDecl.isStrictfp() = getModifiers().isStrictfp();
234      
235      syn boolean ConstructorDecl.isPublic() = getModifiers().isPublic();
236      syn boolean ConstructorDecl.isPrivate() = getModifiers().isPrivate();
237      syn boolean ConstructorDecl.isProtected() = getModifiers().isProtected();
238      
239      syn boolean FieldDeclaration.isPublic() = getModifiers().isPublic() || hostType().isInterfaceDecl();
240      syn boolean FieldDeclaration.isPrivate() = getModifiers().isPrivate();
241      syn boolean FieldDeclaration.isProtected() = getModifiers().isProtected();
242      syn boolean FieldDeclaration.isStatic() = getModifiers().isStatic() || hostType().isInterfaceDecl();
243      syn boolean FieldDecl.isStatic() = getModifiers().isStatic();
244      syn boolean FieldDeclaration.isFinal() = getModifiers().isFinal() || hostType().isInterfaceDecl();
245      syn boolean FieldDeclaration.isTransient() = getModifiers().isTransient();
246      syn boolean FieldDeclaration.isVolatile() = getModifiers().isVolatile();
247    
248      eq MemberTypeDecl.isStatic() = typeDecl().isStatic();
249      
250      // 8.1.1 & 9.1.1
251      eq TypeDecl.getModifiers().mayBePublic() = true;
252      eq TypeDecl.getModifiers().mayBeProtected() = true;
253      eq TypeDecl.getModifiers().mayBePrivate() = true;
254      eq TypeDecl.getModifiers().mayBeAbstract() = true;
255      eq TypeDecl.getModifiers().mayBeStatic() = true;
256      eq TypeDecl.getModifiers().mayBeStrictfp() = true;
257    
258      // 8.1.1
259      eq ClassDecl.getModifiers().mayBeFinal() = true;
260    
261      // 8.3.1
262      eq FieldDeclaration.getModifiers().mayBePublic() = true;
263      eq FieldDeclaration.getModifiers().mayBeProtected() = true;
264      eq FieldDeclaration.getModifiers().mayBePrivate() = true;
265      eq FieldDeclaration.getModifiers().mayBeStatic() = true;
266      eq FieldDeclaration.getModifiers().mayBeFinal() = true;
267      eq FieldDeclaration.getModifiers().mayBeTransient() = true;
268      eq FieldDeclaration.getModifiers().mayBeVolatile() = true;
269      
270      // 8.4.3
271      eq MethodDecl.getModifiers().mayBePublic() = true;
272      eq MethodDecl.getModifiers().mayBeProtected() = true;
273      eq MethodDecl.getModifiers().mayBePrivate() = true;
274      eq MethodDecl.getModifiers().mayBeAbstract() = true;
275      eq MethodDecl.getModifiers().mayBeStatic() = true;
276      eq MethodDecl.getModifiers().mayBeFinal() = true;
277      eq MethodDecl.getModifiers().mayBeSynchronized() = true;
278      eq MethodDecl.getModifiers().mayBeNative() = true;
279      eq MethodDecl.getModifiers().mayBeStrictfp() = true;
280    
281      // 8.8.3
282      eq ConstructorDecl.getModifiers().mayBePublic() = true;
283      eq ConstructorDecl.getModifiers().mayBeProtected() = true;
284      eq ConstructorDecl.getModifiers().mayBePrivate() = true;
285    
286      eq VariableDeclaration.getModifiers().mayBeFinal() = true;
287    
288      eq ParameterDeclaration.getModifiers().mayBeFinal() = true;
289       
290      eq Program.getChild().mayBePublic() = false;
291      eq Program.getChild().mayBeProtected() = false;
292      eq Program.getChild().mayBePrivate() = false;
293      eq Program.getChild().mayBeStatic() = false;
294      eq Program.getChild().mayBeFinal() = false;
295      eq Program.getChild().mayBeAbstract() = false;
296      eq Program.getChild().mayBeVolatile() = false;
297      eq Program.getChild().mayBeTransient() = false;
298      eq Program.getChild().mayBeStrictfp() = false;
299      eq Program.getChild().mayBeSynchronized() = false;
300      eq Program.getChild().mayBeNative() = false;
301      eq TypeDecl.getBodyDecl().mayBePublic() = false;
302      eq TypeDecl.getBodyDecl().mayBeProtected() = false;
303      eq TypeDecl.getBodyDecl().mayBePrivate() = false;
304      eq TypeDecl.getBodyDecl().mayBeStatic() = false;
305      eq TypeDecl.getBodyDecl().mayBeFinal() = false;
306      eq TypeDecl.getBodyDecl().mayBeAbstract() = false;
307      eq TypeDecl.getBodyDecl().mayBeVolatile() = false;
308      eq TypeDecl.getBodyDecl().mayBeTransient() = false;
309      eq TypeDecl.getBodyDecl().mayBeStrictfp() = false;
310      eq TypeDecl.getBodyDecl().mayBeSynchronized() = false;
311      eq TypeDecl.getBodyDecl().mayBeNative() = false;
312    
313      // 8.4.3
314      public void Modifiers.checkModifiers() {
315        super.checkModifiers();
316        if(numProtectionModifiers() > 1)
317          error("only one public, protected, private allowed");
318        if(numModifier("static") > 1)
319          error("only one static allowed");
320        // 8.4.3.1
321        // 8.4.3.2
322        // 8.1.1.2
323        if(numCompletenessModifiers() > 1)
324          error("only one of final, abstract, volatile allowed");
325        if(numModifier("synchronized") > 1)
326          error("only one synchronized allowed");
327        if(numModifier("transient") > 1)
328          error("only one transient allowed");
329        if(numModifier("native") > 1)
330          error("only one native allowed");
331        if(numModifier("strictfp") > 1)
332          error("only one strictfp allowed");
333    
334        if(isPublic() && !mayBePublic())
335          error("modifier public not allowed in this context");
336        if(isPrivate() && !mayBePrivate())
337          error("modifier private not allowed in this context");
338        if(isProtected() && !mayBeProtected())
339          error("modifier protected not allowed in this context");
340        if(isStatic() && !mayBeStatic())
341          error("modifier static not allowed in this context");
342        if(isFinal() && !mayBeFinal())
343          error("modifier final not allowed in this context");
344        if(isAbstract() && !mayBeAbstract())
345          error("modifier abstract not allowed in this context");
346        if(isVolatile() && !mayBeVolatile())
347          error("modifier volatile not allowed in this context");
348        if(isTransient() && !mayBeTransient())
349          error("modifier transient not allowed in this context");
350        if(isStrictfp() && !mayBeStrictfp())
351          error("modifier strictfp not allowed in this context");
352        if(isSynchronized() && !mayBeSynchronized())
353          error("modifier synchronized not allowed in this context");
354        if(isNative() && !mayBeNative())
355          error("modifier native not allowed in this context");
356      }
357    
358      inh TypeDecl Modifiers.hostType();
359      
360      inh boolean Modifiers.mayBePublic();
361      inh boolean Modifiers.mayBePrivate();
362      inh boolean Modifiers.mayBeProtected();
363      inh boolean Modifiers.mayBeStatic();
364      inh boolean Modifiers.mayBeFinal();
365      inh boolean Modifiers.mayBeAbstract();
366      inh boolean Modifiers.mayBeVolatile();
367      inh boolean Modifiers.mayBeTransient();
368      inh boolean Modifiers.mayBeStrictfp();
369      inh boolean Modifiers.mayBeSynchronized();
370      inh boolean Modifiers.mayBeNative();
371    
372      syn lazy boolean Modifiers.isPublic() = numModifier("public") != 0;
373      syn lazy boolean Modifiers.isPrivate() = numModifier("private") != 0;
374      syn lazy boolean Modifiers.isProtected() = numModifier("protected") != 0;
375      syn lazy boolean Modifiers.isStatic() = numModifier("static") != 0;
376      syn lazy boolean Modifiers.isFinal() = numModifier("final") != 0;
377      syn lazy boolean Modifiers.isAbstract() = numModifier("abstract") != 0;
378      syn lazy boolean Modifiers.isVolatile() = numModifier("volatile") != 0;
379      syn lazy boolean Modifiers.isTransient() = numModifier("transient") != 0;
380      syn lazy boolean Modifiers.isStrictfp() = numModifier("strictfp") != 0;
381      syn lazy boolean Modifiers.isSynchronized() = numModifier("synchronized") != 0;
382      syn lazy boolean Modifiers.isNative() = numModifier("native") != 0;
383    
384      syn lazy boolean Modifiers.isSynthetic() = numModifier("synthetic") != 0;
385    
386      syn int Modifiers.numProtectionModifiers() = 
387        numModifier("public") + numModifier("protected") + numModifier("private");
388    
389      syn int Modifiers.numCompletenessModifiers() =
390        numModifier("abstract") + numModifier("final") + numModifier("volatile");
391        
392      syn lazy int Modifiers.numModifier(String name) {
393        int n = 0;
394        for(int i = 0; i < getNumModifier(); i++) {
395          String s = getModifier(i).getID();
396          if(s.equals(name))
397            n++;
398        }
399        return n;
400      }
401      
402    }