kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/util/schema/edges/edges.go (about) 1 /* 2 * Copyright 2016 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Package edges defines constants for Kythe edges. 18 package edges // import "kythe.io/kythe/go/util/schema/edges" 19 20 import ( 21 "regexp" 22 "strconv" 23 "strings" 24 25 "kythe.io/kythe/go/util/schema" 26 ) 27 28 // Prefix defines the common prefix for all Kythe edge kinds. 29 const Prefix = schema.Prefix + "edge/" 30 31 // Edge kind labels 32 const ( 33 ChildOf = Prefix + "childof" 34 Denotes = Prefix + "denotes" 35 Extends = Prefix + "extends" 36 ExtendsPrivate = Prefix + "extends/private" 37 ExtendsPrivateVirtual = Prefix + "extends/private/virtual" 38 ExtendsProtected = Prefix + "extends/protected" 39 ExtendsProtectedVirtual = Prefix + "extends/protected/virtual" 40 ExtendsPublic = Prefix + "extends/public" 41 ExtendsPublicVirtual = Prefix + "extends/public/virtual" 42 ExtendsVirtual = Prefix + "extends/virtual" 43 Generates = Prefix + "generates" 44 Named = Prefix + "named" 45 Overrides = Prefix + "overrides" 46 OverridesTransitive = Prefix + "overrides/transitive" 47 Param = Prefix + "param" 48 Satisfies = Prefix + "satisfies" 49 TParam = Prefix + "tparam" 50 Typed = Prefix + "typed" 51 ) 52 53 // Edge kinds associated with anchors 54 const ( 55 Defines = Prefix + "defines" 56 DefinesBinding = Prefix + "defines/binding" 57 Documents = Prefix + "documents" 58 Ref = Prefix + "ref" 59 RefCall = Prefix + "ref/call" 60 RefCallImplicit = Prefix + "ref/call/implicit" 61 RefDoc = Prefix + "ref/doc" 62 RefImplicit = Prefix + "ref/implicit" 63 RefImports = Prefix + "ref/imports" 64 RefInit = Prefix + "ref/init" 65 RefInitImplicit = Prefix + "ref/init/implicit" 66 RefWrites = Prefix + "ref/writes" 67 Tagged = Prefix + "tagged" 68 ) 69 70 // ParamIndex returns an edge label of the form "param.i" for the i given. 71 func ParamIndex(i int) string { return Param + "." + strconv.Itoa(i) } 72 73 // TParamIndex returns an edge label of the form "tparam.i" for the i given. 74 func TParamIndex(i int) string { return TParam + "." + strconv.Itoa(i) } 75 76 // revPrefix is used to distinguish reverse kinds from forward ones. 77 const revPrefix = "%" 78 79 // Mirror returns the opposite-directional edge label for kind. 80 func Mirror(kind string) string { 81 if rev := strings.TrimPrefix(kind, revPrefix); rev != kind { 82 return rev 83 } 84 return revPrefix + kind 85 } 86 87 // Canonical returns the canonical forward version of an edge kind. 88 func Canonical(kind string) string { return strings.TrimPrefix(kind, revPrefix) } 89 90 // IsForward reports whether kind is a forward edge kind. 91 func IsForward(kind string) bool { return !IsReverse(kind) } 92 93 // IsReverse reports whether kind is a reverse edge kind. 94 func IsReverse(kind string) bool { return strings.HasPrefix(kind, revPrefix) } 95 96 // IsVariant reports whether x is equal to or a subkind of y. 97 // For example, each of the following returns true: 98 // 99 // IsVariant("/kythe/edge/defines/binding", "/kythe/edge/defines") 100 // IsVariant("/kythe/edge/defines", "/kythe/edge/defines") 101 // 102 // Moreover IsVariant(x, y) == IsVariant(Mirror(x), Mirror(y)) for all x, y. 103 func IsVariant(x, y string) bool { return x == y || strings.HasPrefix(x, y+"/") } 104 105 // IsAnchorEdge reports whether kind is one associated with anchors. 106 func IsAnchorEdge(kind string) bool { 107 canon := Canonical(kind) 108 return IsVariant(canon, Defines) || IsVariant(canon, DefinesBinding) || 109 IsVariant(canon, Documents) || 110 IsVariant(canon, Ref) || IsVariant(canon, RefCall) 111 } 112 113 var ordinalKind = regexp.MustCompile(`^(.+)\.(\d+)$`) 114 115 // ParseOrdinal reports whether kind has an ordinal suffix (.nnn), and if so, 116 // returns the value of the ordinal as an integer. If not, the original kind is 117 // returned as written and ordinal == 0. 118 func ParseOrdinal(kind string) (base string, ordinal int, hasOrdinal bool) { 119 m := ordinalKind.FindStringSubmatch(kind) 120 if m == nil { 121 return kind, 0, false 122 } 123 ordinal, _ = strconv.Atoi(m[2]) 124 return m[1], ordinal, true 125 } 126 127 // OrdinalKind reports whether kind (which does not have an ordinal suffix) 128 // generally has an associated ordinal (e.g. /kythe/edge/param edges). 129 func OrdinalKind(kind string) bool { 130 switch Canonical(kind) { 131 case Param: 132 return true 133 default: 134 return false 135 } 136 }