use of com.google.api.codegen.metacode.InitCodeNode in project toolkit by googleapis.
the class InitCodeTransformer method assertNoOverlap.
/**
* Given node `root` and `paths` describing subtrees of `root`, verify that all subtrees are
* disjoint. i.e., no two subtrees are the same, and no subtrees are themselves part of other
* subtrees.
*/
@VisibleForTesting
static void assertNoOverlap(InitCodeNode root, List<String> paths) {
// Keep track of the path that adds a node. If we detect collision we can report the two paths
// that reference the same nodes.
HashMap<InitCodeNode, String> refFrom = new HashMap<>();
// Keep track of the resource name entities. Configuring an entity twice or configuring an
// entity and the parent node at the same time will cause collision. Configuring two different
// entities will not.
Multimap<InitCodeNode, String> nodeEntities = HashMultimap.create();
// Below we'll perform depth-first search, keep a list of nodes we've seen but have not
// descended into. It doesn't really matter if we search breath- or depth-first; DFS is a little
// more efficient on average.
ArrayDeque<InitCodeNode> subNodes = new ArrayDeque<>();
for (String path : paths) {
subNodes.add(root.subTree(path));
String entity = FieldStructureParser.parseEntityName(path);
while (!subNodes.isEmpty()) {
InitCodeNode node = subNodes.pollLast();
String oldPath = refFrom.put(node, path);
if (oldPath == null) {
// The node has not been specified before, thus check if entity has been specified
checkArgument(entity == null || nodeEntities.put(node, entity), "Entity %s in path %s specified multiple times", entity, path);
} else {
// The node has been specified before. The will be no overlap if and only if:
// All previous paths are configuring entities
// This path is configuraing an entity
// The same entity is never specified before
checkArgument(entity != null && nodeEntities.containsKey(node), "SampleInitAttribute %s overlaps with %s", oldPath, path);
checkArgument(nodeEntities.put(node, entity), "Entity %s in path %s specified multiple times", entity, path);
}
subNodes.addAll(node.getChildren().values());
}
}
}
use of com.google.api.codegen.metacode.InitCodeNode in project toolkit by googleapis.
the class InitCodeTransformer method generateSurfaceInitCodeLines.
private List<InitCodeLineView> generateSurfaceInitCodeLines(MethodContext context, Iterable<InitCodeNode> specItemNode) {
boolean isFirstReadFileView = true;
List<InitCodeLineView> surfaceLines = new ArrayList<>();
for (InitCodeNode item : specItemNode) {
surfaceLines.add(generateSurfaceInitCodeLine(context, item, surfaceLines.isEmpty(), isFirstReadFileView));
isFirstReadFileView = isFirstReadFileView && item.getLineType() != InitCodeLineType.ReadFileInitLine;
}
return surfaceLines;
}
use of com.google.api.codegen.metacode.InitCodeNode in project toolkit by googleapis.
the class InitCodeTransformerTest method testOverlap.
@Test
public void testOverlap() {
InitCodeNode x = InitCodeNode.createWithChildren("x", InitCodeLineType.SimpleInitLine);
InitCodeNode y = InitCodeNode.createWithChildren("y", InitCodeLineType.SimpleInitLine);
InitCodeNode a = InitCodeNode.createWithChildren("a", InitCodeLineType.StructureInitLine, x, y);
InitCodeNode b = InitCodeNode.createWithChildren("b", InitCodeLineType.SimpleInitLine);
InitCodeNode root = InitCodeNode.createWithChildren("root", InitCodeLineType.StructureInitLine, a, b);
InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a", "b"));
InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a.x", "a.y"));
InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a%x", "a%y"));
assertThrows(() -> InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a", "a.x")));
assertThrows(() -> InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a", "a.y")));
assertThrows(() -> InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a", "a")));
assertThrows(() -> InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a.x", "a.x")));
assertThrows(() -> InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a.y", "a.y")));
assertThrows(() -> InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a", "a%x")));
assertThrows(() -> InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a%x", "a")));
assertThrows(() -> InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a.x%y", "a")));
assertThrows(() -> InitCodeTransformer.assertNoOverlap(root, ImmutableList.of("a%x", "a%x")));
}
use of com.google.api.codegen.metacode.InitCodeNode in project toolkit by googleapis.
the class PythonSampleImportTransformer method generateImportSection.
public ImportSectionView generateImportSection(MethodContext context, CallingForm form, OutputContext outputContext, ImportTypeTable initCodeTypeTable, Iterable<InitCodeNode> nodes) {
ImportSectionView.Builder imports = ImportSectionView.newBuilder();
ImmutableList.Builder<ImportFileView> appImports = ImmutableList.builder();
// First get all the imports generated from InitCodeTransformer
List<ImportFileView> initCodeAppImports = importSectionTransformer.generateImportSection(context, nodes).appImports();
appImports.addAll(initCodeAppImports);
// Then add more imports that other parts of the sample need
// For now we only need to special-case `enums`
boolean addEnumImports = outputContext.stringFormattedVariableTypes().stream().anyMatch(TypeModel::isEnum) || Streams.stream(nodes).map(InitCodeNode::getType).anyMatch(TypeModel::isEnum);
if (addEnumImports) {
ImportTypeView importTypeView = ImportTypeView.newBuilder().fullName("enums").type(ImportType.SimpleImport).nickname("").build();
ImportFileView enumImportView = ImportFileView.newBuilder().moduleName(context.getNamer().getVersionedDirectoryNamespace()).types(Collections.singletonList(importTypeView)).build();
if (!initCodeAppImports.contains(enumImportView)) {
appImports.add(enumImportView);
}
}
return imports.appImports(appImports.build()).build();
}
use of com.google.api.codegen.metacode.InitCodeNode in project toolkit by googleapis.
the class JavaSampleImportTransformer method addInitCodeImports.
@Override
protected void addInitCodeImports(MethodContext context, ImportTypeTable initCodeTypeTable, Iterable<InitCodeNode> nodes) {
super.addInitCodeImports(context, initCodeTypeTable, nodes);
ImportTypeTable typeTable = context.getTypeTable();
for (InitCodeNode node : nodes) {
switch(node.getLineType()) {
case ListInitLine:
typeTable.saveNicknameFor("java.util.List");
typeTable.saveNicknameFor("java.util.Arrays");
break;
case MapInitLine:
typeTable.saveNicknameFor("java.util.Map");
typeTable.saveNicknameFor("java.util.HashMap");
break;
case ReadFileInitLine:
typeTable.saveNicknameFor("java.nio.file.Files");
typeTable.saveNicknameFor("java.nio.file.Path");
typeTable.saveNicknameFor("java.nio.file.Paths");
break;
case SimpleInitLine:
case StructureInitLine:
// fall through
break;
default:
throw new IllegalArgumentException("Unrecognized line type: " + node.getLineType());
}
}
}
Aggregations