mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-06 02:49:56 +00:00
Handled built in function
This commit is contained in:
parent
d92b1370d3
commit
ac3559e19f
3 changed files with 368 additions and 30 deletions
|
|
@ -226,6 +226,151 @@ public class ${name.replace(/\.[^/.]+$/, "")} {
|
|||
}
|
||||
};
|
||||
|
||||
// Generate content for built-in functions
|
||||
const generateBuiltinFunctionContent = (functionName: string): string => {
|
||||
switch (functionName) {
|
||||
case 'round':
|
||||
return `# Built-in Function: ${functionName}
|
||||
"""
|
||||
Rounds a number to the nearest integer.
|
||||
"""
|
||||
|
||||
def round(number: float, ndigits: int = 0) -> float:
|
||||
"""
|
||||
Rounds a number to the nearest integer.
|
||||
Args:
|
||||
number (float): The number to round.
|
||||
ndigits (int, optional): The number of decimal places to round to. Defaults to 0.
|
||||
Returns:
|
||||
float: The rounded number.
|
||||
"""
|
||||
# Implementation here
|
||||
pass`;
|
||||
case 'len':
|
||||
return `# Built-in Function: ${functionName}
|
||||
"""
|
||||
Returns the number of items in an object.
|
||||
"""
|
||||
|
||||
def len(obj: Any) -> int:
|
||||
"""
|
||||
Returns the number of items in an object.
|
||||
Args:
|
||||
obj (Any): The object to get the length of.
|
||||
Returns:
|
||||
int: The number of items.
|
||||
"""
|
||||
# Implementation here
|
||||
pass`;
|
||||
case 'print':
|
||||
return `# Built-in Function: ${functionName}
|
||||
"""
|
||||
Prints the given arguments to the standard output.
|
||||
"""
|
||||
|
||||
def print(*args, sep: str = " ", end: str = "\\n") -> None:
|
||||
"""
|
||||
Prints the given arguments to the standard output.
|
||||
Args:
|
||||
*args: The arguments to print.
|
||||
sep (str, optional): The separator between arguments. Defaults to " ".
|
||||
end (str, optional): The string to print at the end. Defaults to "\\n".
|
||||
"""
|
||||
# Implementation here
|
||||
pass`;
|
||||
case 'input':
|
||||
return `# Built-in Function: ${functionName}
|
||||
"""
|
||||
Reads a line from the standard input.
|
||||
"""
|
||||
|
||||
def input(prompt: str = "") -> str:
|
||||
"""
|
||||
Reads a line from the standard input.
|
||||
Args:
|
||||
prompt (str, optional): The prompt to display. Defaults to "".
|
||||
Returns:
|
||||
str: The input string.
|
||||
"""
|
||||
# Implementation here
|
||||
pass`;
|
||||
case 'open':
|
||||
return `# Built-in Function: ${functionName}
|
||||
"""
|
||||
Opens a file and returns a file object.
|
||||
"""
|
||||
|
||||
def open(file: str, mode: str = "r", buffering: int = -1, encoding: str | None = None, errors: str | None = None, newline: str | None = None) -> Any:
|
||||
"""
|
||||
Opens a file and returns a file object.
|
||||
Args:
|
||||
file (str): The path to the file.
|
||||
mode (str, optional): The mode in which the file is opened. Defaults to "r".
|
||||
buffering (int, optional): The buffering strategy. Defaults to -1.
|
||||
encoding (str | None, optional): The encoding to use. Defaults to None.
|
||||
errors (str | None, optional): How to handle encoding errors. Defaults to None.
|
||||
newline (str | None, optional): How to handle newlines. Defaults to None.
|
||||
Returns:
|
||||
Any: The file object.
|
||||
"""
|
||||
# Implementation here
|
||||
pass`;
|
||||
case 'type':
|
||||
return `# Built-in Function: ${functionName}
|
||||
"""
|
||||
Returns the type of an object.
|
||||
"""
|
||||
|
||||
def type(obj: Any) -> type:
|
||||
"""
|
||||
Returns the type of an object.
|
||||
Args:
|
||||
obj (Any): The object to get the type of.
|
||||
Returns:
|
||||
type: The type of the object.
|
||||
"""
|
||||
# Implementation here
|
||||
pass`;
|
||||
case 'isinstance':
|
||||
return `# Built-in Function: ${functionName}
|
||||
"""
|
||||
Checks if an object is an instance of a class or a tuple of classes.
|
||||
"""
|
||||
|
||||
def isinstance(obj: Any, classinfo: type | tuple[type, ...]) -> bool:
|
||||
"""
|
||||
Checks if an object is an instance of a class or a tuple of classes.
|
||||
Args:
|
||||
obj (Any): The object to check.
|
||||
classinfo (type | tuple[type, ...]): The class or tuple of classes to check against.
|
||||
Returns:
|
||||
bool: True if the object is an instance of the class or one of the classes in the tuple.
|
||||
"""
|
||||
# Implementation here
|
||||
pass`;
|
||||
case 'hasattr':
|
||||
return `# Built-in Function: ${functionName}
|
||||
"""
|
||||
Checks if an object has an attribute.
|
||||
"""
|
||||
|
||||
def hasattr(obj: Any, name: str) -> bool:
|
||||
"""
|
||||
Checks if an object has an attribute.
|
||||
Args:
|
||||
obj (Any): The object to check.
|
||||
name (str): The name of the attribute to check for.
|
||||
Returns:
|
||||
bool: True if the object has the attribute, False otherwise.
|
||||
"""
|
||||
# Implementation here
|
||||
pass`;
|
||||
default:
|
||||
return `# Built-in Function: ${functionName}
|
||||
# No specific content available`;
|
||||
}
|
||||
};
|
||||
|
||||
// Get source info for selected node
|
||||
const sourceInfo = useMemo((): SourceInfo | null => {
|
||||
if (!selectedNodeId || !graph?.nodes) return null;
|
||||
|
|
@ -258,21 +403,64 @@ public class ${name.replace(/\.[^/.]+$/, "")} {
|
|||
// If still no file path, try reverse lookup by searching for the node name in file contents
|
||||
if (!filePath && fileContents) {
|
||||
console.log('SourceViewer - Searching file contents for node:', nodeName);
|
||||
|
||||
// Try multiple search patterns for the function
|
||||
const searchPatterns = [
|
||||
`def ${nodeName}(`, // Python function
|
||||
`def ${nodeName} (`, // Python function with space
|
||||
`function ${nodeName}(`, // JavaScript function
|
||||
`function ${nodeName} (`, // JavaScript function with space
|
||||
`const ${nodeName} =`, // JavaScript const
|
||||
`let ${nodeName} =`, // JavaScript let
|
||||
`var ${nodeName} =`, // JavaScript var
|
||||
`class ${nodeName}`, // Class definition
|
||||
`${nodeName}:`, // Object property or TypeScript type
|
||||
`export const ${nodeName}`, // ES6 export
|
||||
`export function ${nodeName}`, // ES6 export function
|
||||
`public ${nodeName}(`, // Java/C# method
|
||||
`private ${nodeName}(`, // Java/C# method
|
||||
`protected ${nodeName}(`, // Java/C# method
|
||||
// Also try with underscores and variations
|
||||
`def ${nodeName}_`, // Python with underscore
|
||||
`function ${nodeName}_`, // JavaScript with underscore
|
||||
];
|
||||
|
||||
for (const [path, content] of fileContents) {
|
||||
const patterns = [
|
||||
`def ${nodeName}(`, // Python function
|
||||
`function ${nodeName}(`, // JavaScript function
|
||||
`const ${nodeName} =`, // JavaScript const
|
||||
`class ${nodeName}`, // Class definition
|
||||
`${nodeName}:`, // Object property or TypeScript type
|
||||
];
|
||||
console.log(`SourceViewer - Checking file: ${path}`);
|
||||
|
||||
if (patterns.some(pattern => content.includes(pattern))) {
|
||||
// Check if any pattern matches
|
||||
const foundPattern = searchPatterns.find(pattern => {
|
||||
const found = content.includes(pattern);
|
||||
if (found) {
|
||||
console.log(`SourceViewer - Found pattern "${pattern}" in ${path}`);
|
||||
}
|
||||
return found;
|
||||
});
|
||||
|
||||
if (foundPattern) {
|
||||
filePath = path;
|
||||
console.log('SourceViewer - Found file through content search:', filePath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If still not found, try a more lenient search (case-insensitive)
|
||||
if (!filePath) {
|
||||
console.log('SourceViewer - Trying case-insensitive search for:', nodeName);
|
||||
for (const [path, content] of fileContents) {
|
||||
const lowerContent = content.toLowerCase();
|
||||
const lowerNodeName = nodeName.toLowerCase();
|
||||
|
||||
if (lowerContent.includes(`def ${lowerNodeName}(`) ||
|
||||
lowerContent.includes(`function ${lowerNodeName}(`) ||
|
||||
lowerContent.includes(`const ${lowerNodeName} =`) ||
|
||||
lowerContent.includes(`class ${lowerNodeName}`)) {
|
||||
filePath = path;
|
||||
console.log('SourceViewer - Found file through case-insensitive search:', filePath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -285,7 +473,23 @@ public class ${name.replace(/\.[^/.]+$/, "")} {
|
|||
fileName,
|
||||
nodeLabel: node.label,
|
||||
nodeProperties: node.properties,
|
||||
fileContentsSize: fileContents?.size || 0
|
||||
fileContentsSize: fileContents?.size || 0,
|
||||
// Add detailed relationship debugging
|
||||
allRelationships: graph?.relationships?.length || 0,
|
||||
containsRelationships: graph?.relationships?.filter(rel => rel.type === 'CONTAINS').length || 0,
|
||||
relationshipsForThisNode: graph?.relationships?.filter(rel => rel.target === selectedNodeId || rel.source === selectedNodeId) || [],
|
||||
fileNodesInGraph: graph?.nodes?.filter(n => n.label === 'File').map(n => ({
|
||||
id: n.id,
|
||||
path: n.properties.path,
|
||||
filePath: n.properties.filePath,
|
||||
name: n.properties.name
|
||||
})) || [],
|
||||
availableFileContents: fileContents ? Array.from(fileContents.entries()).map(([path, content]) => ({
|
||||
path,
|
||||
size: content.length,
|
||||
firstLines: content.split('\n').slice(0, 3).join('\\n'),
|
||||
containsSub: content.includes('def sub(') || content.includes('function sub(')
|
||||
})) : []
|
||||
});
|
||||
|
||||
// Try to get actual file content
|
||||
|
|
@ -304,8 +508,20 @@ public class ${name.replace(/\.[^/.]+$/, "")} {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
console.log('SourceViewer - No file content found, using mock content');
|
||||
content = generateMockContent(node);
|
||||
console.log('SourceViewer - No file content found, checking if this is a built-in function');
|
||||
|
||||
// Check if this is a built-in function
|
||||
if (node.id.includes('builtin_') || nodeName === 'round' || nodeName === 'len' || nodeName === 'print' ||
|
||||
['round', 'len', 'str', 'int', 'float', 'bool', 'list', 'dict', 'tuple', 'set',
|
||||
'range', 'enumerate', 'zip', 'map', 'filter', 'sum', 'max', 'min', 'abs',
|
||||
'print', 'input', 'open', 'type', 'isinstance', 'hasattr'].includes(nodeName)) {
|
||||
|
||||
content = generateBuiltinFunctionContent(nodeName);
|
||||
console.log('SourceViewer - Using built-in function content for:', nodeName);
|
||||
} else {
|
||||
console.log('SourceViewer - Using mock content for user-defined node:', nodeName);
|
||||
content = generateMockContent(node);
|
||||
}
|
||||
}
|
||||
|
||||
// Detect language from file extension
|
||||
|
|
|
|||
|
|
@ -47,59 +47,165 @@ const GraphVisualization: React.FC<GraphVisualizationProps> = ({
|
|||
const convertToD3Format = (graph: KnowledgeGraph) => {
|
||||
const nodeIds = new Set<string>();
|
||||
|
||||
// Convert nodes
|
||||
const nodes: D3Node[] = graph.nodes.map((node: GraphNode) => {
|
||||
nodeIds.add(node.id);
|
||||
// First pass: collect all node IDs and analyze the graph structure
|
||||
graph.nodes.forEach(node => nodeIds.add(node.id));
|
||||
|
||||
// Calculate node metrics for intelligent sizing
|
||||
const nodeMetrics = new Map<string, {
|
||||
inDegree: number;
|
||||
outDegree: number;
|
||||
totalDegree: number;
|
||||
depth: number;
|
||||
isRoot: boolean;
|
||||
childrenCount: number;
|
||||
}>();
|
||||
|
||||
// Initialize metrics
|
||||
graph.nodes.forEach(node => {
|
||||
nodeMetrics.set(node.id, {
|
||||
inDegree: 0,
|
||||
outDegree: 0,
|
||||
totalDegree: 0,
|
||||
depth: 0,
|
||||
isRoot: false,
|
||||
childrenCount: 0
|
||||
});
|
||||
});
|
||||
|
||||
// Calculate degrees and relationships
|
||||
graph.relationships.forEach(rel => {
|
||||
const sourceMetrics = nodeMetrics.get(rel.source);
|
||||
const targetMetrics = nodeMetrics.get(rel.target);
|
||||
|
||||
// Determine node color and size based on type
|
||||
if (sourceMetrics && targetMetrics) {
|
||||
sourceMetrics.outDegree++;
|
||||
targetMetrics.inDegree++;
|
||||
|
||||
// For CONTAINS relationships, count children
|
||||
if (rel.type.toLowerCase() === 'contains') {
|
||||
sourceMetrics.childrenCount++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Calculate total degree and identify root nodes
|
||||
nodeMetrics.forEach((metrics) => {
|
||||
metrics.totalDegree = metrics.inDegree + metrics.outDegree;
|
||||
// Root nodes typically have high out-degree and low/zero in-degree
|
||||
metrics.isRoot = metrics.inDegree === 0 && metrics.outDegree > 0;
|
||||
});
|
||||
|
||||
// Calculate depth (simplified - could be more sophisticated)
|
||||
const calculateDepth = (nodeId: string, visited = new Set<string>()): number => {
|
||||
if (visited.has(nodeId)) return 0;
|
||||
visited.add(nodeId);
|
||||
|
||||
const parentRels = graph.relationships.filter(rel =>
|
||||
rel.target === nodeId && rel.type.toLowerCase() === 'contains'
|
||||
);
|
||||
|
||||
if (parentRels.length === 0) return 0; // Root level
|
||||
|
||||
const parentDepths = parentRels.map(rel => calculateDepth(rel.source, new Set(visited)));
|
||||
return Math.max(...parentDepths, 0) + 1;
|
||||
};
|
||||
|
||||
// Calculate depths for all nodes
|
||||
graph.nodes.forEach(node => {
|
||||
const metrics = nodeMetrics.get(node.id);
|
||||
if (metrics) {
|
||||
metrics.depth = calculateDepth(node.id);
|
||||
}
|
||||
});
|
||||
|
||||
// Convert nodes with intelligent sizing
|
||||
const nodes: D3Node[] = graph.nodes.map((node: GraphNode) => {
|
||||
const metrics = nodeMetrics.get(node.id)!;
|
||||
|
||||
// Determine base color and size based on type
|
||||
let color = '#69b3a2';
|
||||
let size = 8;
|
||||
let baseSize = 8;
|
||||
|
||||
switch (node.label.toLowerCase()) {
|
||||
case 'project':
|
||||
color = '#2E7D32';
|
||||
size = 20;
|
||||
baseSize = 25; // Largest - project root
|
||||
break;
|
||||
case 'folder':
|
||||
color = '#F57C00';
|
||||
size = 12;
|
||||
baseSize = 16;
|
||||
break;
|
||||
case 'file':
|
||||
color = '#1976D2';
|
||||
size = 10;
|
||||
baseSize = 12;
|
||||
break;
|
||||
case 'function':
|
||||
color = '#00796B';
|
||||
size = 8;
|
||||
baseSize = 8;
|
||||
break;
|
||||
case 'method':
|
||||
color = '#00695C';
|
||||
size = 7;
|
||||
baseSize = 7;
|
||||
break;
|
||||
case 'class':
|
||||
color = '#C2185B';
|
||||
size = 10;
|
||||
baseSize = 12;
|
||||
break;
|
||||
case 'variable':
|
||||
color = '#546E7A';
|
||||
size = 6;
|
||||
baseSize = 6;
|
||||
break;
|
||||
default:
|
||||
color = '#69b3a2';
|
||||
size = 8;
|
||||
baseSize = 8;
|
||||
}
|
||||
|
||||
// Calculate final size based on multiple factors
|
||||
let finalSize = baseSize;
|
||||
|
||||
// Factor 1: Hierarchy depth (higher levels = bigger)
|
||||
const depthMultiplier = Math.max(0.7, 1.5 - (metrics.depth * 0.15));
|
||||
finalSize *= depthMultiplier;
|
||||
|
||||
// Factor 2: Connection importance (more connections = bigger)
|
||||
if (metrics.totalDegree > 0) {
|
||||
const connectionMultiplier = 1 + Math.min(0.8, metrics.totalDegree * 0.1);
|
||||
finalSize *= connectionMultiplier;
|
||||
}
|
||||
|
||||
// Factor 3: Container nodes (nodes with children) should be bigger
|
||||
if (metrics.childrenCount > 0) {
|
||||
const containerMultiplier = 1 + Math.min(0.6, metrics.childrenCount * 0.08);
|
||||
finalSize *= containerMultiplier;
|
||||
}
|
||||
|
||||
// Factor 4: Root nodes get a boost
|
||||
if (metrics.isRoot) {
|
||||
finalSize *= 1.4;
|
||||
}
|
||||
|
||||
// Factor 5: Special boost for hub nodes (high degree centrality)
|
||||
if (metrics.totalDegree > 10) {
|
||||
finalSize *= 1.3;
|
||||
color = adjustColorBrightness(color, 20); // Make hub nodes slightly brighter
|
||||
}
|
||||
|
||||
// Ensure size bounds
|
||||
finalSize = Math.max(4, Math.min(35, finalSize));
|
||||
|
||||
return {
|
||||
id: node.id,
|
||||
label: node.properties.name as string || node.id,
|
||||
nodeType: node.label.toLowerCase(),
|
||||
properties: node.properties,
|
||||
color,
|
||||
size
|
||||
size: Math.round(finalSize),
|
||||
// Store metrics for potential future use
|
||||
metrics
|
||||
};
|
||||
});
|
||||
|
||||
// Convert links with validation
|
||||
// Convert links with validation (unchanged)
|
||||
const links: D3Link[] = [];
|
||||
graph.relationships.forEach((rel: GraphRelationship) => {
|
||||
// Validate that both source and target nodes exist
|
||||
|
|
@ -152,6 +258,18 @@ const GraphVisualization: React.FC<GraphVisualizationProps> = ({
|
|||
return { nodes, links };
|
||||
};
|
||||
|
||||
// Helper function to adjust color brightness
|
||||
const adjustColorBrightness = (hex: string, percent: number): string => {
|
||||
const num = parseInt(hex.replace("#", ""), 16);
|
||||
const amt = Math.round(2.55 * percent);
|
||||
const R = (num >> 16) + amt;
|
||||
const G = (num >> 8 & 0x00FF) + amt;
|
||||
const B = (num & 0x0000FF) + amt;
|
||||
return "#" + (0x1000000 + (R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 +
|
||||
(G < 255 ? G < 1 ? 0 : G : 255) * 0x100 +
|
||||
(B < 255 ? B < 1 ? 0 : B : 255)).toString(16).slice(1);
|
||||
};
|
||||
|
||||
// Initialize D3 visualization
|
||||
useEffect(() => {
|
||||
if (!svgRef.current || !graph) return;
|
||||
|
|
@ -435,18 +553,17 @@ const GraphVisualization: React.FC<GraphVisualizationProps> = ({
|
|||
|
||||
const defaultStyle: React.CSSProperties = {
|
||||
width: '100%',
|
||||
height: style.height || '700px',
|
||||
minHeight: '600px',
|
||||
height: '100%',
|
||||
minHeight: '400px',
|
||||
border: '1px solid #37474F',
|
||||
borderRadius: '8px',
|
||||
backgroundColor: '#263238',
|
||||
position: 'relative',
|
||||
boxShadow: '0 4px 20px rgba(0,0,0,0.1)',
|
||||
...style
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={`graph-visualization ${className}`} style={{ position: 'relative', width: '100%', minHeight: '600px' }}>
|
||||
<div className={`graph-visualization ${className}`} style={{ position: 'relative', width: '100%', height: '100%', minHeight: '400px' }}>
|
||||
<svg
|
||||
ref={svgRef}
|
||||
style={defaultStyle}
|
||||
|
|
|
|||
|
|
@ -618,6 +618,11 @@ const HomePage: React.FC = () => {
|
|||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
input:focus, textarea:focus {
|
||||
border-color: ${colors.primary} !important;
|
||||
box-shadow: 0 0 0 3px ${colors.primary}20 !important;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue