| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 import 'dart:convert'; | 5 import 'dart:convert'; |
| 6 import 'dart:io'; | |
| 7 | 6 |
| 8 import 'package:analyzer/dart/ast/ast.dart'; | 7 import 'package:analyzer/dart/ast/ast.dart'; |
| 9 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; | 8 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; |
| 10 import 'package:analyzer/dart/ast/syntactic_entity.dart'; | 9 import 'package:analyzer/dart/ast/syntactic_entity.dart'; |
| 11 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| 12 import 'package:analyzer/dart/ast/visitor.dart'; | 11 import 'package:analyzer/dart/ast/visitor.dart'; |
| 13 import 'package:analyzer/dart/element/element.dart'; | 12 import 'package:analyzer/dart/element/element.dart'; |
| 14 import 'package:analyzer/dart/element/type.dart'; | 13 import 'package:analyzer/dart/element/type.dart'; |
| 15 import 'package:analyzer/dart/element/visitor.dart'; | 14 import 'package:analyzer/dart/element/visitor.dart'; |
| 16 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; | 15 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; |
| 16 import 'package:analyzer_plugin/protocol/protocol_common.dart' |
| 17 show KytheEntry, KytheVName; |
| 17 | 18 |
| 18 import 'schema.dart' as schema; | 19 import 'schema.dart' as schema; |
| 19 | 20 |
| 20 const int _notFound = -1; | 21 const int _notFound = -1; |
| 21 | 22 |
| 22 /// Computes analysis of the given compilation [unit]. | 23 /// Computes analysis of the given compilation [unit]. The unit is assumed to |
| 23 /// | 24 /// exist in the given [corpus] and to have the given text [contents]. Analysis |
| 24 /// [unit] is the compilation unit to be analyzed; it is assumed to exist in the | 25 /// results are returned as a list of [KytheEntry] objects. |
| 25 /// given [corpus] and to have the given text [contents]. Analysis results are | 26 List<KytheEntry> computeIndex( |
| 26 /// returned as a list of Kythe [pb_Entry] objects. | |
| 27 List<pb_Entry> computeIndex( | |
| 28 String corpus, CompilationUnit unit, String contents) { | 27 String corpus, CompilationUnit unit, String contents) { |
| 29 final List<pb_Entry> entries = []; | 28 final List<KytheEntry> entries = []; |
| 30 var visitor = new KytheDartVisitor( | 29 var visitor = new KytheDartVisitor( |
| 31 entries, | 30 entries, |
| 32 corpus, | 31 corpus, |
| 33 new InheritanceManager( | 32 new InheritanceManager( |
| 34 resolutionMap.elementDeclaredByCompilationUnit(unit).library), | 33 resolutionMap.elementDeclaredByCompilationUnit(unit).library), |
| 35 contents); | 34 contents); |
| 36 unit.accept(visitor); | 35 unit.accept(visitor); |
| 37 return entries; | 36 return entries; |
| 38 } | 37 } |
| 39 | 38 |
| 40 /// Outputs analysis of the given compilation [unit] to the parent process. | |
| 41 /// | |
| 42 /// [unit] is the compilation unit to be analyzed; it is assumed to exist in the | |
| 43 /// given [corpus] and to have the given text [contents]. Analysis results are | |
| 44 /// sent do the parent process as raw Kythe [Entry] objects. | |
| 45 void writeOutIndex(CompilationUnit unit, String corpus, String contents) { | |
| 46 List<pb_Entry> entries = computeIndex(corpus, unit, contents); | |
| 47 for (pb_Entry e in entries) { | |
| 48 assert(e.source != null); | |
| 49 if (e.edgeKind == "") { | |
| 50 assert(e.target.toString() == ""); | |
| 51 } | |
| 52 _sendToParentProcess(e); | |
| 53 } | |
| 54 } | |
| 55 | |
| 56 /// Given some [ConstructorElement], this method returns '<class-name>' as the | 39 /// Given some [ConstructorElement], this method returns '<class-name>' as the |
| 57 /// name of the constructor, unless the constructor is a named constructor | 40 /// name of the constructor, unless the constructor is a named constructor in |
| 58 /// in which '<class-name>.<constructor-name>' is returned. | 41 /// which '<class-name>.<constructor-name>' is returned. |
| 59 String _computeConstructorElementName(ConstructorElement element) { | 42 String _computeConstructorElementName(ConstructorElement element) { |
| 60 assert(element != null); | 43 assert(element != null); |
| 61 var name = element.enclosingElement.name; | 44 var name = element.enclosingElement.name; |
| 62 var constructorName = element.name; | 45 var constructorName = element.name; |
| 63 if (!constructorName.isEmpty) { | 46 if (!constructorName.isEmpty) { |
| 64 name = name + '.' + constructorName; | 47 name = name + '.' + constructorName; |
| 65 } | 48 } |
| 66 return name; | 49 return name; |
| 67 } | 50 } |
| 68 | 51 |
| 69 /// Create an anchor signature of the form '<start>-<end>'. | 52 /// Create an anchor signature of the form '<start>-<end>'. |
| 70 String _getAnchorSignature(int start, int end) { | 53 String _getAnchorSignature(int start, int end) { |
| 71 return '$start-$end'; | 54 return '$start-$end'; |
| 72 } | 55 } |
| 73 | 56 |
| 74 String _getPath(Element e) { | 57 String _getPath(Element e) { |
| 58 // TODO(jwren) This method simply serves to provide the WORKSPACE relative |
| 59 // path for sources in Elements, it needs to be written in a more robust way. |
| 75 // TODO(jwren) figure out what source generates a e != null, but | 60 // TODO(jwren) figure out what source generates a e != null, but |
| 76 // e.source == null to ensure that it is not a bug somewhere in the stack. | 61 // e.source == null to ensure that it is not a bug somewhere in the stack. |
| 77 if (e == null || e.source == null) { | 62 if (e == null || e.source == null) { |
| 78 // null sometimes when the element is used to generate the node type | 63 // null sometimes when the element is used to generate the node type |
| 79 // "dynamic" | 64 // "dynamic" |
| 80 return ''; | 65 return ''; |
| 81 } | 66 } |
| 82 var path = e.source.fullName; | 67 var path = e.source.fullName; |
| 83 assert(path.lastIndexOf('CORPUS_NAME') != -1); | 68 assert(path.lastIndexOf('CORPUS_NAME') != -1); |
| 84 return path.substring(path.lastIndexOf('CORPUS_NAME') + 12); | 69 return path.substring(path.lastIndexOf('CORPUS_NAME') + 12); |
| 85 } | 70 } |
| 86 | 71 |
| 87 /// If a non-null element is passed, the [SignatureElementVisitor] is used to | 72 /// If a non-null element is passed, the [SignatureElementVisitor] is used to |
| 88 /// generate and return a [String] signature, otherwise | 73 /// generate and return a [String] signature, otherwise [schema.DYNAMIC_KIND] is |
| 89 /// [schema.DYNAMIC_KIND] is returned. | 74 /// returned. |
| 90 String _getSignature(Element element, String nodeKind, String corpus) { | 75 String _getSignature(Element element, String nodeKind, String corpus) { |
| 91 assert(nodeKind != schema.ANCHOR_KIND); // Call _getAnchorSignature instead | 76 assert(nodeKind != schema.ANCHOR_KIND); // Call _getAnchorSignature instead |
| 92 if (element == null) { | 77 if (element == null) { |
| 93 return schema.DYNAMIC_KIND; | 78 return schema.DYNAMIC_KIND; |
| 94 } | 79 } |
| 95 if (element is CompilationUnitElement) { | 80 if (element is CompilationUnitElement) { |
| 96 return _getPath(element); | 81 return _getPath(element); |
| 97 } | 82 } |
| 98 return '$nodeKind:${element.accept(SignatureElementVisitor.instance)}'; | 83 return '$nodeKind:${element.accept(SignatureElementVisitor.instance)}'; |
| 99 } | 84 } |
| 100 | 85 |
| 101 /// Send a [Reply] message to the parent process via standard output. | 86 class CodedBufferWriter { |
| 102 /// | 87 CodedBufferWriter(var v); |
| 103 /// The message is formatted as a base-128 encoded length followed by the | 88 toBuffer() {} |
| 104 /// serialized message data. The base-128 encoding is in little-endian order, | |
| 105 /// with the high bit set on all bytes but the last. This was chosen since | |
| 106 /// it's the same as the base-128 encoding used by protobufs, so it allows a | |
| 107 /// modest amount of code reuse. Also it parallels the format used by | |
| 108 /// [messageGrouper]. | |
| 109 void _sendToParentProcess(pb_Entry entry) { | |
| 110 var rawMessage = entry.writeToBuffer(); | |
| 111 var encodedLength = (new CodedBufferWriter(rawMessage.length)).toBuffer(); | |
| 112 stdout..add(encodedLength)..add(rawMessage); | |
| 113 } | 89 } |
| 114 | 90 |
| 115 // TODO(jwren) This method simply serves to provide the WORKSPACE relative path | |
| 116 // for sources in Elements, it needs to be written in a more robust way. | |
| 117 /// This visitor writes out Kythe facts and edges as specified by the Kythe | 91 /// This visitor writes out Kythe facts and edges as specified by the Kythe |
| 118 /// Schema here https://kythe.io/docs/schema/. This visitor handles all nodes, | 92 /// Schema here https://kythe.io/docs/schema/. This visitor handles all nodes, |
| 119 /// facts and edges. | 93 /// facts and edges. |
| 120 class KytheDartVisitor extends GeneralizingAstVisitor with OutputUtils { | 94 class KytheDartVisitor extends GeneralizingAstVisitor with OutputUtils { |
| 121 final List<pb_Entry> entries; | 95 final List<KytheEntry> entries; |
| 122 final String corpus; | 96 final String corpus; |
| 123 final InheritanceManager _inheritanceManager; | 97 final InheritanceManager _inheritanceManager; |
| 124 String _enclosingFilePath = ''; | 98 String _enclosingFilePath = ''; |
| 125 Element _enclosingElement; | 99 Element _enclosingElement; |
| 126 ClassElement _enclosingClassElement; | 100 ClassElement _enclosingClassElement; |
| 127 pb_VName _enclosingVName; | 101 KytheVName _enclosingVName; |
| 128 pb_VName _enclosingFileVName; | 102 KytheVName _enclosingFileVName; |
| 129 pb_VName _enclosingClassVName; | 103 KytheVName _enclosingClassVName; |
| 130 final String _contents; | 104 final String _contents; |
| 131 | 105 |
| 132 KytheDartVisitor( | 106 KytheDartVisitor( |
| 133 this.entries, this.corpus, this._inheritanceManager, this._contents); | 107 this.entries, this.corpus, this._inheritanceManager, this._contents); |
| 134 | 108 |
| 135 @override | 109 @override |
| 136 String get enclosingFilePath => _enclosingFilePath; | 110 String get enclosingFilePath => _enclosingFilePath; |
| 137 | 111 |
| 138 @override | 112 @override |
| 139 visitAnnotation(Annotation node) { | 113 visitAnnotation(Annotation node) { |
| (...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 927 return schema.RECORD_KIND; | 901 return schema.RECORD_KIND; |
| 928 } | 902 } |
| 929 return null; | 903 return null; |
| 930 } | 904 } |
| 931 | 905 |
| 932 _handleRefCallEdge( | 906 _handleRefCallEdge( |
| 933 Element element, { | 907 Element element, { |
| 934 SyntacticEntity syntacticEntity: null, | 908 SyntacticEntity syntacticEntity: null, |
| 935 start: _notFound, | 909 start: _notFound, |
| 936 end: _notFound, | 910 end: _notFound, |
| 937 pb_VName enclosingTarget: null, | 911 KytheVName enclosingTarget: null, |
| 938 }) { | 912 }) { |
| 939 if (element is ExecutableElement && | 913 if (element is ExecutableElement && |
| 940 _enclosingVName != _enclosingFileVName) { | 914 _enclosingVName != _enclosingFileVName) { |
| 941 _handleRefEdge( | 915 _handleRefEdge( |
| 942 element, | 916 element, |
| 943 const <String>[schema.REF_CALL_EDGE, schema.REF_EDGE], | 917 const <String>[schema.REF_CALL_EDGE, schema.REF_EDGE], |
| 944 syntacticEntity: syntacticEntity, | 918 syntacticEntity: syntacticEntity, |
| 945 start: start, | 919 start: start, |
| 946 end: end, | 920 end: end, |
| 947 enclosingTarget: enclosingTarget, | 921 enclosingTarget: enclosingTarget, |
| 948 enclosingAnchor: _enclosingVName, | 922 enclosingAnchor: _enclosingVName, |
| 949 ); | 923 ); |
| 950 } else { | 924 } else { |
| 951 _handleRefEdge( | 925 _handleRefEdge( |
| 952 element, | 926 element, |
| 953 const <String>[schema.REF_EDGE], | 927 const <String>[schema.REF_EDGE], |
| 954 syntacticEntity: syntacticEntity, | 928 syntacticEntity: syntacticEntity, |
| 955 start: start, | 929 start: start, |
| 956 end: end, | 930 end: end, |
| 957 enclosingTarget: enclosingTarget, | 931 enclosingTarget: enclosingTarget, |
| 958 ); | 932 ); |
| 959 } | 933 } |
| 960 } | 934 } |
| 961 | 935 |
| 962 /// This is a convenience method for adding ref edges. If the [start] and | 936 /// This is a convenience method for adding ref edges. If the [start] and |
| 963 /// [end] offsets are provided, they are used, otherwise the offsets are | 937 /// [end] offsets are provided, they are used, otherwise the offsets are |
| 964 /// computed by using the [syntacticEntity]. | 938 /// computed by using the [syntacticEntity]. The list of edges is assumed to |
| 965 /// The list of edges is assumed to be non-empty, and are added from the | 939 /// be non-empty, and are added from the anchor to the target generated using |
| 966 /// anchor to the target generated using the passed [Element]. | 940 /// the passed [Element]. The created [KytheVName] is returned, if not `null` |
| 967 /// The created [pb_VName] is returned, if not `null` is returned. | 941 /// is returned. |
| 968 pb_VName _handleRefEdge( | 942 KytheVName _handleRefEdge( |
| 969 Element element, | 943 Element element, |
| 970 List<String> refEdgeTypes, { | 944 List<String> refEdgeTypes, { |
| 971 SyntacticEntity syntacticEntity: null, | 945 SyntacticEntity syntacticEntity: null, |
| 972 start: _notFound, | 946 start: _notFound, |
| 973 end: _notFound, | 947 end: _notFound, |
| 974 pb_VName enclosingTarget: null, | 948 KytheVName enclosingTarget: null, |
| 975 pb_VName enclosingAnchor: null, | 949 KytheVName enclosingAnchor: null, |
| 976 }) { | 950 }) { |
| 977 assert(refEdgeTypes.isNotEmpty); | 951 assert(refEdgeTypes.isNotEmpty); |
| 978 element = _findNonSyntheticElement(element); | 952 element = _findNonSyntheticElement(element); |
| 979 if (element == null) { | 953 if (element == null) { |
| 980 return null; | 954 return null; |
| 981 } | 955 } |
| 982 | 956 |
| 983 // vname | 957 // vname |
| 984 var nodeKind = _getNodeKind(element); | 958 var nodeKind = _getNodeKind(element); |
| 985 if (nodeKind == null || nodeKind.isEmpty) { | 959 if (nodeKind == null || nodeKind.isEmpty) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1054 addAnchorEdgesContainingEdge( | 1028 addAnchorEdgesContainingEdge( |
| 1055 start: start, | 1029 start: start, |
| 1056 end: end, | 1030 end: end, |
| 1057 edges: [schema.REF_IMPORTS_EDGE], | 1031 edges: [schema.REF_IMPORTS_EDGE], |
| 1058 target: packageVName, | 1032 target: packageVName, |
| 1059 enclosingTarget: _enclosingFileVName); | 1033 enclosingTarget: _enclosingFileVName); |
| 1060 } | 1034 } |
| 1061 } | 1035 } |
| 1062 | 1036 |
| 1063 _handleVariableDeclarationListAnnotations( | 1037 _handleVariableDeclarationListAnnotations( |
| 1064 VariableDeclarationList variableDeclarationList, pb_VName refVName) { | 1038 VariableDeclarationList variableDeclarationList, KytheVName refVName) { |
| 1065 assert(refVName != null); | 1039 assert(refVName != null); |
| 1066 for (var varDecl in variableDeclarationList.variables) { | 1040 for (var varDecl in variableDeclarationList.variables) { |
| 1067 if (varDecl.element != null) { | 1041 if (varDecl.element != null) { |
| 1068 var parentVName = | 1042 var parentVName = |
| 1069 _vNameFromElement(varDecl.element, schema.VARIABLE_KIND); | 1043 _vNameFromElement(varDecl.element, schema.VARIABLE_KIND); |
| 1070 addEdge(parentVName, schema.ANNOTATED_BY_EDGE, refVName); | 1044 addEdge(parentVName, schema.ANNOTATED_BY_EDGE, refVName); |
| 1071 } else { | 1045 } else { |
| 1072 // The element out of the VarDeclarationList is null | 1046 // The element out of the VarDeclarationList is null |
| 1073 assert(false); | 1047 assert(false); |
| 1074 } | 1048 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1113 _enclosingElement = outerEnclosingElement; | 1087 _enclosingElement = outerEnclosingElement; |
| 1114 _enclosingClassElement = outerEnclosingClassElement; | 1088 _enclosingClassElement = outerEnclosingClassElement; |
| 1115 _enclosingClassVName = outerEnclosingClassVName; | 1089 _enclosingClassVName = outerEnclosingClassVName; |
| 1116 _enclosingVName = outerEnclosingVName; | 1090 _enclosingVName = outerEnclosingVName; |
| 1117 } | 1091 } |
| 1118 } | 1092 } |
| 1119 } | 1093 } |
| 1120 | 1094 |
| 1121 /// This class is meant to be a mixin to concrete visitor methods to walk the | 1095 /// This class is meant to be a mixin to concrete visitor methods to walk the |
| 1122 /// [Element] or [AstNode]s produced by the Dart Analyzer to output Kythe | 1096 /// [Element] or [AstNode]s produced by the Dart Analyzer to output Kythe |
| 1123 /// [pb_Entry] protos. | 1097 /// [KytheEntry] protos. |
| 1124 abstract class OutputUtils { | 1098 abstract class OutputUtils { |
| 1125 /// A set of [String]s which have already had a name [pb_VName] created. | 1099 /// A set of [String]s which have already had a name [KytheVName] created. |
| 1126 final Set<String> nameNodes = new Set<String>(); | 1100 final Set<String> nameNodes = new Set<String>(); |
| 1127 String get corpus; | 1101 String get corpus; |
| 1128 pb_VName get dynamicBuiltin => _vName(schema.DYNAMIC_KIND, '', '', ''); | 1102 KytheVName get dynamicBuiltin => _vName(schema.DYNAMIC_KIND, '', '', ''); |
| 1129 | 1103 |
| 1130 String get enclosingFilePath; | 1104 String get enclosingFilePath; |
| 1131 | 1105 |
| 1132 List<pb_Entry> get entries; | 1106 List<KytheEntry> get entries; |
| 1133 pb_VName get fnBuiltin => _vName(schema.FN_BUILTIN, '', '', ''); | 1107 KytheVName get fnBuiltin => _vName(schema.FN_BUILTIN, '', '', ''); |
| 1134 pb_VName get voidBuiltin => _vName(schema.VOID_BUILTIN, '', '', ''); | 1108 KytheVName get voidBuiltin => _vName(schema.VOID_BUILTIN, '', '', ''); |
| 1135 | 1109 |
| 1136 /// This is a convenience method for adding anchors. If the [start] and [end] | 1110 /// This is a convenience method for adding anchors. If the [start] and [end] |
| 1137 /// offsets are provided, they are used, otherwise the offsets are computed by | 1111 /// offsets are provided, they are used, otherwise the offsets are computed by |
| 1138 /// using the [syntacticEntity]. If a non-empty list of edges is provided, as | 1112 /// using the [syntacticEntity]. If a non-empty list of edges is provided, as |
| 1139 /// well as a target, then this method also adds the edges from the anchor to | 1113 /// well as a target, then this method also adds the edges from the anchor to |
| 1140 /// target. The anchor [pb_VName] is returned. | 1114 /// target. The anchor [KytheVName] is returned. |
| 1141 /// | 1115 /// |
| 1142 /// If a [target] and [enclosingTarget] are provided, a childof edge is | 1116 /// If a [target] and [enclosingTarget] are provided, a childof edge is |
| 1143 /// written out from the target to the enclosing target. | 1117 /// written out from the target to the enclosing target. |
| 1144 /// | 1118 /// |
| 1145 /// If an [enclosingAnchor] is provided a childof edge is written out from the | 1119 /// If an [enclosingAnchor] is provided a childof edge is written out from the |
| 1146 /// anchor to the enclosing anchor. In cases where ref/call is an edge, this | 1120 /// anchor to the enclosing anchor. In cases where ref/call is an edge, this |
| 1147 /// is required to generate the callgraph. | 1121 /// is required to generate the callgraph. |
| 1148 /// | 1122 /// |
| 1149 /// Finally, for all anchors, a childof edge with a target of the enclosing | 1123 /// Finally, for all anchors, a childof edge with a target of the enclosing |
| 1150 /// file is written out. | 1124 /// file is written out. |
| 1151 pb_VName addAnchorEdgesContainingEdge({ | 1125 KytheVName addAnchorEdgesContainingEdge({ |
| 1152 SyntacticEntity syntacticEntity: null, | 1126 SyntacticEntity syntacticEntity: null, |
| 1153 int start: _notFound, | 1127 int start: _notFound, |
| 1154 int end: _notFound, | 1128 int end: _notFound, |
| 1155 List<String> edges: const [], | 1129 List<String> edges: const [], |
| 1156 pb_VName target: null, | 1130 KytheVName target: null, |
| 1157 pb_VName enclosingTarget: null, | 1131 KytheVName enclosingTarget: null, |
| 1158 pb_VName enclosingAnchor: null, | 1132 KytheVName enclosingAnchor: null, |
| 1159 }) { | 1133 }) { |
| 1160 if (start == _notFound && end == _notFound) { | 1134 if (start == _notFound && end == _notFound) { |
| 1161 if (syntacticEntity != null) { | 1135 if (syntacticEntity != null) { |
| 1162 start = syntacticEntity.offset; | 1136 start = syntacticEntity.offset; |
| 1163 end = syntacticEntity.end; | 1137 end = syntacticEntity.end; |
| 1164 } else { | 1138 } else { |
| 1165 throw new Exception('Offset positions were not provided when calling ' | 1139 throw new Exception('Offset positions were not provided when calling ' |
| 1166 'addAnchorEdgesContainingEdge'); | 1140 'addAnchorEdgesContainingEdge'); |
| 1167 } | 1141 } |
| 1168 } | 1142 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1193 } | 1167 } |
| 1194 | 1168 |
| 1195 // Finally add the childof edge to the enclosing file VName. | 1169 // Finally add the childof edge to the enclosing file VName. |
| 1196 addEdge(anchorVName, schema.CHILD_OF_EDGE, _vNameFile()); | 1170 addEdge(anchorVName, schema.CHILD_OF_EDGE, _vNameFile()); |
| 1197 return anchorVName; | 1171 return anchorVName; |
| 1198 } | 1172 } |
| 1199 | 1173 |
| 1200 /// TODO(jwren): for cases where the target is a name, we need the same kind | 1174 /// TODO(jwren): for cases where the target is a name, we need the same kind |
| 1201 /// of logic as [addNameFact] to prevent the edge from being written out. | 1175 /// of logic as [addNameFact] to prevent the edge from being written out. |
| 1202 /// This is a convenience method for visitors to add an edge Entry. | 1176 /// This is a convenience method for visitors to add an edge Entry. |
| 1203 pb_Entry addEdge(pb_VName source, String edgeKind, pb_VName target, | 1177 KytheEntry addEdge(KytheVName source, String edgeKind, KytheVName target, |
| 1204 {int ordinalIntValue: _notFound}) { | 1178 {int ordinalIntValue: _notFound}) { |
| 1205 if (ordinalIntValue == _notFound) { | 1179 if (ordinalIntValue == _notFound) { |
| 1206 return addEntry(source, edgeKind, target, "/", new List<int>()); | 1180 return addEntry(source, edgeKind, target, "/", new List<int>()); |
| 1207 } else { | 1181 } else { |
| 1208 return addEntry(source, edgeKind, target, schema.ORDINAL, | 1182 return addEntry(source, edgeKind, target, schema.ORDINAL, |
| 1209 _encodeInt(ordinalIntValue)); | 1183 _encodeInt(ordinalIntValue)); |
| 1210 } | 1184 } |
| 1211 } | 1185 } |
| 1212 | 1186 |
| 1213 pb_Entry addEntry(pb_VName source, String edgeKind, pb_VName target, | 1187 KytheEntry addEntry(KytheVName source, String edgeKind, KytheVName target, |
| 1214 String factName, List<int> factValue) { | 1188 String factName, List<int> factValue) { |
| 1215 assert(source != null); | 1189 assert(source != null); |
| 1216 assert(factName != null); | 1190 assert(factName != null); |
| 1217 assert(factValue != null); | 1191 assert(factValue != null); |
| 1218 // factValue may be an empty array, the fact may be that a file text or | 1192 // factValue may be an empty array, the fact may be that a file text or |
| 1219 // document text is empty | 1193 // document text is empty |
| 1220 var entry = pb_Entry.create() | 1194 if (edgeKind == null || edgeKind.isEmpty) { |
| 1221 ..source = source | 1195 edgeKind = null; |
| 1222 ..factName = factName | 1196 target = null; |
| 1223 ..factValue = factValue; | |
| 1224 if (edgeKind != null && edgeKind.isNotEmpty) { | |
| 1225 entry.edgeKind = edgeKind; | |
| 1226 entry.target = target; | |
| 1227 } | 1197 } |
| 1198 var entry = new KytheEntry(source, edgeKind, target, factName, factValue); |
| 1228 entries.add(entry); | 1199 entries.add(entry); |
| 1229 return entry; | 1200 return entry; |
| 1230 } | 1201 } |
| 1231 | 1202 |
| 1232 /// This is a convenience method for visitors to add a fact [pb_Entry]. | 1203 /// This is a convenience method for visitors to add a fact [KytheEntry]. |
| 1233 pb_Entry addFact(pb_VName source, String factName, List<int> factValue) { | 1204 KytheEntry addFact(KytheVName source, String factName, List<int> factValue) { |
| 1234 return addEntry(source, null, null, factName, factValue); | 1205 return addEntry(source, null, null, factName, factValue); |
| 1235 } | 1206 } |
| 1236 | 1207 |
| 1237 /// This is a convenience method for adding function types. | 1208 /// This is a convenience method for adding function types. |
| 1238 pb_VName addFunctionType( | 1209 KytheVName addFunctionType( |
| 1239 Element functionElement, | 1210 Element functionElement, |
| 1240 FormalParameterList paramNodes, | 1211 FormalParameterList paramNodes, |
| 1241 pb_VName functionVName, { | 1212 KytheVName functionVName, { |
| 1242 AstNode returnNode: null, | 1213 AstNode returnNode: null, |
| 1243 }) { | 1214 }) { |
| 1244 var i = 0; | 1215 var i = 0; |
| 1245 var funcTypeVName = | 1216 var funcTypeVName = |
| 1246 addNodeAndFacts(schema.TAPP_KIND, element: functionElement); | 1217 addNodeAndFacts(schema.TAPP_KIND, element: functionElement); |
| 1247 addEdge(funcTypeVName, schema.PARAM_EDGE, fnBuiltin, ordinalIntValue: i++); | 1218 addEdge(funcTypeVName, schema.PARAM_EDGE, fnBuiltin, ordinalIntValue: i++); |
| 1248 | 1219 |
| 1249 var returnTypeVName; | 1220 var returnTypeVName; |
| 1250 if (returnNode is TypeName) { | 1221 if (returnNode is TypeName) { |
| 1251 // MethodDeclaration and FunctionDeclaration both return a TypeName from | 1222 // MethodDeclaration and FunctionDeclaration both return a TypeName from |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1288 } | 1259 } |
| 1289 addEdge(funcTypeVName, schema.PARAM_EDGE, paramTypeVName, | 1260 addEdge(funcTypeVName, schema.PARAM_EDGE, paramTypeVName, |
| 1290 ordinalIntValue: i++); | 1261 ordinalIntValue: i++); |
| 1291 } | 1262 } |
| 1292 } | 1263 } |
| 1293 addEdge(functionVName, schema.TYPED_EDGE, funcTypeVName); | 1264 addEdge(functionVName, schema.TYPED_EDGE, funcTypeVName); |
| 1294 return funcTypeVName; | 1265 return funcTypeVName; |
| 1295 } | 1266 } |
| 1296 | 1267 |
| 1297 /// This is a convenience method for adding nodes with facts. | 1268 /// This is a convenience method for adding nodes with facts. |
| 1298 /// If an [pb_VName] is passed, it is used, otherwise an element is required | 1269 /// If an [KytheVName] is passed, it is used, otherwise an element is required |
| 1299 /// which is used to create a [pb_VName]. Either [nodeVName] must be non-null
or | 1270 /// which is used to create a [KytheVName]. Either [nodeVName] must be non-nu
ll or |
| 1300 /// [element] must be non-null. Other optional parameters if passed are then | 1271 /// [element] must be non-null. Other optional parameters if passed are then |
| 1301 /// used to set the associated facts on the [pb_VName]. This method does not | 1272 /// used to set the associated facts on the [KytheVName]. This method does not |
| 1302 /// currently guarantee that the inputs to these fact kinds are valid for the | 1273 /// currently guarantee that the inputs to these fact kinds are valid for the |
| 1303 /// associated nodeKind- if a non-null, then it will set. | 1274 /// associated nodeKind- if a non-null, then it will set. |
| 1304 pb_VName addNodeAndFacts(String nodeKind, | 1275 KytheVName addNodeAndFacts(String nodeKind, |
| 1305 {Element element: null, | 1276 {Element element: null, |
| 1306 pb_VName nodeVName: null, | 1277 KytheVName nodeVName: null, |
| 1307 String subKind: null, | 1278 String subKind: null, |
| 1308 String completeFact: null}) { | 1279 String completeFact: null}) { |
| 1309 if (nodeVName == null) { | 1280 if (nodeVName == null) { |
| 1310 nodeVName = _vNameFromElement(element, nodeKind); | 1281 nodeVName = _vNameFromElement(element, nodeKind); |
| 1311 } | 1282 } |
| 1312 addFact(nodeVName, schema.NODE_KIND_FACT, _encode(nodeKind)); | 1283 addFact(nodeVName, schema.NODE_KIND_FACT, _encode(nodeKind)); |
| 1313 if (subKind != null) { | 1284 if (subKind != null) { |
| 1314 addFact(nodeVName, schema.SUBKIND_FACT, _encode(subKind)); | 1285 addFact(nodeVName, schema.SUBKIND_FACT, _encode(subKind)); |
| 1315 } | 1286 } |
| 1316 if (completeFact != null) { | 1287 if (completeFact != null) { |
| 1317 addFact(nodeVName, schema.COMPLETE_FACT, _encode(completeFact)); | 1288 addFact(nodeVName, schema.COMPLETE_FACT, _encode(completeFact)); |
| 1318 } | 1289 } |
| 1319 return nodeVName; | 1290 return nodeVName; |
| 1320 } | 1291 } |
| 1321 | 1292 |
| 1322 List<int> _encode(String str) { | 1293 List<int> _encode(String str) { |
| 1323 return UTF8.encode(str); | 1294 return UTF8.encode(str); |
| 1324 } | 1295 } |
| 1325 | 1296 |
| 1326 List<int> _encodeInt(int i) { | 1297 List<int> _encodeInt(int i) { |
| 1327 return UTF8.encode(i.toString()); | 1298 return UTF8.encode(i.toString()); |
| 1328 } | 1299 } |
| 1329 | 1300 |
| 1330 /// Given all parameters for a [pb_VName] this method creates and returns a | 1301 /// Given all parameters for a [KytheVName] this method creates and returns a |
| 1331 /// [pb_VName]. | 1302 /// [KytheVName]. |
| 1332 pb_VName _vName(String signature, String corpus, String root, String path, | 1303 KytheVName _vName(String signature, String corpus, String root, String path, |
| 1333 [String language = schema.DART_LANG]) { | 1304 [String language = schema.DART_LANG]) { |
| 1334 return pb_VName.create() | 1305 return new KytheVName(signature, corpus, root, path, language); |
| 1335 ..signature = signature | |
| 1336 ..corpus = corpus | |
| 1337 ..root = root | |
| 1338 ..path = path | |
| 1339 ..language = language; | |
| 1340 } | 1306 } |
| 1341 | 1307 |
| 1342 /// Returns an anchor [pb_VName] corresponding to the given start and end | 1308 /// Returns an anchor [KytheVName] corresponding to the given start and end |
| 1343 /// offsets. | 1309 /// offsets. |
| 1344 pb_VName _vNameAnchor(int start, int end) { | 1310 KytheVName _vNameAnchor(int start, int end) { |
| 1345 return _vName( | 1311 return _vName( |
| 1346 _getAnchorSignature(start, end), corpus, '', enclosingFilePath); | 1312 _getAnchorSignature(start, end), corpus, '', enclosingFilePath); |
| 1347 } | 1313 } |
| 1348 | 1314 |
| 1349 /// Return the [pb_VName] for this file. | 1315 /// Return the [KytheVName] for this file. |
| 1350 pb_VName _vNameFile() { | 1316 KytheVName _vNameFile() { |
| 1351 // file vnames, the signature and language are not set | 1317 // file vnames, the signature and language are not set |
| 1352 return _vName('', corpus, '', enclosingFilePath, ''); | 1318 return _vName('', corpus, '', enclosingFilePath, ''); |
| 1353 } | 1319 } |
| 1354 | 1320 |
| 1355 /// Given some [Element] and Kythe node kind, this method generates and | 1321 /// Given some [Element] and Kythe node kind, this method generates and |
| 1356 /// returns the [pb_VName]. | 1322 /// returns the [KytheVName]. |
| 1357 pb_VName _vNameFromElement(Element e, String nodeKind) { | 1323 KytheVName _vNameFromElement(Element e, String nodeKind) { |
| 1358 assert(nodeKind != schema.FILE_KIND); | 1324 assert(nodeKind != schema.FILE_KIND); |
| 1359 // general case | 1325 // general case |
| 1360 return _vName(_getSignature(e, nodeKind, corpus), corpus, '', _getPath(e)); | 1326 return _vName(_getSignature(e, nodeKind, corpus), corpus, '', _getPath(e)); |
| 1361 } | 1327 } |
| 1362 | 1328 |
| 1363 /// Returns a [pb_VName] corresponding to the given [DartType]. | 1329 /// Returns a [KytheVName] corresponding to the given [DartType]. |
| 1364 pb_VName _vNameFromType(DartType type) { | 1330 KytheVName _vNameFromType(DartType type) { |
| 1365 if (type == null || type.isDynamic) { | 1331 if (type == null || type.isDynamic) { |
| 1366 return dynamicBuiltin; | 1332 return dynamicBuiltin; |
| 1367 } else if (type.isVoid) { | 1333 } else if (type.isVoid) { |
| 1368 return voidBuiltin; | 1334 return voidBuiltin; |
| 1369 } else if (type.element is ClassElement) { | 1335 } else if (type.element is ClassElement) { |
| 1370 return _vNameFromElement(type.element, schema.RECORD_KIND); | 1336 return _vNameFromElement(type.element, schema.RECORD_KIND); |
| 1371 } else { | 1337 } else { |
| 1372 return dynamicBuiltin; | 1338 return dynamicBuiltin; |
| 1373 } | 1339 } |
| 1374 } | 1340 } |
| 1375 } | 1341 } |
| 1376 | 1342 |
| 1377 class CodedBufferWriter { | |
| 1378 CodedBufferWriter(var v); | |
| 1379 toBuffer() {} | |
| 1380 } | |
| 1381 | |
| 1382 class pb_Entry { | |
| 1383 var source, edgeKind, target, factName, factValue; | |
| 1384 static pb_Entry create() => new pb_Entry(); | |
| 1385 writeToBuffer() {} | |
| 1386 } | |
| 1387 | |
| 1388 class pb_VName { | |
| 1389 var signature, corpus, root, path, language; | |
| 1390 static pb_VName create() => new pb_VName(); | |
| 1391 } | |
| 1392 | |
| 1393 /// This visitor class should be used by [_getSignature]. | 1343 /// This visitor class should be used by [_getSignature]. |
| 1394 /// | 1344 /// |
| 1395 /// This visitor is an [GeneralizingElementVisitor] which builds up a [String] | 1345 /// This visitor is an [GeneralizingElementVisitor] which builds up a [String] |
| 1396 /// signature for a given [Element], uniqueness is guaranteed within the | 1346 /// signature for a given [Element], uniqueness is guaranteed within the |
| 1397 /// enclosing file. | 1347 /// enclosing file. |
| 1398 class SignatureElementVisitor extends GeneralizingElementVisitor<StringBuffer> { | 1348 class SignatureElementVisitor extends GeneralizingElementVisitor<StringBuffer> { |
| 1399 static SignatureElementVisitor instance = new SignatureElementVisitor(); | 1349 static SignatureElementVisitor instance = new SignatureElementVisitor(); |
| 1400 | 1350 |
| 1401 @override | 1351 @override |
| 1402 StringBuffer visitCompilationUnitElement(CompilationUnitElement e) { | 1352 StringBuffer visitCompilationUnitElement(CompilationUnitElement e) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1430 } | 1380 } |
| 1431 | 1381 |
| 1432 @override | 1382 @override |
| 1433 StringBuffer visitTypeParameterElement(TypeParameterElement e) { | 1383 StringBuffer visitTypeParameterElement(TypeParameterElement e) { |
| 1434 // It is legal to have a named constructor with the same name as a type | 1384 // It is legal to have a named constructor with the same name as a type |
| 1435 // parameter. So we distinguish them by using '.' between the class (or | 1385 // parameter. So we distinguish them by using '.' between the class (or |
| 1436 // typedef) name and the type parameter name. | 1386 // typedef) name and the type parameter name. |
| 1437 return e.enclosingElement.accept(this)..write('.')..write(e.name); | 1387 return e.enclosingElement.accept(this)..write('.')..write(e.name); |
| 1438 } | 1388 } |
| 1439 } | 1389 } |
| OLD | NEW |