From f049b6a9a7c64fe2193e15d541955a69b0701888 Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Thu, 4 Jan 2024 17:00:06 +0100 Subject: [PATCH] Refactor ExplicitStatement Rather than having a superclass, just create StatementDeclarations as a host for the two factory methods. Implementations are completely internal and do not leak outside of this class. We also optimize memory footprint by using two versions of each class -- one storing file/line as ints, the other one as shorts. This ends up saving a few bytes of memory. Eliminate the InFile specialization, as it is not used anywhere really. Also renale atPosition() to inText() to more closely align naming. JIRA: YANGTOOLS-1150 Change-Id: Ib5a20e45f645f00fac8d1d27c48dd4dcab16fb17 Signed-off-by: Robert Varga --- .../model/api/meta/StatementDeclaration.java | 8 +- .../model/spi/meta/StatementDeclarations.java | 151 ++++++++++++++++++ .../spi/meta/StatementDeclarationsTest.java | 12 +- .../rfc7950/repo/StatementContextVisitor.java | 5 +- .../repo/StatementSourceReferenceHandler.java | 6 +- .../repo/YangIRSourceInfoExtractor.java | 8 +- .../parser/spi/source/ExplicitStatement.java | 135 ---------------- 7 files changed, 173 insertions(+), 152 deletions(-) create mode 100644 model/yang-model-spi/src/main/java/org/opendaylight/yangtools/yang/model/spi/meta/StatementDeclarations.java rename parser/yang-parser-spi/src/test/java/org/opendaylight/yangtools/yang/parser/spi/source/ExplicitStatementTest.java => model/yang-model-spi/src/test/java/org/opendaylight/yangtools/yang/model/spi/meta/StatementDeclarationsTest.java (57%) delete mode 100644 parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/ExplicitStatement.java diff --git a/model/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/meta/StatementDeclaration.java b/model/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/meta/StatementDeclaration.java index 4108e42709..21c4bfaa0f 100644 --- a/model/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/meta/StatementDeclaration.java +++ b/model/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/meta/StatementDeclaration.java @@ -12,7 +12,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; /** - * A {@link StatementSourceReference} which acts as its own {@link DeclarationReference}. + * A {@link StatementSourceReference} which acts as its own {@link DeclarationReference}, i.e. referring to a statement + * source present in textual source format. */ @NonNullByDefault public abstract class StatementDeclaration extends StatementSourceReference implements DeclarationReference { @@ -29,6 +30,11 @@ public abstract class StatementDeclaration extends StatementSourceReference impl protected final int column() { return startColumn(); } + + @Override + protected @Nullable String file() { + return null; + } } /** diff --git a/model/yang-model-spi/src/main/java/org/opendaylight/yangtools/yang/model/spi/meta/StatementDeclarations.java b/model/yang-model-spi/src/main/java/org/opendaylight/yangtools/yang/model/spi/meta/StatementDeclarations.java new file mode 100644 index 0000000000..b1d4dcbe0c --- /dev/null +++ b/model/yang-model-spi/src/main/java/org/opendaylight/yangtools/yang/model/spi/meta/StatementDeclarations.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2021 PANTHEON.tech, s.r.o. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.model.spi.meta; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.opendaylight.yangtools.yang.model.api.meta.StatementDeclaration; +import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference; + +/** + * Factory for creating default {@link StatementDeclaration} implementations. This is preferred source of + * {@link StatementSourceReference} for implementations of YANG / YIN statement stream sources. + * + *

+ * To create source reference use one of this static factories: + *

+ */ +public final class StatementDeclarations { + private static class InTextInt extends StatementDeclaration.InText { + private final int startLine; + private final int startColumn; + + InTextInt(final int startLine, final int startColumn) { + this.startLine = startLine; + this.startColumn = startColumn; + } + + @Override + public int startLine() { + return startLine; + } + + @Override + public int startColumn() { + return startColumn; + } + } + + private static class InTextShort extends StatementDeclaration.InText { + private final short startLine; + private final short startColumn; + + InTextShort(final short startLine, final short startColumn) { + this.startLine = startLine; + this.startColumn = startColumn; + } + + @Override + public int startLine() { + return Short.toUnsignedInt(startLine); + } + + @Override + public int startColumn() { + return Short.toUnsignedInt(startColumn); + } + } + + private static final class InTextFileInt extends StatementDeclaration.InTextFile { + private final @NonNull String fileName; + private final int startLine; + private final int startColumn; + + InTextFileInt(final String fileName, final int startLine, final int startColumn) { + this.fileName = requireNonNull(fileName); + this.startLine = startLine; + this.startColumn = startColumn; + } + + @Override + public int startLine() { + return startLine; + } + + @Override + public int startColumn() { + return startColumn; + } + + @Override + public String fileName() { + return fileName; + } + } + + private static final class InTextFileShort extends StatementDeclaration.InTextFile { + private final @NonNull String fileName; + private final short startLine; + private final short startColumn; + + InTextFileShort(final String fileName, final short startLine, final short startColumn) { + this.fileName = requireNonNull(fileName); + this.startLine = startLine; + this.startColumn = startColumn; + } + + @Override + public int startLine() { + return Short.toUnsignedInt(startLine); + } + + @Override + public int startColumn() { + return Short.toUnsignedInt(startColumn); + } + + @Override + public String fileName() { + return fileName; + } + } + + private StatementDeclarations() { + // Hidden on purpose + } + + public static StatementDeclaration.@NonNull InText inText(final int startLine, final int startColumn) { + return canUseShort(startLine, startColumn) ? new InTextShort((short) startLine, (short) startColumn) + : new InTextInt(startLine, startColumn); + } + + public static StatementDeclaration.@NonNull InText inText(final @Nullable String fileName, final int startLine, + final int startColumn) { + if (fileName == null) { + return inText(startLine, startColumn); + } + checkArgument(!fileName.isEmpty(), "Invalid empty file name"); + return canUseShort(startLine, startColumn) + ? new InTextFileShort(fileName, (short) startLine, (short) startColumn) + : new InTextFileInt(fileName, startLine, startColumn); + } + + private static boolean canUseShort(final int startLine, final int startColumn) { + checkArgument(startLine > 0, "Invalid start line %s", startLine); + checkArgument(startColumn > 0, "Invalid start column %s", startColumn); + return startLine <= 65535 && startColumn <= 65535; + } +} diff --git a/parser/yang-parser-spi/src/test/java/org/opendaylight/yangtools/yang/parser/spi/source/ExplicitStatementTest.java b/model/yang-model-spi/src/test/java/org/opendaylight/yangtools/yang/model/spi/meta/StatementDeclarationsTest.java similarity index 57% rename from parser/yang-parser-spi/src/test/java/org/opendaylight/yangtools/yang/parser/spi/source/ExplicitStatementTest.java rename to model/yang-model-spi/src/test/java/org/opendaylight/yangtools/yang/model/spi/meta/StatementDeclarationsTest.java index b3f8792577..6695af03f3 100644 --- a/parser/yang-parser-spi/src/test/java/org/opendaylight/yangtools/yang/parser/spi/source/ExplicitStatementTest.java +++ b/model/yang-model-spi/src/test/java/org/opendaylight/yangtools/yang/model/spi/meta/StatementDeclarationsTest.java @@ -5,23 +5,23 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ -package org.opendaylight.yangtools.yang.parser.spi.source; +package org.opendaylight.yangtools.yang.model.spi.meta; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin; -class ExplicitStatementTest { +class StatementDeclarationsTest { @Test void testStatementSource() { - assertEquals(StatementOrigin.DECLARATION, ExplicitStatement.inFile("foo").statementOrigin()); + assertEquals(StatementOrigin.DECLARATION, StatementDeclarations.inText(1, 1).statementOrigin()); } @Test void testToString() { - assertEquals("foo", ExplicitStatement.inFile("foo").toString()); - assertEquals(":5:10", ExplicitStatement.atPosition(5, 10).toString()); - assertEquals("foo:5:10", ExplicitStatement.atPosition("foo", 5, 10).toString()); + assertEquals(":5:10", StatementDeclarations.inText(5, 10).toString()); + assertEquals("foo:5:10", StatementDeclarations.inText("foo", 5, 10).toString()); + assertEquals(":1:1", StatementDeclarations.inText(null, 1, 1).toString()); } } diff --git a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/StatementContextVisitor.java b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/StatementContextVisitor.java index cf53aebd94..e64454201e 100644 --- a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/StatementContextVisitor.java +++ b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/StatementContextVisitor.java @@ -19,7 +19,7 @@ import org.opendaylight.yangtools.yang.ir.IRKeyword.Qualified; import org.opendaylight.yangtools.yang.ir.IRStatement; import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference; -import org.opendaylight.yangtools.yang.parser.spi.source.ExplicitStatement; +import org.opendaylight.yangtools.yang.model.spi.meta.StatementDeclarations; import org.opendaylight.yangtools.yang.parser.spi.source.PrefixResolver; import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition; import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter; @@ -96,8 +96,7 @@ class StatementContextVisitor { // Slow-path allocation of a new statement private boolean processNewStatement(final int myOffset, final IRStatement stmt) { - final StatementSourceReference ref = ExplicitStatement.atPosition(sourceName, stmt.startLine(), - stmt.startColumn() + 1); + final var ref = StatementDeclarations.inText(sourceName, stmt.startLine(), stmt.startColumn() + 1); final QName def = getValidStatementDefinition(stmt.keyword(), ref); if (def == null) { return false; diff --git a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/StatementSourceReferenceHandler.java b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/StatementSourceReferenceHandler.java index 091dc43c46..6e666d8430 100644 --- a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/StatementSourceReferenceHandler.java +++ b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/StatementSourceReferenceHandler.java @@ -12,7 +12,7 @@ import static java.util.Objects.requireNonNull; import java.util.ArrayDeque; import java.util.Deque; import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference; -import org.opendaylight.yangtools.yang.parser.spi.source.ExplicitStatement; +import org.opendaylight.yangtools.yang.model.spi.meta.StatementDeclarations; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -54,7 +54,7 @@ final class StatementSourceReferenceHandler extends DefaultHandler { @Override public void setDocumentLocator(final Locator locator) { // Save the locator, so that it can be used later for line tracking when traversing nodes. - this.documentLocator = locator; + documentLocator = locator; } @Override @@ -67,7 +67,7 @@ final class StatementSourceReferenceHandler extends DefaultHandler { el.setAttributeNS(attributes.getURI(i), attributes.getQName(i), attributes.getValue(i)); } - final StatementSourceReference ref = ExplicitStatement.atPosition(file, documentLocator.getLineNumber(), + final var ref = StatementDeclarations.inText(file, documentLocator.getLineNumber(), documentLocator.getColumnNumber()); el.setUserData(USER_DATA_KEY, ref, null); stack.push(el); diff --git a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/YangIRSourceInfoExtractor.java b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/YangIRSourceInfoExtractor.java index c038ed74bc..a1363858b3 100644 --- a/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/YangIRSourceInfoExtractor.java +++ b/parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/repo/YangIRSourceInfoExtractor.java @@ -18,15 +18,15 @@ import org.opendaylight.yangtools.yang.ir.IRKeyword; import org.opendaylight.yangtools.yang.ir.IRStatement; import org.opendaylight.yangtools.yang.ir.YangIRSchemaSource; import org.opendaylight.yangtools.yang.model.api.YangStmtMapping; -import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference; +import org.opendaylight.yangtools.yang.model.api.meta.StatementDeclaration; import org.opendaylight.yangtools.yang.model.api.source.SourceDependency.BelongsTo; import org.opendaylight.yangtools.yang.model.api.source.SourceDependency.Import; import org.opendaylight.yangtools.yang.model.api.source.SourceDependency.Include; import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.spi.meta.StatementDeclarations; import org.opendaylight.yangtools.yang.model.spi.source.SourceInfo; import org.opendaylight.yangtools.yang.model.spi.source.YangTextSource; import org.opendaylight.yangtools.yang.parser.api.YangSyntaxErrorException; -import org.opendaylight.yangtools.yang.parser.spi.source.ExplicitStatement; /** * Utility class for extract {@link SourceInfo} from a {@link YangIRSchemaSource}. @@ -186,7 +186,7 @@ public final class YangIRSourceInfoExtractor { return ArgumentContextUtils.rfc6020().stringFromStringContext(arg, ref); } - private static StatementSourceReference refOf(final SourceIdentifier source, final IRStatement stmt) { - return ExplicitStatement.atPosition(source.name().getLocalName(), stmt.startLine(), stmt.startColumn() + 1); + private static StatementDeclaration.InText refOf(final SourceIdentifier source, final IRStatement stmt) { + return StatementDeclarations.inText(source.name().getLocalName(), stmt.startLine(), stmt.startColumn() + 1); } } diff --git a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/ExplicitStatement.java b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/ExplicitStatement.java deleted file mode 100644 index 4d9390c244..0000000000 --- a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/source/ExplicitStatement.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. - * Copyright (c) 2021 PANTHEON.tech, s.r.o. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ -package org.opendaylight.yangtools.yang.parser.spi.source; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Verify.verifyNotNull; - -import com.google.common.annotations.Beta; -import java.util.Objects; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.opendaylight.yangtools.yang.model.api.meta.DeclarationInFile; -import org.opendaylight.yangtools.yang.model.api.meta.DeclarationInText; -import org.opendaylight.yangtools.yang.model.api.meta.StatementDeclaration; -import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference; - -/** - * Reference of statement source present in textual source format. Utility implementation - * of {@link StatementSourceReference} for textual sources, this is preferred {@link StatementSourceReference} - * for implementations of YANG / YIN statement stream sources. - * - *

- * To create source reference use one of this static factories: - *

    - *
  • {@link #atPosition(String, int, int)} - provides most specific reference of statement location, this is most - * preferred since it provides most context to debug YANG model.
  • - *
  • {@link #atPosition(int, int)}- provides location in text without knowing the name of the text file.
  • - *
  • {@link #inFile(String)}- provides a source name.
  • - *
- */ -@Beta -public abstract class ExplicitStatement extends StatementDeclaration { - private static final class InFile extends ExplicitStatement implements DeclarationInFile { - InFile(final String fileName) { - super(fileName, -1, -1); - checkArgument(!fileName.isEmpty(), "Invalid empty file name"); - } - - @Override - public String fileName() { - return verifyNotNull(file()); - } - } - - private static class InText extends ExplicitStatement implements DeclarationInText { - InText(final String file, final int line, final int column) { - super(file, line, column); - checkArgument(line > 0, "Invalid start line %s", line); - checkArgument(column > 0, "Invalid start column %s", column); - } - - @Override - public int startLine() { - return line(); - } - - @Override - public int startColumn() { - return column(); - } - } - - private static final class InTextFile extends InText implements DeclarationInFile { - InTextFile(final String fileName, final int line, final int column) { - super(fileName, line, column); - checkArgument(!fileName.isEmpty(), "Invalid empty file name"); - } - - @Override - public String fileName() { - return verifyNotNull(file()); - } - } - - private final String file; - private final int line; - private final int column; - - ExplicitStatement(final String file, final int line, final int column) { - this.file = file; - this.line = line; - this.column = column; - } - - public static @NonNull ExplicitStatement atPosition(final int line, final int column) { - return new InText(null, line, column); - } - - public static @NonNull ExplicitStatement atPosition(final @Nullable String fileName, final int line, - final int column) { - return fileName == null ? atPosition(line, column) : new InTextFile(fileName, line, column); - } - - public static @NonNull ExplicitStatement inFile(final @NonNull String fileName) { - return new InFile(fileName); - } - - @Override - public final int hashCode() { - return Objects.hash(file(), line(), column()); - } - - @Override - public final boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null || !getClass().equals(obj.getClass())) { - return false; - } - final ExplicitStatement other = (ExplicitStatement) obj; - return line == other.line && column == other.column && Objects.equals(file, other.file); - } - - @Override - protected final String file() { - return file; - } - - @Override - protected final int line() { - return line; - } - - @Override - protected final int column() { - return column; - } -} -- 2.36.6