diff --git a/annotations/src/main/java/annotations/ast/ASTDocLinkAnnotation.java b/annotations/src/main/java/annotations/ast/ASTDocLinkAnnotation.java new file mode 100644 index 000000000..f5f55d5de --- /dev/null +++ b/annotations/src/main/java/annotations/ast/ASTDocLinkAnnotation.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * + * Copyright (c) 2019 Nick Battle. + * + * Author: Nick Battle + * + * This file is part of VDMJ. + * + * VDMJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VDMJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VDMJ. If not, see . + * SPDX-License-Identifier: GPL-3.0-or-later + * + ******************************************************************************/ + +package annotations.ast; + +import com.fujitsu.vdmj.ast.annotations.ASTAnnotation; +import com.fujitsu.vdmj.ast.lex.LexIdentifierToken; + +public class ASTDocLinkAnnotation extends ASTAnnotation +{ + private static final long serialVersionUID = 1L; + + public ASTDocLinkAnnotation(LexIdentifierToken name) + { + super(name); + } +} diff --git a/annotations/src/main/java/annotations/in/INDocLinkAnnotation.java b/annotations/src/main/java/annotations/in/INDocLinkAnnotation.java new file mode 100644 index 000000000..21b268127 --- /dev/null +++ b/annotations/src/main/java/annotations/in/INDocLinkAnnotation.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * + * Copyright (c) 2019 Nick Battle. + * + * Author: Nick Battle + * + * This file is part of VDMJ. + * + * VDMJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VDMJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VDMJ. If not, see . + * SPDX-License-Identifier: GPL-3.0-or-later + * + ******************************************************************************/ + +package annotations.in; + +import com.fujitsu.vdmj.in.annotations.INAnnotation; +import com.fujitsu.vdmj.in.expressions.INExpression; +import com.fujitsu.vdmj.in.expressions.INExpressionList; +import com.fujitsu.vdmj.in.expressions.INStringLiteralExpression; +import com.fujitsu.vdmj.tc.lex.TCIdentifierToken; + +public class INDocLinkAnnotation extends INAnnotation +{ + private static final long serialVersionUID = 1L; + + public INDocLinkAnnotation(TCIdentifierToken name, INExpressionList args) + { + super(name, args); + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + + for (INExpression arg: args) + { + INStringLiteralExpression s = (INStringLiteralExpression) arg; + sb.append(s.value.value); + sb.append("\n"); + } + + return sb.toString(); + } +} diff --git a/annotations/src/main/java/annotations/in/INOnFailAnnotation.java b/annotations/src/main/java/annotations/in/INOnFailAnnotation.java index ee6eb7332..05341f902 100644 --- a/annotations/src/main/java/annotations/in/INOnFailAnnotation.java +++ b/annotations/src/main/java/annotations/in/INOnFailAnnotation.java @@ -25,6 +25,7 @@ package annotations.in; import com.fujitsu.vdmj.in.annotations.INAnnotation; +import com.fujitsu.vdmj.in.annotations.INAnnotationList; import com.fujitsu.vdmj.in.expressions.INExpression; import com.fujitsu.vdmj.in.expressions.INExpressionList; import com.fujitsu.vdmj.in.expressions.INIntegerLiteralExpression; @@ -38,11 +39,13 @@ public class INOnFailAnnotation extends INAnnotation { private static final long serialVersionUID = 1L; private final String format; + private final INAnnotationList doclinks; // INDocLinkAnnotations - public INOnFailAnnotation(TCIdentifierToken name, INExpressionList args, String format) + public INOnFailAnnotation(TCIdentifierToken name, INExpressionList args, String format, INAnnotationList doclinks) { super(name, args); this.format = format; + this.doclinks = doclinks; } @Override @@ -79,6 +82,14 @@ public void inAfter(INExpression exp, Value rv, Context ctxt) } Console.out.printf(errno + useformat + location + "\n", values); + + if (doclinks != null) + { + for (INAnnotation link: doclinks) + { + Console.out.printf(link.toString()); + } + } } } catch (ValueException e) diff --git a/annotations/src/main/java/annotations/tc/TCDocLinkAnnotation.java b/annotations/src/main/java/annotations/tc/TCDocLinkAnnotation.java new file mode 100644 index 000000000..f6b0e9834 --- /dev/null +++ b/annotations/src/main/java/annotations/tc/TCDocLinkAnnotation.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * + * Copyright (c) 2019 Nick Battle. + * + * Author: Nick Battle + * + * This file is part of VDMJ. + * + * VDMJ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * VDMJ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with VDMJ. If not, see . + * SPDX-License-Identifier: GPL-3.0-or-later + * + ******************************************************************************/ + +package annotations.tc; + +import java.util.Stack; + +import com.fujitsu.vdmj.tc.annotations.TCAnnotation; +import com.fujitsu.vdmj.tc.definitions.TCClassDefinition; +import com.fujitsu.vdmj.tc.definitions.TCDefinition; +import com.fujitsu.vdmj.tc.expressions.TCExpression; +import com.fujitsu.vdmj.tc.expressions.TCExpressionList; +import com.fujitsu.vdmj.tc.expressions.TCStringLiteralExpression; +import com.fujitsu.vdmj.tc.lex.TCIdentifierToken; +import com.fujitsu.vdmj.tc.modules.TCModule; +import com.fujitsu.vdmj.tc.statements.TCStatement; +import com.fujitsu.vdmj.tc.types.TCType; +import com.fujitsu.vdmj.typechecker.Environment; +import com.fujitsu.vdmj.typechecker.ModuleEnvironment; +import com.fujitsu.vdmj.typechecker.NameScope; +import com.fujitsu.vdmj.typechecker.PrivateClassEnvironment; + +public class TCDocLinkAnnotation extends TCAnnotation +{ + private static final long serialVersionUID = 1L; + + private static Stack stack = new Stack(); + + public TCDocLinkAnnotation(TCIdentifierToken name, TCExpressionList args) + { + super(name, args); + } + + @Override + public void tcBefore(TCModule module, ModuleEnvironment env) + { + stack.clear(); + stack.push(this); + check(); + } + + @Override + public void tcBefore(TCClassDefinition clazz, PrivateClassEnvironment env) + { + stack.clear(); + stack.push(this); + check(); + } + + @Override + public void tcBefore(TCDefinition def, Environment env, NameScope scope) + { + stack.push(this); + check(); + } + + @Override + public void tcBefore(TCStatement stmt, Environment env, NameScope scope) + { + stack.push(this); + check(); + } + + @Override + public void tcBefore(TCExpression exp, Environment env, NameScope scope) + { + stack.push(this); + check(); + } + + @Override + public void tcAfter(TCClassDefinition m, PrivateClassEnvironment env) + { + stack.pop(); + } + + @Override + public void tcAfter(TCModule m, ModuleEnvironment e) + { + stack.pop(); + } + + @Override + public void tcAfter(TCDefinition def, TCType type, Environment env, NameScope scope) + { + stack.pop(); + } + + @Override + public void tcAfter(TCExpression exp, TCType type, Environment env, NameScope scope) + { + stack.pop(); + } + + @Override + public void tcAfter(TCStatement stmt, TCType type, Environment env, NameScope scope) + { + stack.pop(); + } + + public void check() + { + if (args.isEmpty()) + { + name.report(6008, "@DocLink(\"arg\"...)"); + } + else + { + for (TCExpression arg: args) + { + if (!(arg instanceof TCStringLiteralExpression)) + { + arg.report(6008, "@DocLink args must be string literals"); + } + } + } + } + + public static Stack enclosing() + { + return stack; + } +} diff --git a/annotations/src/main/java/annotations/tc/TCOnFailAnnotation.java b/annotations/src/main/java/annotations/tc/TCOnFailAnnotation.java index b3cfe62df..77073b9f8 100644 --- a/annotations/src/main/java/annotations/tc/TCOnFailAnnotation.java +++ b/annotations/src/main/java/annotations/tc/TCOnFailAnnotation.java @@ -25,8 +25,10 @@ package annotations.tc; import java.util.Arrays; +import java.util.Stack; import com.fujitsu.vdmj.tc.annotations.TCAnnotation; +import com.fujitsu.vdmj.tc.annotations.TCAnnotationList; import com.fujitsu.vdmj.tc.definitions.TCClassDefinition; import com.fujitsu.vdmj.tc.definitions.TCDefinition; import com.fujitsu.vdmj.tc.expressions.TCExpression; @@ -46,6 +48,8 @@ public class TCOnFailAnnotation extends TCAnnotation { private static final long serialVersionUID = 1L; private String format = null; + @SuppressWarnings("unused") + private TCAnnotationList doclinks = null; public TCOnFailAnnotation(TCIdentifierToken name, TCExpressionList args) { @@ -129,6 +133,14 @@ public void tcBefore(TCExpression exp, Environment env, NameScope scope) { name.report(6008, "@OnFail must only use %[arg$][#][width]s conversions"); } + + Stack enclosing = TCDocLinkAnnotation.enclosing(); + + if (!enclosing.isEmpty()) + { + doclinks = new TCAnnotationList(); + doclinks.addAll(enclosing); + } } else { diff --git a/annotations/src/main/java/annotations/tc/TCWarningAnnotation.java b/annotations/src/main/java/annotations/tc/TCWarningAnnotation.java index eb9c38348..014387e1b 100644 --- a/annotations/src/main/java/annotations/tc/TCWarningAnnotation.java +++ b/annotations/src/main/java/annotations/tc/TCWarningAnnotation.java @@ -24,7 +24,6 @@ package annotations.tc; -import java.io.File; import java.util.HashSet; import java.util.Iterator; import java.util.Set; @@ -41,6 +40,7 @@ import com.fujitsu.vdmj.tc.statements.TCStatement; import com.fujitsu.vdmj.tc.types.TCType; import com.fujitsu.vdmj.typechecker.Environment; +import com.fujitsu.vdmj.typechecker.ModuleEnvironment; import com.fujitsu.vdmj.typechecker.NameScope; import com.fujitsu.vdmj.typechecker.TypeChecker; @@ -48,6 +48,7 @@ public class TCWarningAnnotation extends TCAnnotation { private static final long serialVersionUID = 1L; private int warningCount = 0; + private String moduleName = null; private Set suppressed; public TCWarningAnnotation(TCIdentifierToken name, TCExpressionList args) @@ -56,32 +57,37 @@ public TCWarningAnnotation(TCIdentifierToken name, TCExpressionList args) } @Override - public void tcBefore(TCDefinition def, Environment env, NameScope scope) + public void tcBefore(TCModule module, ModuleEnvironment e) { + moduleName = module.name.getName(); preCheck(); } @Override - public void tcBefore(TCModule module) + public void tcBefore(TCClassDefinition clazz) { + moduleName = clazz.name.getName(); preCheck(); } @Override - public void tcBefore(TCClassDefinition clazz) + public void tcBefore(TCDefinition def, Environment env, NameScope scope) { + warningCount = TypeChecker.getWarningCount(); preCheck(); } @Override public void tcBefore(TCExpression exp, Environment env, NameScope scope) { + warningCount = TypeChecker.getWarningCount(); preCheck(); } @Override public void tcBefore(TCStatement stmt, Environment env, NameScope scope) { + warningCount = TypeChecker.getWarningCount(); preCheck(); } @@ -92,7 +98,6 @@ private void preCheck() name.report(6010, "@Warning must have one or more numeric arguments"); } - warningCount = TypeChecker.getWarningCount(); suppressed = new HashSet(); for (TCExpression arg: args) @@ -121,6 +126,12 @@ public void tcAfter(TCModule module) postCheck(); } + @Override + public void tcAfter(TCModule module, ModuleEnvironment e) + { + postCheck(); + } + @Override public void tcAfter(TCExpression exp, TCType type, Environment env, NameScope scope) { @@ -143,38 +154,25 @@ private void postCheck() { Iterator witer = TypeChecker.getWarnings().iterator(); - for (int i=0; i < warningCount; i++) + if (moduleName == null) { - witer.next(); // skip previous warnings + for (int i=0; i < warningCount; i++) + { + witer.next(); // skip previous warnings + } } while (witer.hasNext()) { VDMWarning w = witer.next(); - if (suppressed.contains((long)w.number)) + if (moduleName != null && !w.location.module.equals(moduleName)) { - witer.remove(); + continue; } - } - } - - @Override - public void doClose() - { - Iterator witer = TypeChecker.getWarnings().iterator(); - int myLine = name.getLocation().startLine; - File myFile = name.getLocation().file; - - while (witer.hasNext()) - { - VDMWarning w = witer.next(); - if (w.location.startLine == myLine + 1 && - w.location.file.equals(myFile) && - suppressed.contains((long)w.number)) + if (suppressed.contains((long)w.number)) { - // Warning is on the line after the one we annotated, so remove it witer.remove(); } } diff --git a/annotations/src/main/resources/ast-tc.mappings b/annotations/src/main/resources/ast-tc.mappings index f04b20539..581367356 100644 --- a/annotations/src/main/resources/ast-tc.mappings +++ b/annotations/src/main/resources/ast-tc.mappings @@ -13,3 +13,4 @@ map ASTOnFailAnnotation{name, args} to TCOnFailAnnotation(name, args); map ASTSeparateAnnotation{name, args} to TCSeparateAnnotation(name, args); map ASTDeadlineMetAnnotation{name, args} to TCDeadlineMetAnnotation(name, args); map ASTSepRequireAnnotation{name, args} to TCSepRequireAnnotation(name, args); +map ASTDocLinkAnnotation{name, args} to TCDocLinkAnnotation(name, args); diff --git a/annotations/src/main/resources/tc-in.mappings b/annotations/src/main/resources/tc-in.mappings index 98bd2ee98..4686dbe28 100644 --- a/annotations/src/main/resources/tc-in.mappings +++ b/annotations/src/main/resources/tc-in.mappings @@ -9,7 +9,8 @@ map TCOverrideAnnotation{name, args} to INNullAnnotation(name, args); map TCNoPOGAnnotation{name, args} to INNullAnnotation(name, args); map TCPrintfAnnotation{name, args} to INPrintfAnnotation(name, args); map TCWarningAnnotation{name, args} to INNullAnnotation(name, args); -map TCOnFailAnnotation{name, args, format} to INOnFailAnnotation(name, args, format); +map TCOnFailAnnotation{name, args, format, doclinks} to INOnFailAnnotation(name, args, format, doclinks); map TCSeparateAnnotation{name, args} to INSeparateAnnotation(name, args); map TCDeadlineMetAnnotation{name, args} to INDeadlineMetAnnotation(name, args); map TCSepRequireAnnotation{name, args} to INSepRequireAnnotation(name, args); +map TCDocLinkAnnotation{name, args} to INDocLinkAnnotation(name, args); diff --git a/annotations/src/main/resources/tc-po.mappings b/annotations/src/main/resources/tc-po.mappings index ccf02a76c..dcf6536e9 100644 --- a/annotations/src/main/resources/tc-po.mappings +++ b/annotations/src/main/resources/tc-po.mappings @@ -10,4 +10,4 @@ map TCNoPOGAnnotation{name, args} to PONoPOGAnnotation(name, args); map TCPrintfAnnotation{name, args} to PONullAnnotation(name, args); map TCWarningAnnotation{name, args} to PONullAnnotation(name, args); map TCOnFailAnnotation{name, args} to PONullAnnotation(name, args); - +map TCDocLinkAnnotation{name, args} to PONullAnnotation(name, args); diff --git a/annotations/src/main/resources/vdmj.annotations b/annotations/src/main/resources/vdmj.annotations index 4f55a872a..91d02bc70 100644 --- a/annotations/src/main/resources/vdmj.annotations +++ b/annotations/src/main/resources/vdmj.annotations @@ -7,4 +7,5 @@ annotations.ast.ASTPrintfAnnotation annotations.ast.ASTSeparateAnnotation annotations.ast.ASTSepRequireAnnotation annotations.ast.ASTTraceAnnotation -annotations.ast.ASTWarningAnnotation \ No newline at end of file +annotations.ast.ASTWarningAnnotation +annotations.ast.ASTDocLinkAnnotation \ No newline at end of file diff --git a/vdmj/src/main/java/com/fujitsu/vdmj/tc/annotations/TCAnnotation.java b/vdmj/src/main/java/com/fujitsu/vdmj/tc/annotations/TCAnnotation.java index 4cb818c4c..ad88ae842 100644 --- a/vdmj/src/main/java/com/fujitsu/vdmj/tc/annotations/TCAnnotation.java +++ b/vdmj/src/main/java/com/fujitsu/vdmj/tc/annotations/TCAnnotation.java @@ -42,7 +42,9 @@ import com.fujitsu.vdmj.tc.statements.TCStatement; import com.fujitsu.vdmj.tc.types.TCType; import com.fujitsu.vdmj.typechecker.Environment; +import com.fujitsu.vdmj.typechecker.ModuleEnvironment; import com.fujitsu.vdmj.typechecker.NameScope; +import com.fujitsu.vdmj.typechecker.PrivateClassEnvironment; public abstract class TCAnnotation extends TCNode implements MappingOptional { @@ -145,11 +147,21 @@ public void tcBefore(TCModule m) // Do nothing } + public void tcBefore(TCModule m, ModuleEnvironment e) + { + // Do nothing + } + public void tcBefore(TCClassDefinition clazz) { // Do nothing } + public void tcBefore(TCClassDefinition clazz, PrivateClassEnvironment self) + { + // Do nothing + } + public void tcAfter(TCDefinition def, TCType type, Environment env, NameScope scope) { // Do nothing @@ -170,11 +182,21 @@ public void tcAfter(TCModule m) // Do nothing } + public void tcAfter(TCModule m, ModuleEnvironment env) + { + // Do nothing + } + public void tcAfter(TCClassDefinition m) { // Do nothing } + public void tcAfter(TCClassDefinition clazz, PrivateClassEnvironment self) + { + // Do nothing + } + public static void close() { for (TCAnnotation annotation: instances) diff --git a/vdmj/src/main/java/com/fujitsu/vdmj/tc/annotations/TCAnnotationList.java b/vdmj/src/main/java/com/fujitsu/vdmj/tc/annotations/TCAnnotationList.java index 9585e22a9..70452cdb4 100644 --- a/vdmj/src/main/java/com/fujitsu/vdmj/tc/annotations/TCAnnotationList.java +++ b/vdmj/src/main/java/com/fujitsu/vdmj/tc/annotations/TCAnnotationList.java @@ -34,7 +34,9 @@ import com.fujitsu.vdmj.tc.modules.TCModule; import com.fujitsu.vdmj.tc.types.TCType; import com.fujitsu.vdmj.typechecker.Environment; +import com.fujitsu.vdmj.typechecker.ModuleEnvironment; import com.fujitsu.vdmj.typechecker.NameScope; +import com.fujitsu.vdmj.typechecker.PrivateClassEnvironment; public class TCAnnotationList extends TCMappedList { @@ -78,6 +80,14 @@ public void tcBefore(TCModule m) } } + public void tcBefore(TCModule m, ModuleEnvironment e) + { + for (TCAnnotation annotation: this) + { + annotation.tcBefore(m, e); + } + } + public void tcBefore(TCClassDefinition clazz) { for (TCAnnotation annotation: this) @@ -86,6 +96,14 @@ public void tcBefore(TCClassDefinition clazz) } } + public void tcBefore(TCClassDefinition clazz, PrivateClassEnvironment self) + { + for (TCAnnotation annotation: this) + { + annotation.tcBefore(clazz, self); + } + } + public void tcAfter(TCDefinition def, TCType type, Environment env, NameScope scope) { for (TCAnnotation annotation: this) @@ -102,6 +120,14 @@ public void tcAfter(TCModule m) } } + public void tcAfter(TCModule m, ModuleEnvironment e) + { + for (TCAnnotation annotation: this) + { + annotation.tcAfter(m, e); + } + } + public void tcAfter(TCClassDefinition clazz) { for (TCAnnotation annotation: this) @@ -109,4 +135,12 @@ public void tcAfter(TCClassDefinition clazz) annotation.tcAfter(clazz); } } + + public void tcAfter(TCClassDefinition clazz, PrivateClassEnvironment self) + { + for (TCAnnotation annotation: this) + { + annotation.tcAfter(clazz, self); + } + } } diff --git a/vdmj/src/main/java/com/fujitsu/vdmj/typechecker/ClassTypeChecker.java b/vdmj/src/main/java/com/fujitsu/vdmj/typechecker/ClassTypeChecker.java index 6efacb999..6ca446d13 100644 --- a/vdmj/src/main/java/com/fujitsu/vdmj/typechecker/ClassTypeChecker.java +++ b/vdmj/src/main/java/com/fujitsu/vdmj/typechecker/ClassTypeChecker.java @@ -129,9 +129,15 @@ public void typeCheck() { for (TCClassDefinition c: classes) { + PrivateClassEnvironment self = new PrivateClassEnvironment(c, allClasses); + + if (pass == Pass.DEFS && c.annotations != null) + { + c.annotations.tcBefore(c, self); + } + try { - Environment self = new PrivateClassEnvironment(c, allClasses); c.typeCheckPass(pass, self); } catch (TypeCheckException te) @@ -146,6 +152,11 @@ public void typeCheck() } } } + + if (pass == Pass.DEFS && c.annotations != null) + { + c.annotations.tcAfter(c, self); + } } } diff --git a/vdmj/src/main/java/com/fujitsu/vdmj/typechecker/ModuleTypeChecker.java b/vdmj/src/main/java/com/fujitsu/vdmj/typechecker/ModuleTypeChecker.java index c87f67717..b83d49fb9 100644 --- a/vdmj/src/main/java/com/fujitsu/vdmj/typechecker/ModuleTypeChecker.java +++ b/vdmj/src/main/java/com/fujitsu/vdmj/typechecker/ModuleTypeChecker.java @@ -198,8 +198,12 @@ public void typeCheck() for (TCModule m: modules) { TypeComparator.setCurrentModule(m.name.getName()); - - Environment e = new ModuleEnvironment(m); + ModuleEnvironment e = new ModuleEnvironment(m); + + if (pass == Pass.DEFS && m.annotations != null) + { + m.annotations.tcBefore(m, e); + } for (TCDefinition d: m.defs) { @@ -223,6 +227,11 @@ public void typeCheck() } } } + + if (pass == Pass.DEFS && m.annotations != null) + { + m.annotations.tcAfter(m, e); + } } }