|
| 1 | +package com.github.plume.oss.drivers |
| 2 | + |
| 3 | +import io.shiftleft.codepropertygraph.generated.EdgeTypes |
| 4 | +import io.shiftleft.codepropertygraph.generated.nodes.* |
| 5 | +import org.slf4j.LoggerFactory |
| 6 | + |
| 7 | +/** A single utility to build out the CPG schema in other databases. |
| 8 | + */ |
| 9 | +object SchemaBuilder { |
| 10 | + |
| 11 | + private val logger = LoggerFactory.getLogger(getClass) |
| 12 | + |
| 13 | + val STRING_DEFAULT: String = "<empty>" |
| 14 | + val INT_DEFAULT: Int = -1 |
| 15 | + val LONG_DEFAULT: Long = -1L |
| 16 | + val BOOL_DEFAULT: Boolean = false |
| 17 | + val LIST_DEFAULT: Seq[String] = Seq.empty[String] |
| 18 | + |
| 19 | + /** Given a property, returns its known default. |
| 20 | + */ |
| 21 | + def getPropertyDefault(prop: String): Any = { |
| 22 | + import io.shiftleft.codepropertygraph.generated.PropertyNames.* |
| 23 | + prop match { |
| 24 | + case AST_PARENT_TYPE => STRING_DEFAULT |
| 25 | + case AST_PARENT_FULL_NAME => STRING_DEFAULT |
| 26 | + case NAME => STRING_DEFAULT |
| 27 | + case CODE => STRING_DEFAULT |
| 28 | + case ORDER => INT_DEFAULT |
| 29 | + case SIGNATURE => "" |
| 30 | + case ARGUMENT_INDEX => INT_DEFAULT |
| 31 | + case FULL_NAME => STRING_DEFAULT |
| 32 | + case TYPE_FULL_NAME => STRING_DEFAULT |
| 33 | + case TYPE_DECL_FULL_NAME => STRING_DEFAULT |
| 34 | + case IS_EXTERNAL => BOOL_DEFAULT |
| 35 | + case DISPATCH_TYPE => STRING_DEFAULT |
| 36 | + case LINE_NUMBER => INT_DEFAULT |
| 37 | + case COLUMN_NUMBER => INT_DEFAULT |
| 38 | + case LINE_NUMBER_END => INT_DEFAULT |
| 39 | + case COLUMN_NUMBER_END => INT_DEFAULT |
| 40 | + case OVERLAYS => LIST_DEFAULT |
| 41 | + case INHERITS_FROM_TYPE_FULL_NAME => LIST_DEFAULT |
| 42 | + case POSSIBLE_TYPES => LIST_DEFAULT |
| 43 | + case _ => STRING_DEFAULT |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + /** Edges that should be specified as being between any kind of vertex. |
| 48 | + */ |
| 49 | + val WILDCARD_EDGE_LABELS: Set[String] = |
| 50 | + Set(EdgeTypes.EVAL_TYPE, EdgeTypes.REF, EdgeTypes.INHERITS_FROM, EdgeTypes.ALIAS_OF) |
| 51 | + |
| 52 | + /** Determines if an edge type between two node types is valid. |
| 53 | + */ |
| 54 | + def checkEdgeConstraint(from: String, to: String, edge: String): Boolean = { |
| 55 | + val fromCheck = from match { |
| 56 | + case MetaData.Label => MetaData.Edges.Out.contains(edge) |
| 57 | + case File.Label => File.Edges.Out.contains(edge) |
| 58 | + case Method.Label => Method.Edges.Out.contains(edge) |
| 59 | + case MethodParameterIn.Label => MethodParameterIn.Edges.Out.contains(edge) |
| 60 | + case MethodParameterOut.Label => MethodParameterOut.Edges.Out.contains(edge) |
| 61 | + case MethodReturn.Label => MethodReturn.Edges.Out.contains(edge) |
| 62 | + case Modifier.Label => Modifier.Edges.Out.contains(edge) |
| 63 | + case Type.Label => Type.Edges.Out.contains(edge) |
| 64 | + case TypeDecl.Label => TypeDecl.Edges.Out.contains(edge) |
| 65 | + case TypeParameter.Label => TypeParameter.Edges.Out.contains(edge) |
| 66 | + case TypeArgument.Label => TypeArgument.Edges.Out.contains(edge) |
| 67 | + case Member.Label => Member.Edges.Out.contains(edge) |
| 68 | + case Namespace.Label => Namespace.Edges.Out.contains(edge) |
| 69 | + case NamespaceBlock.Label => NamespaceBlock.Edges.Out.contains(edge) |
| 70 | + case Literal.Label => Literal.Edges.Out.contains(edge) |
| 71 | + case Call.Label => Call.Edges.Out.contains(edge) |
| 72 | + case ClosureBinding.Label => ClosureBinding.Edges.Out.contains(edge) |
| 73 | + case Local.Label => Local.Edges.Out.contains(edge) |
| 74 | + case Identifier.Label => Identifier.Edges.Out.contains(edge) |
| 75 | + case FieldIdentifier.Label => FieldIdentifier.Edges.Out.contains(edge) |
| 76 | + case Return.Label => Return.Edges.Out.contains(edge) |
| 77 | + case Block.Label => Block.Edges.Out.contains(edge) |
| 78 | + case MethodRef.Label => MethodRef.Edges.Out.contains(edge) |
| 79 | + case TypeRef.Label => TypeRef.Edges.Out.contains(edge) |
| 80 | + case JumpTarget.Label => JumpTarget.Edges.Out.contains(edge) |
| 81 | + case ControlStructure.Label => ControlStructure.Edges.Out.contains(edge) |
| 82 | + case Annotation.Label => Annotation.Edges.Out.contains(edge) |
| 83 | + case AnnotationLiteral.Label => AnnotationLiteral.Edges.Out.contains(edge) |
| 84 | + case AnnotationParameter.Label => AnnotationParameter.Edges.Out.contains(edge) |
| 85 | + case AnnotationParameterAssign.Label => AnnotationParameterAssign.Edges.Out.contains(edge) |
| 86 | + case Unknown.Label => Unknown.Edges.Out.contains(edge) |
| 87 | + case x => |
| 88 | + logger.warn(s"Unhandled node type '$x'") |
| 89 | + false |
| 90 | + } |
| 91 | + val toCheck = to match { |
| 92 | + case MetaData.Label => MetaData.Edges.In.contains(edge) |
| 93 | + case File.Label => File.Edges.In.contains(edge) |
| 94 | + case Method.Label => Method.Edges.In.contains(edge) |
| 95 | + case MethodParameterIn.Label => MethodParameterIn.Edges.In.contains(edge) |
| 96 | + case MethodParameterOut.Label => MethodParameterOut.Edges.In.contains(edge) |
| 97 | + case MethodReturn.Label => MethodReturn.Edges.In.contains(edge) |
| 98 | + case Modifier.Label => Modifier.Edges.In.contains(edge) |
| 99 | + case Type.Label => Type.Edges.In.contains(edge) |
| 100 | + case TypeDecl.Label => TypeDecl.Edges.In.contains(edge) |
| 101 | + case TypeParameter.Label => TypeParameter.Edges.In.contains(edge) |
| 102 | + case TypeArgument.Label => TypeArgument.Edges.In.contains(edge) |
| 103 | + case Member.Label => Member.Edges.In.contains(edge) |
| 104 | + case Namespace.Label => Namespace.Edges.In.contains(edge) |
| 105 | + case NamespaceBlock.Label => NamespaceBlock.Edges.In.contains(edge) |
| 106 | + case Literal.Label => Literal.Edges.In.contains(edge) |
| 107 | + case Call.Label => Call.Edges.In.contains(edge) |
| 108 | + case ClosureBinding.Label => ClosureBinding.Edges.Out.contains(edge) |
| 109 | + case Local.Label => Local.Edges.In.contains(edge) |
| 110 | + case Identifier.Label => Identifier.Edges.In.contains(edge) |
| 111 | + case FieldIdentifier.Label => FieldIdentifier.Edges.In.contains(edge) |
| 112 | + case Return.Label => Return.Edges.In.contains(edge) |
| 113 | + case Block.Label => Block.Edges.In.contains(edge) |
| 114 | + case MethodRef.Label => MethodRef.Edges.In.contains(edge) |
| 115 | + case TypeRef.Label => TypeRef.Edges.In.contains(edge) |
| 116 | + case JumpTarget.Label => JumpTarget.Edges.In.contains(edge) |
| 117 | + case ControlStructure.Label => ControlStructure.Edges.In.contains(edge) |
| 118 | + case Annotation.Label => Annotation.Edges.In.contains(edge) |
| 119 | + case AnnotationLiteral.Label => AnnotationLiteral.Edges.In.contains(edge) |
| 120 | + case AnnotationParameter.Label => AnnotationParameter.Edges.In.contains(edge) |
| 121 | + case AnnotationParameterAssign.Label => AnnotationParameterAssign.Edges.In.contains(edge) |
| 122 | + case Unknown.Label => Unknown.Edges.In.contains(edge) |
| 123 | + case x => |
| 124 | + logger.warn(s"Unhandled node type '$x'") |
| 125 | + false |
| 126 | + } |
| 127 | + |
| 128 | + fromCheck && toCheck |
| 129 | + } |
| 130 | + |
| 131 | + def allProperties: Set[String] = NodeToProperties.flatMap(_._2).toSet |
| 132 | + |
| 133 | + val NodeToProperties: Map[String, Set[String]] = Map( |
| 134 | + MetaData.Label -> MetaData.PropertyNames.all, |
| 135 | + File.Label -> File.PropertyNames.all, |
| 136 | + Method.Label -> Method.PropertyNames.all, |
| 137 | + MethodParameterIn.Label -> MethodParameterIn.PropertyNames.all, |
| 138 | + MethodParameterOut.Label -> MethodParameterOut.PropertyNames.all, |
| 139 | + MethodReturn.Label -> MethodReturn.PropertyNames.all, |
| 140 | + Modifier.Label -> Modifier.PropertyNames.all, |
| 141 | + Type.Label -> Type.PropertyNames.all, |
| 142 | + TypeDecl.Label -> TypeDecl.PropertyNames.all, |
| 143 | + TypeParameter.Label -> TypeParameter.PropertyNames.all, |
| 144 | + TypeArgument.Label -> TypeArgument.PropertyNames.all, |
| 145 | + Member.Label -> Member.PropertyNames.all, |
| 146 | + Namespace.Label -> Namespace.PropertyNames.all, |
| 147 | + NamespaceBlock.Label -> NamespaceBlock.PropertyNames.all, |
| 148 | + Literal.Label -> Literal.PropertyNames.all, |
| 149 | + Call.Label -> Call.PropertyNames.all, |
| 150 | + Local.Label -> Local.PropertyNames.all, |
| 151 | + Identifier.Label -> Identifier.PropertyNames.all, |
| 152 | + FieldIdentifier.Label -> FieldIdentifier.PropertyNames.all, |
| 153 | + Return.Label -> Return.PropertyNames.all, |
| 154 | + Block.Label -> Block.PropertyNames.all, |
| 155 | + MethodRef.Label -> MethodRef.PropertyNames.all, |
| 156 | + TypeRef.Label -> TypeRef.PropertyNames.all, |
| 157 | + JumpTarget.Label -> JumpTarget.PropertyNames.all, |
| 158 | + ControlStructure.Label -> ControlStructure.PropertyNames.all, |
| 159 | + Annotation.Label -> Annotation.PropertyNames.all, |
| 160 | + AnnotationLiteral.Label -> AnnotationLiteral.PropertyNames.all, |
| 161 | + AnnotationParameter.Label -> AnnotationParameter.PropertyNames.all, |
| 162 | + AnnotationParameterAssign.Label -> AnnotationParameterAssign.PropertyNames.all, |
| 163 | + Unknown.Label -> Unknown.PropertyNames.all |
| 164 | + ) |
| 165 | + |
| 166 | +} |
0 commit comments