logic: add type information of variable decl to name hierarchy

* implemented this feature for both, CXX and Java
* adjusted tests to reflect these changes
* added NameElement and NameHierarchy to Java code
* created more specialized JavaDeclName classes: JavaFunctionDeclName and JavaVariableDeclName
* implemented recording static modifier for Java methods and variables

fortune cookie message = You will enjoy true success in whatever you do.
This commit is contained in:
malte_langkabel
2017-07-28 09:12:32 +02:00
parent 2e117c4b6d
commit 01b1e0d6f1
21 changed files with 526 additions and 135 deletions
@@ -51,6 +51,7 @@ import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
import com.github.javaparser.symbolsolver.model.typesystem.*;
import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
import com.sourcetrail.name.JavaDeclName;
public class AstVisitor extends AstVisitorAdapter
{
@@ -77,7 +78,7 @@ public class AstVisitor extends AstVisitorAdapter
Name name = n.getName();
m_client.recordSymbolWithLocationAndScope(
JavaparserDeclNameResolver.getQualifiedName(name).toSerializedNameHierarchy(),
JavaparserDeclNameResolver.getQualifiedName(name).toNameHierarchy().serialize(),
SymbolKind.PACKAGE,
name.getRange(),
n.getRange(),
@@ -89,7 +90,7 @@ public class AstVisitor extends AstVisitorAdapter
{
name = name.getQualifier().get();
m_client.recordSymbol(
JavaparserDeclNameResolver.getQualifiedName(name).toSerializedNameHierarchy(),
JavaparserDeclNameResolver.getQualifiedName(name).toNameHierarchy().serialize(),
SymbolKind.PACKAGE,
AccessKind.NONE,
DefinitionKind.EXPLICIT
@@ -103,7 +104,7 @@ public class AstVisitor extends AstVisitorAdapter
{
SimpleName name = n.getName();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toNameHierarchy().serialize();
m_client.recordSymbolWithLocationAndScope(
qualifiedName, (n.isInterface() ? SymbolKind.INTERFACE : SymbolKind.CLASS),
@@ -171,7 +172,7 @@ public class AstVisitor extends AstVisitorAdapter
{
SimpleName name = n.getName();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toNameHierarchy().serialize();
m_client.recordSymbolWithLocationAndScope(
qualifiedName, SymbolKind.ENUM,
@@ -196,7 +197,7 @@ public class AstVisitor extends AstVisitorAdapter
@Override public void visit(final EnumConstantDeclaration n, final Void v)
{
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toNameHierarchy().serialize();
m_client.recordSymbolWithLocation(
qualifiedName, SymbolKind.ENUM_CONSTANT,
@@ -216,7 +217,7 @@ public class AstVisitor extends AstVisitorAdapter
{
SimpleName name = n.getName();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toNameHierarchy().serialize();
m_client.recordSymbolWithLocationAndScope(
qualifiedName, SymbolKind.METHOD,
@@ -237,7 +238,7 @@ public class AstVisitor extends AstVisitorAdapter
{
SimpleName name = n.getName();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toNameHierarchy().serialize();
m_client.recordSymbolWithLocationAndScope(
qualifiedName, SymbolKind.METHOD,
@@ -252,7 +253,7 @@ public class AstVisitor extends AstVisitorAdapter
com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration overridden = getOverridden(n);
if (overridden != null && (overridden instanceof JavaParserMethodDeclaration))
{
String overriddenName = JavaparserDeclNameResolver.getQualifiedDeclName(((JavaParserMethodDeclaration)overridden).getWrappedNode(), m_typeSolver).toSerializedNameHierarchy();
String overriddenName = JavaparserDeclNameResolver.getQualifiedDeclName(((JavaParserMethodDeclaration)overridden).getWrappedNode(), m_typeSolver).toNameHierarchy().serialize();
m_client.recordReference(
ReferenceKind.OVERRIDE, overriddenName, qualifiedName,
@@ -332,9 +333,8 @@ public class AstVisitor extends AstVisitorAdapter
for (VariableDeclarator declarator: n.getVariables())
{
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(declarator, m_typeSolver).toSerializedNameHierarchy();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(declarator, m_typeSolver).toNameHierarchy().serialize();
SimpleName name = declarator.getName();
m_client.recordSymbolWithLocation(
qualifiedName, SymbolKind.FIELD,
name.getRange(),
@@ -392,7 +392,7 @@ public class AstVisitor extends AstVisitorAdapter
if (n.isAsterisk())
{
String importedName = JavaparserDeclNameResolver.getQualifiedName(name).toSerializedNameHierarchy();
String importedName = JavaparserDeclNameResolver.getQualifiedName(name).toNameHierarchy().serialize();
for (DeclContext context: m_context)
{
m_client.recordReference(
@@ -445,7 +445,7 @@ public class AstVisitor extends AstVisitorAdapter
{
for (JavaDeclName importedDeclName: importedDeclNames)
{
String nameHierarchy = importedDeclName.toSerializedNameHierarchy();
String nameHierarchy = importedDeclName.toNameHierarchy().serialize();
for (DeclContext context: m_context)
{
m_client.recordReference(
@@ -475,7 +475,7 @@ public class AstVisitor extends AstVisitorAdapter
{
for (DeclContext context: m_context)
{
String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toSerializedNameHierarchy();
String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toNameHierarchy().serialize();
Range range = Range.range(0, 0, 0, 0);
@@ -519,7 +519,7 @@ public class AstVisitor extends AstVisitorAdapter
{
try
{
String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toSerializedNameHierarchy();
String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toNameHierarchy().serialize();
m_client.recordSymbol(
referencedName, SymbolKind.BUILTIN_TYPE,
@@ -547,7 +547,7 @@ public class AstVisitor extends AstVisitorAdapter
{
try
{
String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toSerializedNameHierarchy();
String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toNameHierarchy().serialize();
m_client.recordSymbol(
referencedName, SymbolKind.BUILTIN_TYPE, AccessKind.NONE, DefinitionKind.EXPLICIT
@@ -591,7 +591,7 @@ public class AstVisitor extends AstVisitorAdapter
{
if (var.getName().getIdentifier().equals(fieldName.getIdentifier()))
{
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(var, m_typeSolver).toSerializedNameHierarchy();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(var, m_typeSolver).toNameHierarchy().serialize();
for (DeclContext context: m_context)
{
m_client.recordReference(
@@ -656,7 +656,7 @@ public class AstVisitor extends AstVisitorAdapter
{
if (var.getName().getIdentifier().equals(e.getName().getIdentifier()))
{
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(var, m_typeSolver).toSerializedNameHierarchy();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(var, m_typeSolver).toNameHierarchy().serialize();
for (DeclContext context: m_context)
{
m_client.recordReference(
@@ -684,7 +684,7 @@ public class AstVisitor extends AstVisitorAdapter
{
if (wrappedNode.getAncestorOfType(FieldDeclaration.class).isPresent())
{
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName((VariableDeclarator)wrappedNode, m_typeSolver).toSerializedNameHierarchy();
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName((VariableDeclarator)wrappedNode, m_typeSolver).toNameHierarchy().serialize();
for (DeclContext context: m_context)
{
@@ -849,7 +849,7 @@ public class AstVisitor extends AstVisitorAdapter
if (method instanceof JavaParserMethodDeclaration)
{
MethodDeclaration wrappedNode = ((JavaParserMethodDeclaration)method).getWrappedNode();
qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(wrappedNode, m_typeSolver).toSerializedNameHierarchy();
qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(wrappedNode, m_typeSolver).toNameHierarchy().serialize();
}
else // todo: move this implementation somewhere else
{
@@ -884,7 +884,7 @@ public class AstVisitor extends AstVisitorAdapter
if (constructor instanceof JavaParserConstructorDeclaration)
{
ConstructorDeclaration wrappedNode = ((JavaParserConstructorDeclaration)constructor).getWrappedNode();
qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(wrappedNode, m_typeSolver).toSerializedNameHierarchy();
qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(wrappedNode, m_typeSolver).toNameHierarchy().serialize();
}
else // todo: move this implementation somewhere else
{
@@ -1,7 +1,5 @@
package com.sourcetrail;
import java.util.List;
import com.github.javaparser.ast.type.TypeParameter;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.BodyDeclaration;
@@ -43,4 +41,9 @@ public class CallableConstructorDecl implements CallableDecl
{
return new UnknownType();
}
public boolean isStatic()
{
return m_decl.isStatic();
}
}
@@ -13,4 +13,5 @@ public interface CallableDecl
public NodeList<TypeParameter> getTypeParameters();
public NodeList<Parameter> getParameters();
public Type getType();
public boolean isStatic();
}
@@ -1,7 +1,5 @@
package com.sourcetrail;
import java.util.List;
import com.github.javaparser.ast.type.TypeParameter;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.BodyDeclaration;
@@ -42,4 +40,9 @@ public class CallableMethodDecl implements CallableDecl
{
return m_decl.getType();
}
public boolean isStatic()
{
return m_decl.isStatic();
}
}
@@ -15,6 +15,10 @@ import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
import com.sourcetrail.name.JavaDeclName;
import com.sourcetrail.name.JavaFunctionDeclName;
import com.sourcetrail.name.JavaTypeName;
public class JavaSymbolSolverDeclNameResolver extends JavaNameResolver
{
public JavaSymbolSolverDeclNameResolver(TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
@@ -86,11 +90,12 @@ public class JavaSymbolSolverDeclNameResolver extends JavaNameResolver
));
}
declName = new JavaDeclName(
declName = new JavaFunctionDeclName(
methodDecl.getName(),
getTypeParameterNames(methodDecl.getTypeParameters()),
JavaSymbolSolverTypeNameResolver.getQualifiedTypeName(methodDecl.getReturnType(), m_typeSolver, m_ignoredContexts),
parameterNames
parameterNames,
methodDecl.isStatic()
);
declName.setParent(
@@ -5,7 +5,6 @@ import java.util.Optional;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.BodyDeclaration;
import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
import com.github.javaparser.symbolsolver.logic.InferenceVariableType;
@@ -20,6 +19,9 @@ import com.github.javaparser.symbolsolver.model.typesystem.TypeVariable;
import com.github.javaparser.symbolsolver.model.typesystem.VoidType;
import com.github.javaparser.symbolsolver.model.typesystem.Wildcard;
import com.sourcetrail.name.JavaDeclName;
import com.sourcetrail.name.JavaTypeName;
public class JavaSymbolSolverTypeNameResolver extends JavaNameResolver
{
public JavaSymbolSolverTypeNameResolver(TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
@@ -24,6 +24,11 @@ import com.github.javaparser.ast.expr.Name;
import com.github.javaparser.ast.type.TypeParameter;
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
import com.sourcetrail.name.JavaDeclName;
import com.sourcetrail.name.JavaFunctionDeclName;
import com.sourcetrail.name.JavaTypeName;
import com.sourcetrail.name.JavaVariableDeclName;
public class JavaparserDeclNameResolver extends JavaNameResolver
{
public JavaparserDeclNameResolver(TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
@@ -129,7 +134,17 @@ public class JavaparserDeclNameResolver extends JavaNameResolver
public JavaDeclName getDeclName(VariableDeclarator decl)
{
return new JavaDeclName(decl.getNameAsString());
ArrayList<BodyDeclaration> ignoredContextsForTypes = new ArrayList<BodyDeclaration>(m_ignoredContexts);
JavaTypeName typeName = JavaparserTypeNameResolver.getQualifiedTypeName(decl.getType(), m_typeSolver, ignoredContextsForTypes);
boolean isStatic = false;
Optional<FieldDeclaration> fieldDeclaration = decl.getAncestorOfType(FieldDeclaration.class);
if (fieldDeclaration.isPresent())
{
isStatic = fieldDeclaration.get().isStatic();
}
return new JavaVariableDeclName(decl.getNameAsString(), typeName, isStatic);
}
public JavaDeclName getDeclName(BodyDeclaration decl)
@@ -216,16 +231,19 @@ public class JavaparserDeclNameResolver extends JavaNameResolver
ArrayList<BodyDeclaration> ignoredContextsForTypes = new ArrayList<BodyDeclaration>(m_ignoredContexts);
ignoredContextsForTypes.add(decl.getWrappedNode()); // adding own decl
String name = decl.getName();
List<String> typeParameterNames = getTypeParameterNames(decl.getTypeParameters());
JavaTypeName returnTypeName = JavaparserTypeNameResolver.getQualifiedTypeName(decl.getType(), m_typeSolver, ignoredContextsForTypes);
List<JavaTypeName> parameterNames = new ArrayList<>();
for (Parameter parameter: decl.getParameters())
{
parameterNames.add(JavaparserTypeNameResolver.getQualifiedTypeName(parameter.getType(), m_typeSolver, ignoredContextsForTypes));
}
return new JavaDeclName(name, typeParameterNames, returnTypeName, parameterNames);
return new JavaFunctionDeclName(
decl.getName(),
getTypeParameterNames(decl.getTypeParameters()),
JavaparserTypeNameResolver.getQualifiedTypeName(decl.getType(), m_typeSolver, ignoredContextsForTypes),
parameterNames,
decl.isStatic()
);
}
private static BodyDeclaration getBodyDeclContext(Node decl)
@@ -4,10 +4,11 @@ import java.util.ArrayList;
import com.github.javaparser.ast.body.BodyDeclaration;
import com.github.javaparser.ast.type.*;
import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
import com.sourcetrail.name.JavaTypeName;
public class JavaparserTypeNameResolver extends JavaNameResolver
{
public JavaparserTypeNameResolver(TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
@@ -1,4 +1,4 @@
package com.sourcetrail;
package com.sourcetrail.name;
import java.util.List;
@@ -7,8 +7,6 @@ public class JavaDeclName
private JavaDeclName m_parent = null;
private String m_name = "";
private List<String> m_typeParameterNames = null;
private JavaTypeName m_returnTypeName = null;
private List<JavaTypeName> m_parameterNames = null;
public static JavaDeclName fromDotSeparatedString(String s)
{
@@ -34,25 +32,11 @@ public class JavaDeclName
m_name = name;
}
public JavaDeclName(String name, JavaTypeName returnTypeName, List<JavaTypeName> parameterNames)
{
m_name = name;
m_returnTypeName = returnTypeName;
m_parameterNames = parameterNames;
}
public JavaDeclName(String name, List<String> typeParameterNames)
{
m_name = name;
m_typeParameterNames = typeParameterNames;
}
public JavaDeclName(String name, List<String> typeParameterNames, JavaTypeName returnTypeName, List<JavaTypeName> parameterNames)
{
m_name = name;
m_typeParameterNames = typeParameterNames;
m_returnTypeName = returnTypeName;
m_parameterNames = parameterNames;
}
public void setParent(JavaDeclName parent)
{
@@ -69,26 +53,21 @@ public class JavaDeclName
return m_name;
}
public String toSerializedNameHierarchy()
public NameHierarchy toNameHierarchy()
{
String nameHierarchy = ".\tm";
NameHierarchy nameHierarchy;
if (m_parent != null)
{
nameHierarchy = m_parent.toSerializedNameHierarchy();
nameHierarchy += "\tn";
nameHierarchy = m_parent.toNameHierarchy();
}
nameHierarchy += m_name;
nameHierarchy += getTypeParameterString();
nameHierarchy += "\ts";
if (m_returnTypeName != null)
else
{
nameHierarchy += m_returnTypeName.toString();
nameHierarchy = new NameHierarchy();
}
nameHierarchy += "\tp";
nameHierarchy += getParameterString();
nameHierarchy.push(new NameElement(m_name + getTypeParameterString()));
return nameHierarchy;
}
@@ -107,25 +86,6 @@ public class JavaDeclName
return string;
}
private String getParameterString()
{
String string = "";
if (m_parameterNames != null)
{
string += "(";
for (int i = 0; i < m_parameterNames.size(); i++)
{
if (i != 0)
{
string += ", ";
}
string += m_parameterNames.get(i).toString();
}
string += ")";
}
return string;
}
public String getTypeParameterString()
{
String string = "";
@@ -0,0 +1,76 @@
package com.sourcetrail.name;
import java.util.List;
import java.util.Optional;
public class JavaFunctionDeclName extends JavaDeclName
{
private JavaTypeName m_returnTypeName = null;
private List<JavaTypeName> m_parameterNames = null;
private boolean m_isStatic = false;
public JavaFunctionDeclName(String name, JavaTypeName returnTypeName, List<JavaTypeName> parameterNames, boolean isStatic)
{
super(name);
m_returnTypeName = returnTypeName;
m_parameterNames = parameterNames;
m_isStatic = isStatic;
}
public JavaFunctionDeclName(String name, List<String> typeParameterNames, JavaTypeName returnTypeName, List<JavaTypeName> parameterNames, boolean isStatic)
{
super(name, typeParameterNames);
m_returnTypeName = returnTypeName;
m_parameterNames = parameterNames;
m_isStatic = isStatic;
}
@Override
public NameHierarchy toNameHierarchy()
{
String prefix = "";
if (m_isStatic)
{
prefix += "static ";
}
if (m_returnTypeName != null)
{
prefix += m_returnTypeName.toString();
}
String postfix = getParameterString();
NameHierarchy nameHierarchy = super.toNameHierarchy();
Optional<NameElement> nameElement = nameHierarchy.peek();
if (nameElement.isPresent())
{
String name = nameElement.get().getName();
nameHierarchy.pop();
nameHierarchy.push(new NameElement(name, prefix, postfix));
}
return nameHierarchy;
}
private String getParameterString()
{
String string = "(";
if (m_parameterNames != null)
{
for (int i = 0; i < m_parameterNames.size(); i++)
{
if (i != 0)
{
string += ", ";
}
string += m_parameterNames.get(i).toString();
}
}
string += ")";
return string;
}
}
@@ -1,4 +1,4 @@
package com.sourcetrail;
package com.sourcetrail.name;
import java.util.List;
@@ -48,18 +48,20 @@ public class JavaTypeName
return m_name;
}
public String toSerializedNameHierarchy()
public NameHierarchy toNameHierarchy()
{
String nameHierarchy = ".\tm";
NameHierarchy nameHierarchy;
if (m_parent != null)
{
nameHierarchy = m_parent.toSerializedNameHierarchy();
nameHierarchy += "\tn";
nameHierarchy = m_parent.toNameHierarchy();
}
else
{
nameHierarchy = new NameHierarchy();
}
nameHierarchy += m_name;
nameHierarchy += getTypeArgumentString();
nameHierarchy += "\ts\tp";
nameHierarchy.push(new NameElement(m_name + getTypeArgumentString()));
return nameHierarchy;
}
@@ -0,0 +1,42 @@
package com.sourcetrail.name;
import java.util.Optional;
public class JavaVariableDeclName extends JavaDeclName
{
private JavaTypeName m_typeName = null;
private boolean m_isStatic = false;
public JavaVariableDeclName(String name, JavaTypeName typeName, boolean isStatic)
{
super(name);
m_typeName = typeName;
m_isStatic = isStatic;
}
@Override
public NameHierarchy toNameHierarchy()
{
String prefix = "";
if (m_isStatic)
{
prefix += "static ";
}
if (m_typeName != null)
{
prefix += m_typeName.toString();
}
NameHierarchy nameHierarchy = super.toNameHierarchy();
Optional<NameElement> nameElement = nameHierarchy.peek();
if (nameElement.isPresent())
{
String name = nameElement.get().getName();
nameHierarchy.pop();
nameHierarchy.push(new NameElement(name, prefix, ""));
}
return nameHierarchy;
}
}
@@ -0,0 +1,52 @@
package com.sourcetrail.name;
public class NameElement
{
private String m_name = "";
private String m_prefix = "";
private String m_postfix = "";
public NameElement(String name)
{
if (name != null) m_name = name;
}
public NameElement(String name, String prefix, String postfix)
{
if (name != null) m_name = name;
if (prefix != null) m_prefix = prefix;
if (postfix != null) m_postfix = postfix;
}
String getName()
{
return m_name;
}
String getNameWithSignature()
{
String nameWithSignature = m_name;
if (m_prefix.length() > 0 || m_postfix.length() > 0)
{
nameWithSignature = m_prefix;
if (!m_name.isEmpty())
{
if (!m_prefix.isEmpty())
{
nameWithSignature += " ";
}
nameWithSignature += m_name;
}
nameWithSignature += m_postfix;
}
return nameWithSignature;
}
String serialize()
{
return m_name + "\ts" + m_prefix + "\tp" + m_postfix;
}
}
@@ -0,0 +1,69 @@
package com.sourcetrail.name;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class NameHierarchy
{
private List<NameElement> m_elements = new ArrayList<>();
public NameHierarchy()
{
}
public NameHierarchy(String name)
{
m_elements.add(new NameElement(name));
}
public NameHierarchy(NameElement name)
{
m_elements.add(name);
}
public NameHierarchy(List<NameElement> names)
{
m_elements.addAll(names);
}
public void push(NameElement element)
{
m_elements.add(element);
}
public void pop()
{
if (!m_elements.isEmpty())
{
m_elements.remove(m_elements.size() - 1);
}
}
public Optional<NameElement> peek()
{
if (!m_elements.isEmpty())
{
return Optional.of(m_elements.get(m_elements.size() - 1));
}
return Optional.empty();
}
public String serialize()
{
String serialized = ".\tm";
for (int i = 0; i < m_elements.size(); i++)
{
if (i != 0)
{
serialized += "\tn";
}
serialized += m_elements.get(i).serialize();
}
return serialized;
}
}