Check referencing instance variables from static context.

This commit is contained in:
Jindra Petřík
2025-05-30 23:36:46 +02:00
parent af408060b3
commit df9791ebda
11 changed files with 312 additions and 164 deletions

View File

@@ -26,9 +26,15 @@ import java.util.List;
public class FunctionScope implements Scope {
private final List<VariableOrScope> privateItems;
private final boolean isStatic;
public FunctionScope(List<VariableOrScope> functionBody) {
public FunctionScope(List<VariableOrScope> functionBody, boolean isStatic) {
this.privateItems = functionBody;
this.isStatic = isStatic;
}
public boolean isStatic() {
return isStatic;
}
@Override

View File

@@ -51,60 +51,132 @@ public interface SimpleParser {
List<VariableOrScope> sharedVariables,
Map<Integer, List<Integer>> definitionPosToReferences,
Map<Integer, Integer> referenceToDefinition,
Map<String, Integer> parentVarNameToDefinitionPosition
List<SimpleParseException> errors
) {
parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), new LinkedHashMap<>(), true, errors);
}
public static void parseVariablesList(
List<VariableOrScope> privateVariables,
List<VariableOrScope> sharedVariables,
Map<Integer, List<Integer>> definitionPosToReferences,
Map<Integer, Integer> referenceToDefinition,
Map<String, Integer> parentVarFullNameToDefinitionPosition,
Map<String, Integer> parentVarNameToDefinitionPosition,
Map<Integer, Boolean> positionToStatic,
boolean isStatic,
List<SimpleParseException> errors
) {
Map<String, Integer> privateVarNameToDefinitionPosition = new LinkedHashMap<>();
privateVarNameToDefinitionPosition.putAll(parentVarNameToDefinitionPosition);
Map<String, Integer> privateVarFullNameToDefinitionPosition = new LinkedHashMap<>();
privateVarFullNameToDefinitionPosition.putAll(parentVarFullNameToDefinitionPosition);
for (VariableOrScope vt : privateVariables) {
if (vt instanceof Variable) {
Variable v = (Variable) vt;
if (v.definition) {
privateVarNameToDefinitionPosition.put(v.name, v.position);
privateVarFullNameToDefinitionPosition.put(v.name, v.position);
privateVarNameToDefinitionPosition.put(v.getLastName(), v.position);
definitionPosToReferences.put(v.position, new ArrayList<>());
positionToStatic.put(v.position, v.isStatic != null ? v.isStatic : isStatic);
} else {
if (!privateVarNameToDefinitionPosition.containsKey(v.name)) {
parentVarNameToDefinitionPosition.put(v.name, -v.position - 1);
privateVarNameToDefinitionPosition.put(v.name, -v.position - 1);
if (!privateVarFullNameToDefinitionPosition.containsKey(v.name)
&& !privateVarNameToDefinitionPosition.containsKey(v.getFirstName())) {
parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
parentVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1);
privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
privateVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1);
definitionPosToReferences.put(-v.position - 1, new ArrayList<>());
definitionPosToReferences.get(-v.position - 1).add(v.position);
referenceToDefinition.put(v.position, -v.position - 1);
} else {
int definitionPos = privateVarNameToDefinitionPosition.get(v.name);
definitionPosToReferences.get(definitionPos).add(v.position);
referenceToDefinition.put(v.position, definitionPos);
if ("this".equals(v.name) && isStatic) {
errors.add(new SimpleParseException("Cannot use this in static context", -1, v.position));
} else {
int definitionPos;
if (privateVarFullNameToDefinitionPosition.containsKey(v.name)) {
definitionPos = privateVarFullNameToDefinitionPosition.get(v.name);
} else {
definitionPos = privateVarNameToDefinitionPosition.get(v.getFirstName());
}
boolean staticDefinition = definitionPos >= 0 ? positionToStatic.get(definitionPos) : true;
if (!(!staticDefinition && isStatic)) {
definitionPosToReferences.get(definitionPos).add(v.position);
referenceToDefinition.put(v.position, definitionPos);
} else {
errors.add(new SimpleParseException("Cannot reference instance variable from static context", -1, v.position));
}
}
}
}
}
if (vt instanceof Scope) {
Scope vs = (Scope) vt;
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarNameToDefinitionPosition);
boolean subStatic = isStatic;
if (vs instanceof FunctionScope) {
subStatic = ((FunctionScope) vs).isStatic();
}
if (vs instanceof TraitVarConstValueScope) {
subStatic = ((TraitVarConstValueScope) vs).isStatic();
}
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors);
}
}
for (VariableOrScope vt : sharedVariables) {
if (vt instanceof Variable) {
Variable v = (Variable) vt;
if (v.definition) {
parentVarNameToDefinitionPosition.put(v.name, v.position);
privateVarNameToDefinitionPosition.put(v.name, v.position);
parentVarFullNameToDefinitionPosition.put(v.name, v.position);
parentVarNameToDefinitionPosition.put(v.getLastName(), v.position);
privateVarFullNameToDefinitionPosition.put(v.name, v.position);
privateVarNameToDefinitionPosition.put(v.getLastName(), v.position);
definitionPosToReferences.put(v.position, new ArrayList<>());
positionToStatic.put(v.position, v.isStatic != null ? v.isStatic : isStatic);
} else {
if (!privateVarNameToDefinitionPosition.containsKey(v.name)) {
parentVarNameToDefinitionPosition.put(v.name, -v.position - 1);
privateVarNameToDefinitionPosition.put(v.name, -v.position - 1);
if (!privateVarFullNameToDefinitionPosition.containsKey(v.name)
&& !privateVarNameToDefinitionPosition.containsKey(v.getFirstName())) {
parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
parentVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1);
privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1);
privateVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1);
definitionPosToReferences.put(-v.position - 1, new ArrayList<>());
definitionPosToReferences.get(-v.position - 1).add(v.position);
referenceToDefinition.put(v.position, -v.position - 1);
} else {
int definitionPos = privateVarNameToDefinitionPosition.get(v.name);
definitionPosToReferences.get(definitionPos).add(v.position);
referenceToDefinition.put(v.position, definitionPos);
if ("this".equals(v.name) && isStatic) {
errors.add(new SimpleParseException("Cannot use this in static context", -1, v.position));
} else {
int definitionPos;
if (privateVarFullNameToDefinitionPosition.containsKey(v.name)) {
definitionPos = privateVarFullNameToDefinitionPosition.get(v.name);
} else {
definitionPos = privateVarNameToDefinitionPosition.get(v.getFirstName());
}
boolean staticDefinition = definitionPos >= 0 ? positionToStatic.get(definitionPos) : true;
if (!(!staticDefinition && isStatic)) {
definitionPosToReferences.get(definitionPos).add(v.position);
referenceToDefinition.put(v.position, definitionPos);
} else {
errors.add(new SimpleParseException("Cannot reference instance variable from static context", -1, v.position));
}
}
}
}
}
if (vt instanceof Scope) {
Scope vs = (Scope) vt;
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarNameToDefinitionPosition);
boolean subStatic = isStatic;
if (vs instanceof FunctionScope) {
subStatic = ((FunctionScope) vs).isStatic();
}
if (vs instanceof TraitVarConstValueScope) {
subStatic = ((TraitVarConstValueScope) vs).isStatic();
}
parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors);
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2010-2025 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.simpleparser;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class TraitVarConstValueScope implements Scope {
private List<VariableOrScope> sharedItems;
private final boolean isStatic;
public TraitVarConstValueScope(List<VariableOrScope> sharedItems, boolean isStatic) {
this.sharedItems = sharedItems;
this.isStatic = isStatic;
}
public boolean isStatic() {
return isStatic;
}
@Override
public List<VariableOrScope> getSharedItems() {
return sharedItems;
}
@Override
public List<VariableOrScope> getPrivateItems() {
return new ArrayList<>();
}
}

View File

@@ -25,15 +25,35 @@ public class Variable implements VariableOrScope {
public boolean definition;
public String name;
public int position;
public Boolean isStatic;
public Variable(boolean definition, String name, int position) {
this(definition, name, position, null);
}
public Variable(boolean definition, String name, int position, Boolean isStatic) {
this.definition = definition;
this.name = name;
this.position = position;
this.isStatic = isStatic;
}
@Override
public String toString() {
return (definition ? "definition of " : "") + name + " at " + position;
return (definition ? "definition of " : "") + (isStatic ? "static " : "") + name + " at " + position;
}
public String getLastName() {
if (name.contains(".")) {
return name.substring(name.lastIndexOf(".") + 1);
}
return name;
}
public String getFirstName() {
if (name.contains(".")) {
return name.substring(0, name.indexOf("."));
}
return name;
}
}