001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.netui.compiler.processor;
020:
021: import org.apache.beehive.netui.compiler.BaseChecker;
022: import org.apache.beehive.netui.compiler.BaseGenerator;
023: import org.apache.beehive.netui.compiler.CompilerUtils;
024: import org.apache.beehive.netui.compiler.Diagnostics;
025: import org.apache.beehive.netui.compiler.JpfLanguageConstants;
026: import org.apache.beehive.netui.compiler.SourceFileInfo;
027: import org.apache.beehive.netui.compiler.FatalCompileTimeException;
028: import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationTypeDeclaration;
029: import org.apache.beehive.netui.compiler.typesystem.declaration.ClassDeclaration;
030: import org.apache.beehive.netui.compiler.typesystem.declaration.Declaration;
031: import org.apache.beehive.netui.compiler.typesystem.declaration.Modifier;
032: import org.apache.beehive.netui.compiler.typesystem.env.CoreAnnotationProcessorEnv;
033: import org.apache.beehive.netui.compiler.typesystem.type.ClassType;
034:
035: import java.text.MessageFormat;
036: import java.util.HashMap;
037: import java.util.ResourceBundle;
038:
039: public abstract class BaseCoreAnnotationProcessor extends
040: TwoPhaseCoreAnnotationProcessor implements JpfLanguageConstants {
041: private HashMap _sourceFileInfo;
042: private SourceFileInfo _singleSourceFileInfo = null;
043: private ResourceBundle _messages;
044:
045: protected BaseCoreAnnotationProcessor(
046: AnnotationTypeDeclaration[] annotationTypeDecls,
047: CoreAnnotationProcessorEnv env) {
048: super (annotationTypeDecls, env);
049: _messages = ResourceBundle
050: .getBundle("org.apache.beehive.netui.compiler.diagnostics");
051: }
052:
053: public void check(Declaration decl)
054: throws FatalCompileTimeException {
055: assert _sourceFileInfo != null; // process() should guarantee this.
056:
057: if (decl instanceof ClassDeclaration) {
058: ClassDeclaration classDecl = (ClassDeclaration) decl;
059: BaseChecker checker = getChecker(classDecl, this );
060:
061: if (checker != null) {
062: checker.check(classDecl);
063:
064: //
065: // Also do a silent check on all base classes. We don't want to generate if there were errors
066: // in the base class.
067: //
068: SilentDiagnostics silentDiagnostics = new SilentDiagnostics();
069:
070: for (ClassType i = classDecl.getSuperclass(); i != null; i = i
071: .getSuperclass()) {
072: ClassDeclaration baseDecl = i
073: .getClassTypeDeclaration();
074:
075: if (CompilerUtils.getSourceFile(baseDecl, false) != null) {
076: BaseChecker silentChecker = getChecker(
077: baseDecl, silentDiagnostics);
078: if (silentChecker != null)
079: silentChecker.check(baseDecl);
080: }
081: }
082:
083: if (silentDiagnostics.hasErrors())
084: setHasErrors(true);
085: }
086: }
087: }
088:
089: public void generate(Declaration decl)
090: throws FatalCompileTimeException {
091: assert _sourceFileInfo != null; // process() should guarantee this.
092:
093: if (decl instanceof ClassDeclaration) {
094: ClassDeclaration classDecl = (ClassDeclaration) decl;
095: BaseGenerator generator = getGenerator(classDecl, this );
096: if (generator != null)
097: generator.generate(classDecl);
098: }
099: }
100:
101: public void process() {
102: _sourceFileInfo = new HashMap();
103: super .process();
104: _sourceFileInfo = null;
105: }
106:
107: protected abstract BaseChecker getChecker(ClassDeclaration decl,
108: Diagnostics diagnostics);
109:
110: protected abstract BaseGenerator getGenerator(
111: ClassDeclaration decl, Diagnostics diagnostics);
112:
113: protected SourceFileInfo getSourceFileInfo(ClassDeclaration decl) {
114: assert _sourceFileInfo != null || _singleSourceFileInfo != null;
115: assert _sourceFileInfo == null || _singleSourceFileInfo == null;
116: return _singleSourceFileInfo != null ? _singleSourceFileInfo
117: : (SourceFileInfo) _sourceFileInfo.get(decl
118: .getQualifiedName());
119: }
120:
121: protected void setSourceFileInfo(ClassDeclaration decl,
122: SourceFileInfo sourceFileInfo) {
123: assert _sourceFileInfo != null || _singleSourceFileInfo == null;
124:
125: if (_sourceFileInfo != null) {
126: _sourceFileInfo
127: .put(decl.getQualifiedName(), sourceFileInfo);
128: } else {
129: _singleSourceFileInfo = sourceFileInfo;
130: }
131: }
132:
133: protected static boolean expectAnnotation(
134: ClassDeclaration classDecl, String annotationBaseName,
135: String fileExtensionRequiresAnnotation, String baseClass,
136: Diagnostics diagnostics) {
137: if (CompilerUtils.getAnnotation(classDecl, annotationBaseName) != null)
138: return true;
139:
140: String fileName = classDecl.getPosition().file().getName();
141:
142: if (fileExtensionRequiresAnnotation != null
143: && fileName.endsWith(fileExtensionRequiresAnnotation)) {
144: diagnostics.addError(classDecl,
145: "error.annotation-required",
146: fileExtensionRequiresAnnotation,
147: ANNOTATIONS_CLASSNAME + '.' + annotationBaseName);
148: } else if (!classDecl.hasModifier(Modifier.ABSTRACT)) {
149: diagnostics.addWarning(classDecl,
150: "warning.missing-annotation", baseClass,
151: ANNOTATIONS_CLASSNAME + '.' + annotationBaseName);
152: }
153:
154: return false;
155: }
156:
157: protected String getResourceString(String key, Object[] args) {
158: String message = _messages.getString(key);
159: return MessageFormat.format(message, args);
160: }
161: }
|