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
final constructorPattern = '(?:const\\s+)?(?:factory\\s+)?' +
RegExp.escape(className) +
'(?:\\.([\\w.]+))?\\s*\\(([^)]*?)\\)(?:\\s*:[^{;]*?)?(?:\\s*(?:=>|{|;))';
'(?:\\.([\\w.]+))?\\s*\\(([^)]*)\\)(?:\\s*:[^{;]*?)?(?:\\s*(?:=>|{|;))';
print('Constructor pattern: $constructorPattern');
final constructorRegex =
@ -517,49 +517,76 @@ class PackageAnalyzer {
print('Full match: $fullMatch');
print('Group 1 (name): ${match.group(1)}');
print('Group 2 (params): ${match.group(2)}');
// Get the line containing this match
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;
}
// Use a map to deduplicate constructors by name
final constructorMap = <String, ConstructorMetadata>{};
// Process constructors
for (final match in matches) {
final fullMatch = classContent.substring(match.start, match.end);
final name = match.group(1) ?? '';
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'
final constructorName = isFactory && name.isEmpty ? 'create' : name;
// Only add if we haven't seen this constructor name before
if (!constructorMap.containsKey(constructorName)) {
constructorMap[constructorName] = ConstructorMetadata(
// Parse parameters
final parameterTypes = _extractParameterTypes(params);
final parameters = _extractParameters(params);
// Add constructor
constructors.add(ConstructorMetadata(
name: constructorName,
parameterTypes: _extractParameterTypes(params),
parameters: _extractParameters(params),
);
}
parameterTypes: parameterTypes,
parameters: parameters,
));
}
final result = constructorMap.values.toList();
print('Returning ${result.length} constructors');
return result;
print('Returning ${constructors.length} constructors');
return constructors;
}
/// Extracts parameter types from a parameter list string.
static List<Type> _extractParameterTypes(String params) {
final types = <Type>[];
final paramRegex = RegExp(
r'(?:required\s+)?(\w+(?:<[^>]+>)?)\s+(?:this\.)?(\w+)(?:\s*\?)?',
multiLine: true,
);
final matches = paramRegex.allMatches(params);
for (final match in matches) {
final type = match.group(1)!;
types.add(_getTypeForName(type));
// Split parameters by commas, handling both positional and named parameters
final parts =
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;
@ -568,27 +595,59 @@ class PackageAnalyzer {
/// Extracts parameters from a parameter list string.
static List<ParameterMetadata> _extractParameters(String params) {
final parameters = <ParameterMetadata>[];
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,
);
final matches = paramRegex.allMatches(params);
for (final match in matches) {
// Split parameters by commas, handling both positional and named parameters
final parts =
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) {
final type = match.group(1)!;
final name = match.group(2)!;
final defaultValue = match.group(3);
final isRequired = namedPart.contains('required');
parameters.add(ParameterMetadata(
name: name,
type: _getTypeForName(type),
isRequired: params.contains('required $type $name'),
isNamed: params.contains('{') && params.contains('}'),
defaultValue:
defaultValue != null ? _parseDefaultValue(defaultValue) : null,
isRequired: isRequired,
isNamed: true,
defaultValue: 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;
}
@ -597,23 +656,22 @@ class PackageAnalyzer {
static String _extractClassContent(String source, String className) {
// Find the class declaration
final classRegex = RegExp(
'(?:abstract\\s+)?class\\s+' + RegExp.escape(className) + '[^{]*{',
'(?:abstract\\s+)?class\\s+' + RegExp.escape(className) + '[^{]*\\{',
);
final match = classRegex.firstMatch(source);
if (match == null) return '';
final startIndex = match.start;
var bracketCount = 1;
// Find the matching closing brace
var bracketCount = 0;
var inString = false;
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.end; i < source.length; i++) {
for (var i = match.start; i < source.length; i++) {
final char = source[i];
// 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) {
inString = true;
stringChar = char;
@ -627,14 +685,16 @@ class PackageAnalyzer {
bracketCount++;
} else if (char == '}') {
bracketCount--;
if (bracketCount == 0) {
content += source.substring(match.end, i + 1);
if (bracketCount == 0 && i > match.end) {
endIndex = i + 1;
break;
}
}
}
}
// Include the class declaration and its content
final content = source.substring(match.start, endIndex);
return content;
}