update: package analyzer 10 pass 1 fail

This commit is contained in:
Patrick Stewart 2024-12-25 17:59:05 -07:00
parent d728fcb9dd
commit dacf949af4

View file

@ -504,7 +504,7 @@ class PackageAnalyzer {
// Extract all constructor declarations using regex // Extract all constructor declarations using regex
final constructorPattern = '(?:const\\s+)?(?:factory\\s+)?' + final constructorPattern = '(?:const\\s+)?(?:factory\\s+)?' +
RegExp.escape(className) + RegExp.escape(className) +
'(?:\\.([\\w.]+))?\\s*\\(([^)]*?)\\)(?:\\s*:[^{;]*?)?(?:\\s*(?:=>|{|;))'; '(?:\\.([\\w.]+))?\\s*\\(([^)]*)\\)(?:\\s*:[^{;]*?)?(?:\\s*(?:=>|{|;))';
print('Constructor pattern: $constructorPattern'); print('Constructor pattern: $constructorPattern');
final constructorRegex = final constructorRegex =
@ -517,49 +517,76 @@ class PackageAnalyzer {
print('Full match: $fullMatch'); print('Full match: $fullMatch');
print('Group 1 (name): ${match.group(1)}'); print('Group 1 (name): ${match.group(1)}');
print('Group 2 (params): ${match.group(2)}'); print('Group 2 (params): ${match.group(2)}');
}
// Use a map to deduplicate constructors by name // Get the line containing this match
final constructorMap = <String, ConstructorMetadata>{}; final lineStart = classContent.lastIndexOf('\n', match.start) + 1;
final lineEnd = classContent.indexOf('\n', match.start);
final line = classContent.substring(
lineStart, lineEnd > 0 ? lineEnd : classContent.length);
// Skip if this is part of a static method or return statement
if (line.trim().startsWith('static') ||
line.trim().startsWith('return')) {
continue;
}
// Process constructors
for (final match in matches) {
final fullMatch = classContent.substring(match.start, match.end);
final name = match.group(1) ?? ''; final name = match.group(1) ?? '';
final params = match.group(2) ?? ''; final params = match.group(2) ?? '';
final isFactory = fullMatch.trim().startsWith('factory'); final isFactory = line.trim().startsWith('factory');
// For factory constructors without a name, use 'create' // For factory constructors without a name, use 'create'
final constructorName = isFactory && name.isEmpty ? 'create' : name; final constructorName = isFactory && name.isEmpty ? 'create' : name;
// Only add if we haven't seen this constructor name before // Parse parameters
if (!constructorMap.containsKey(constructorName)) { final parameterTypes = _extractParameterTypes(params);
constructorMap[constructorName] = ConstructorMetadata( final parameters = _extractParameters(params);
name: constructorName,
parameterTypes: _extractParameterTypes(params), // Add constructor
parameters: _extractParameters(params), constructors.add(ConstructorMetadata(
); name: constructorName,
} parameterTypes: parameterTypes,
parameters: parameters,
));
} }
final result = constructorMap.values.toList(); print('Returning ${constructors.length} constructors');
print('Returning ${result.length} constructors'); return constructors;
return result;
} }
/// Extracts parameter types from a parameter list string. /// Extracts parameter types from a parameter list string.
static List<Type> _extractParameterTypes(String params) { static List<Type> _extractParameterTypes(String params) {
final types = <Type>[]; final types = <Type>[];
final paramRegex = RegExp( final paramRegex = RegExp(
r'(?:required\s+)?(\w+(?:<[^>]+>)?)\s+(?:this\.)?(\w+)(?:\s*\?)?', r'(?:required\s+)?(\w+(?:<[^>]+>)?)\s+(?:this\.)?(\w+)(?:\s*\?)?',
multiLine: true, multiLine: true,
); );
final matches = paramRegex.allMatches(params);
for (final match in matches) { // Split parameters by commas, handling both positional and named parameters
final type = match.group(1)!; final parts =
types.add(_getTypeForName(type)); params.split(',').map((p) => p.trim()).where((p) => p.isNotEmpty);
for (final part in parts) {
if (part.startsWith('{') || part.endsWith('}')) {
// Handle named parameter section
final namedParams = part.replaceAll(RegExp(r'[{}]'), '').trim();
if (namedParams.isNotEmpty) {
final namedParts = namedParams
.split(',')
.map((p) => p.trim())
.where((p) => p.isNotEmpty);
for (final namedPart in namedParts) {
final match = paramRegex.firstMatch(namedPart);
if (match != null) {
types.add(_getTypeForName(match.group(1)!));
}
}
}
} else {
// Handle positional parameter
final match = paramRegex.firstMatch(part);
if (match != null) {
types.add(_getTypeForName(match.group(1)!));
}
}
} }
return types; return types;
@ -568,26 +595,58 @@ class PackageAnalyzer {
/// Extracts parameters from a parameter list string. /// Extracts parameters from a parameter list string.
static List<ParameterMetadata> _extractParameters(String params) { static List<ParameterMetadata> _extractParameters(String params) {
final parameters = <ParameterMetadata>[]; final parameters = <ParameterMetadata>[];
final paramRegex = RegExp( final paramRegex = RegExp(
r'(?:required\s+)?(\w+(?:<[^>]+>)?)\s+(?:this\.)?(\w+)(?:\s*\?)?(?:\s*=\s*([^,}]+))?(?:,|\s*$|\s*\}|\s*\)|$)', r'(?:required\s+)?(\w+(?:<[^>]+>)?)\s+(?:this\.)?(\w+)(?:\s*\?)?(?:\s*=\s*([^,}]+))?',
multiLine: true, multiLine: true,
); );
final matches = paramRegex.allMatches(params);
for (final match in matches) { // Split parameters by commas, handling both positional and named parameters
final type = match.group(1)!; final parts =
final name = match.group(2)!; params.split(',').map((p) => p.trim()).where((p) => p.isNotEmpty);
final defaultValue = match.group(3); for (final part in parts) {
if (part.startsWith('{') || part.endsWith('}')) {
// Handle named parameter section
final namedParams = part.replaceAll(RegExp(r'[{}]'), '').trim();
if (namedParams.isNotEmpty) {
final namedParts = namedParams
.split(',')
.map((p) => p.trim())
.where((p) => p.isNotEmpty);
for (final namedPart in namedParts) {
final match = paramRegex.firstMatch(namedPart);
if (match != null) {
final type = match.group(1)!;
final name = match.group(2)!;
final defaultValue = match.group(3);
final isRequired = namedPart.contains('required');
parameters.add(ParameterMetadata( parameters.add(ParameterMetadata(
name: name, name: name,
type: _getTypeForName(type), type: _getTypeForName(type),
isRequired: params.contains('required $type $name'), isRequired: isRequired,
isNamed: params.contains('{') && params.contains('}'), isNamed: true,
defaultValue: defaultValue: defaultValue != null
defaultValue != null ? _parseDefaultValue(defaultValue) : null, ? _parseDefaultValue(defaultValue)
)); : null,
));
}
}
}
} else {
// Handle positional parameter
final match = paramRegex.firstMatch(part);
if (match != null) {
final type = match.group(1)!;
final name = match.group(2)!;
parameters.add(ParameterMetadata(
name: name,
type: _getTypeForName(type),
isRequired: true,
isNamed: false,
));
}
}
} }
return parameters; return parameters;
@ -597,23 +656,22 @@ class PackageAnalyzer {
static String _extractClassContent(String source, String className) { static String _extractClassContent(String source, String className) {
// Find the class declaration // Find the class declaration
final classRegex = RegExp( final classRegex = RegExp(
'(?:abstract\\s+)?class\\s+' + RegExp.escape(className) + '[^{]*{', '(?:abstract\\s+)?class\\s+' + RegExp.escape(className) + '[^{]*\\{',
); );
final match = classRegex.firstMatch(source); final match = classRegex.firstMatch(source);
if (match == null) return ''; if (match == null) return '';
final startIndex = match.start; // Find the matching closing brace
var bracketCount = 1; var bracketCount = 0;
var inString = false; var inString = false;
var stringChar = ''; var stringChar = '';
var content = source.substring(startIndex, match.end); var endIndex = source.length;
// Extract everything between the opening and closing braces for (var i = match.start; i < source.length; i++) {
for (var i = match.end; i < source.length; i++) {
final char = source[i]; final char = source[i];
// Handle string literals to avoid counting braces inside strings // Handle string literals to avoid counting braces inside strings
if ((char == '"' || char == "'") && source[i - 1] != '\\') { if ((char == '"' || char == "'") && (i == 0 || source[i - 1] != '\\')) {
if (!inString) { if (!inString) {
inString = true; inString = true;
stringChar = char; stringChar = char;
@ -627,14 +685,16 @@ class PackageAnalyzer {
bracketCount++; bracketCount++;
} else if (char == '}') { } else if (char == '}') {
bracketCount--; bracketCount--;
if (bracketCount == 0) { if (bracketCount == 0 && i > match.end) {
content += source.substring(match.end, i + 1); endIndex = i + 1;
break; break;
} }
} }
} }
} }
// Include the class declaration and its content
final content = source.substring(match.start, endIndex);
return content; return content;
} }