phodal / chapi

CHAPI (Common Hierarchical Abstract Parser and Information Converter) streamlines code analysis by converting diverse language source code into a unified abstract model, simplifying cross-language development. Chapi 是一个通用层次抽象解析器与信息转换器,它可以将不同编程语言的源代码转换为统一的层次抽象模型。
https://chapi.phodal.com/
Mozilla Public License 2.0
274 stars 44 forks source link

Bug: Python- Class variables and Global Variables in Procedural Files are captured in every function #32

Open JayGhiya opened 13 hours ago

JayGhiya commented 13 hours ago

For example:

class UserService:
    # Class variables
    USER_NOT_FOUND = "User not found"

    def create_user(self, db: Session, user: UserCreate) -> User:
        hashed_password = get_password_hash(user.password)
        db_user = User(
            username=user.username,
            email=user.email,
            hashed_password=hashed_password
        )
        db.add(db_user)
        db.commit()
        db.refresh(db_user)
        return db_user

    def get_users(self, db: Session, skip: int = 0, limit: int = 100):
        return db.query(User).offset(skip).limit(limit).all() 

Class variable is captured as part of all functions of class duplicated instead of being in Fields in Node.

This also happens with procedural nodes of chapi where global variables are not captured in fields but instead in all the functions.

So it should not be captured as part of any function instead should be part of fields in any case be if of type class or none(procedure).

Let me know your thoughts.

JayGhiya commented 12 hours ago

This is the current output:

{
        "NodeName": "UserService",
        "Type": "CLASS",
        "FilePath": "/Users/jayghiya/Documents/unoplat/sample_python_project/app/services/user_service.py",
        "Functions": [
            {
                "Name": "create_user",
                "Parameters": [
                    {
                        "TypeValue": "db",
                        "TypeType": "Session"
                    },
                    {
                        "TypeValue": "user",
                        "TypeType": "UserCreate"
                    }
                ],
                "FunctionCalls": [
                    {
                        "NodeName": "db",
                        "FunctionName": "refresh",
                        "Position": {
                            "StartLine": 19,
                            "StartLinePosition": 10,
                            "StopLine": 19,
                            "StopLinePosition": 26
                        }
                    }
                ],
                "Position": {
                    "StartLine": 10,
                    "StartLinePosition": 4,
                    "StopLine": 22,
                    "StopLinePosition": 4
                },
                "LocalVariables": [
                    {
                        "TypeValue": "USER_NOT_FOUND",
                        "TypeType": "\"User not found\""
                    },
                    {
                        "TypeValue": "hashed_password",
                        "TypeType": "get_password_hash"
                    },
                    {
                        "TypeValue": "db_user",
                        "TypeType": "User"
                    }
                ],
                "Content": "def create_user(self, db: Session, user: UserCreate) -> User:        hashed_password = get_password_hash(user.password)        db_user = User(            username=user.username,            email=user.email,            hashed_password=hashed_password        )        db.add(db_user)        db.commit()        db.refresh(db_user)        return db_user        "
            },
            {
                "Name": "get_users",
                "Parameters": [
                    {
                        "TypeValue": "db",
                        "TypeType": "Session"
                    },
                    {
                        "DefaultValue": "0",
                        "TypeValue": "skip",
                        "TypeType": "int"
                    },
                    {
                        "DefaultValue": "100",
                        "TypeValue": "limit",
                        "TypeType": "int"
                    }
                ],
                "Position": {
                    "StartLine": 22,
                    "StartLinePosition": 4,
                    "StopLine": 23,
                    "StopLinePosition": 62
                },
                "LocalVariables": [
                    {
                        "TypeValue": "USER_NOT_FOUND",
                        "TypeType": "\"User not found\""
                    },
                    {
                        "TypeValue": "hashed_password",
                        "TypeType": "get_password_hash"
                    },
                    {
                        "TypeValue": "db_user",
                        "TypeType": "User"
                    }
                ],
                "Content": "def get_users(self, db: Session, skip: int = 0, limit: int = 100):        return db.query(User).offset(skip).limit(limit).all() "
            }
        ],
        "Imports": [
            {
                "Source": "sqlalchemy.orm",
                "UsageName": [
                    "Session"
                ]
            },
            {
                "Source": "app.models.database",
                "UsageName": [
                    "User"
                ]
            },
            {
                "Source": "app.models.schemas",
                "UsageName": [
                    "UserCreate"
                ]
            },
            {
                "Source": "app.utils.helpers",
                "UsageName": [
                    "get_password_hash"
                ]
            }
        ],
        "Position": {
            "StartLine": 6,
            "StopLine": 23,
            "StopLinePosition": 62
        },
        "Content": "class UserService:    # Class variables    USER_NOT_FOUND = \"User not found\"        def create_user(self, db: Session, user: UserCreate) -> User:        hashed_password = get_password_hash(user.password)        db_user = User(            username=user.username,            email=user.email,            hashed_password=hashed_password        )        db.add(db_user)        db.commit()        db.refresh(db_user)        return db_user        def get_users(self, db: Session, skip: int = 0, limit: int = 100):        return db.query(User).offset(skip).limit(limit).all() "
    }