Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 0 additions & 29 deletions docs/checkers_doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@
- [`arrayAccess` checker](#arrayaccess-checker)
- [`classMembersOrder` checker](#classmembersorder-checker)
- [`complexity` checker](#complexity-checker)
- [`deprecatedUntagged` checker](#deprecateduntagged-checker)
- [`errorSilence` checker](#errorsilence-checker)
- [`getTypeMisUse` checker (autofixable)](#gettypemisuse-checker)
- [`langDeprecated` checker](#langdeprecated-checker)
Expand Down Expand Up @@ -2303,34 +2302,6 @@ function checkRights() {
<p><br></p>


### `deprecatedUntagged` checker

#### Description

Report usages of deprecated symbols if the `@deprecated` tag has no description (see `deprecated` check).

#### Non-compliant code:
```php
/**
* @deprecated
*/
function f() {}

f();
```

#### Compliant code:
```php
/**
* @deprecated
*/
function f() {}

g();
```
<p><br></p>


### `errorSilence` checker

#### Description
Expand Down
38 changes: 28 additions & 10 deletions src/linter/block_linter.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,13 +253,6 @@ func (b *blockLinter) checkClass(class *ir.ClassStmt) {
case *ir.ClassMethodStmt:
members = append(members, classMethod)
b.walker.CheckParamNullability(value.Params)
case *ir.PropertyListStmt:
for _, element := range value.Doc.Parsed {
if element.Name() == "deprecated" {
b.report(stmt, LevelNotice, "deprecated", "Has deprecated field in class %s", class.ClassName.Value)
}
}
members = append(members, classOtherMember)
default:
members = append(members, classOtherMember)
}
Expand Down Expand Up @@ -565,6 +558,15 @@ func (b *blockLinter) checkNew(e *ir.NewExpr) {
if class.IsInterface() {
b.report(e.Class, LevelError, "invalidNew", "Cannot instantiate interface %s", class.Name)
}

if class.IsDeprecated() {
if class.WithDeprecationNote() {
b.report(e, LevelNotice, "deprecated", "Try to create instance of the class %s that was marked as deprecated (%s)", class.Name, class.DeprecationInfo)
} else {
b.report(e, LevelNotice, "deprecated", "Try to create instance %s class that was marked as deprecated", class.Name)
}
}

b.walker.r.checker.CheckNameCase(e.Class, className, class.Name)
}

Expand Down Expand Up @@ -1035,7 +1037,7 @@ func (b *blockLinter) checkDeprecatedFunctionCall(e *ir.FunctionCallExpr, call *
return
}

b.report(e.Function, LevelNotice, "deprecatedUntagged", "Call to deprecated function %s", utils.NameNodeToString(e.Function))
b.report(e.Function, LevelNotice, "deprecated", "Call to deprecated function %s", utils.NameNodeToString(e.Function))
}

func (b *blockLinter) checkFunctionAvailability(e *ir.FunctionCallExpr, call *funcCallInfo) {
Expand Down Expand Up @@ -1387,7 +1389,7 @@ func (b *blockLinter) checkMethodCall(e *ir.MethodCallExpr) {
b.report(e.Method, LevelNotice, "deprecated", "Call to deprecated method {%s}->%s() (%s)",
call.methodCallerType, call.methodName, deprecation)
} else {
b.report(e.Method, LevelNotice, "deprecatedUntagged", "Call to deprecated method {%s}->%s()",
b.report(e.Method, LevelNotice, "deprecated", "Call to deprecated method {%s}->%s()",
call.methodCallerType, call.methodName)
}
}
Expand Down Expand Up @@ -1465,7 +1467,7 @@ func (b *blockLinter) checkStaticCall(e *ir.StaticCallExpr) {
b.report(e.Call, LevelNotice, "deprecated", "Call to deprecated static method %s::%s() (%s)",
call.className, call.methodName, deprecation)
} else {
b.report(e.Call, LevelNotice, "deprecatedUntagged", "Call to deprecated static method %s::%s()",
b.report(e.Call, LevelNotice, "deprecated", "Call to deprecated static method %s::%s()",
call.className, call.methodName)
}
}
Expand Down Expand Up @@ -1524,6 +1526,14 @@ func (b *blockLinter) checkPropertyFetch(e *ir.PropertyFetchExpr) {
b.report(e.Property, LevelError, "accessLevel", "Cannot access %s property %s->%s", fetch.info.AccessLevel, fetch.className, fetch.propertyNode.Value)
}

if fetch.info.IsDeprecated() {
if fetch.info.WithDeprecationNote() {
b.report(e, LevelNotice, "deprecated", "Try to call property %s that was marked as deprecated (%s) in the class %s", fetch.propertyNode.Value, fetch.info.DeprecationInfo, fetch.className)
} else {
b.report(e, LevelNotice, "deprecated", "Try to call property %s that was marked as deprecated in the class %s", fetch.propertyNode.Value, fetch.className)
}
}

left, ok := b.walker.ctx.sc.GetVarType(e.Variable)
if ok {
b.checkSafetyCall(e, left, "", "PropertyFetch")
Expand Down Expand Up @@ -1577,6 +1587,14 @@ func (b *blockLinter) checkClassConstFetch(e *ir.ClassConstFetchExpr) {
if fetch.isFound && !canAccess(b.classParseState(), fetch.implClassName, fetch.info.AccessLevel) {
b.report(e.ConstantName, LevelError, "accessLevel", "Cannot access %s constant %s::%s", fetch.info.AccessLevel, fetch.implClassName, fetch.constName)
}

if fetch.info.IsDeprecated() {
if fetch.info.WithDeprecationNote() {
b.report(e, LevelNotice, "deprecated", "Try to call constant %s that was marked as deprecated (%s) from the class %s", fetch.constName, fetch.info.DeprecationInfo, fetch.className)
} else {
b.report(e, LevelNotice, "deprecated", "Try to call constant %s that was marked as deprecated from the class %s", fetch.constName, fetch.className)
}
}
}

func (b *blockLinter) checkClassSpecialNameCase(n ir.Node, className string) {
Expand Down
8 changes: 5 additions & 3 deletions src/linter/block_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ func findProperty(info *meta.Info, className, propName string) (res solver.FindP
// Construct a dummy property from the magic method.
p.ClassName = m.ClassName
p.TraitName = m.TraitName

p.Info = meta.PropertyInfo{
Pos: m.Info.Pos,
Typ: m.Info.Typ,
AccessLevel: m.Info.AccessLevel,
Pos: m.Info.Pos,
Typ: m.Info.Typ,
AccessLevel: m.Info.AccessLevel,
DeprecationInfo: m.Info.DeprecationInfo,
}
return p, true, true
}
Expand Down
75 changes: 38 additions & 37 deletions src/linter/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,44 @@ import (
//
// Version log:
//
// 27 - added Static field to meta.FuncInfo
// 28 - array type parsed as mixed[]
// 29 - updated type inference for ClassConstFetch
// 30 - resolve ClassConstFetch to a wrapped type string
// 31 - fixed plus operator type inference for arrays
// 32 - replaced Static:bool with Flags:uint8 in meta.FuncInfo
// 33 - support parsing of array<k,v> and list<type>
// 34 - support parsing of ?ClassName as "ClassName|null"
// 35 - added Flags:uint8 to meta.ClassInfo
// 36 - added FuncAbstract bit to FuncFlags
// added FuncFinal bit to FuncFlags
// added ClassFinal bit to ClassFlags
// FuncInfo now stores original function name
// ClassInfo now stores original class name
// 37 - added ClassShape bit to ClassFlags
// changed meta.scopeVar bool fields representation
// 38 - replaced TypesMap.immutable:bool with flags:uint8.
// added mapPrecise flag to mark precise type maps.
// 39 - added new field Value in ConstantInfo
// 40 - changed string const value storage (no quotes)
// 41 - const-folding affected const definition values
// 42 - bool-typed consts are now stored in meta info
// 43 - define'd const values stored in cache
// 44 - rename ConstantInfo => ConstInfo
// 45 - added Mixins field to meta.ClassInfo
// 46 - changed the way of inferring the return type of functions and methods
// 47 - forced cache version invalidation due to the #921
// 48 - renamed meta.TypesMap to types.Map; this affects gob encoding
// 49 - for shape, names are now generated using the keys that make up this shape
// 50 - added Flags field for meta.PropertyInfo
// 51 - added anonymous classes
// 52 - renamed all PhpDoc and Phpdoc with PHPDoc
// 53 - added DeprecationInfo for functions and methods and support for some attributes
// 54 - forced cache version invalidation due to the #1165
// 55 - updated go version 1.16 -> 1.21
// 56 - added isVariadic to meta.FuncInfo
const cacheVersion = 56
// 27 - added Static field to meta.FuncInfo
// 28 - array type parsed as mixed[]
// 29 - updated type inference for ClassConstFetch
// 30 - resolve ClassConstFetch to a wrapped type string
// 31 - fixed plus operator type inference for arrays
// 32 - replaced Static:bool with Flags:uint8 in meta.FuncInfo
// 33 - support parsing of array<k,v> and list<type>
// 34 - support parsing of ?ClassName as "ClassName|null"
// 35 - added Flags:uint8 to meta.ClassInfo
// 36 - added FuncAbstract bit to FuncFlags
// added FuncFinal bit to FuncFlags
// added ClassFinal bit to ClassFlags
// FuncInfo now stores original function name
// ClassInfo now stores original class name
// 37 - added ClassShape bit to ClassFlags
// changed meta.scopeVar bool fields representation
// 38 - replaced TypesMap.immutable:bool with flags:uint8.
// added mapPrecise flag to mark precise type maps.
// 39 - added new field Value in ConstantInfo
// 40 - changed string const value storage (no quotes)
// 41 - const-folding affected const definition values
// 42 - bool-typed consts are now stored in meta info
// 43 - define'd const values stored in cache
// 44 - rename ConstantInfo => ConstInfo
// 45 - added Mixins field to meta.ClassInfo
// 46 - changed the way of inferring the return type of functions and methods
// 47 - forced cache version invalidation due to the #921
// 48 - renamed meta.TypesMap to types.Map; this affects gob encoding
// 49 - for shape, names are now generated using the keys that make up this shape
// 50 - added Flags field for meta.PropertyInfo
// 51 - added anonymous classes
// 52 - renamed all PhpDoc and Phpdoc with PHPDoc
// 53 - added DeprecationInfo for functions and methods and support for some attributes
// 54 - forced cache version invalidation due to the #1165
// 55 - updated go version 1.16 -> 1.21
// 56 - added isVariadic to meta.FuncInfo
// 57 - added DeprecationInfo for property and const
const cacheVersion = 57

var (
errWrongVersion = errors.New("Wrong cache version")
Expand Down
4 changes: 2 additions & 2 deletions src/linter/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ main();
//
// If cache encoding changes, there is a very high chance that
// encoded data lengh will change as well.
wantLen := 5952
wantLen := 6069
haveLen := buf.Len()
if haveLen != wantLen {
t.Errorf("cache len mismatch:\nhave: %d\nwant: %d", haveLen, wantLen)
Expand All @@ -158,7 +158,7 @@ main();
// 2. Check cache "strings" hash.
//
// It catches new fields in cached types, field renames and encoding of additional named attributes.
wantStrings := "690e77c94ecdd7878de0bf6f6881d786cf1fafa4588f7905f54d700646c4952aad359008ae2dcddb1c7f29163ecee62355d525672090ac30257bc414f690006f"
wantStrings := "339e0a8348fcf8f5060b8ce3534f97be9af03fe462ca06eba27ab83488efc5e5d5813f4fb227535997f0c4a99253f57042876fdead6f058a923219c99593f3b6"
haveStrings := collectCacheStrings(buf.String())
if haveStrings != wantStrings {
t.Errorf("cache strings mismatch:\nhave: %q\nwant: %q", haveStrings, wantStrings)
Expand Down
7 changes: 6 additions & 1 deletion src/linter/phpdoc_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,16 @@ func (e *PHPDocErrors) pushLint(place PHPDocLocation, format string, args ...int
type classPHPDocParseResult struct {
properties meta.PropertiesMap
methods meta.FunctionsMap
deprecation meta.DeprecationInfo
errs PHPDocErrors
mixins []string
packageName string
internal bool
deprecated bool
}

type variablePHPDocParseResult struct {
typesMap types.Map
deprecation meta.DeprecationInfo
}

func parseClassPHPDocMethod(classNode ir.Node, ctx *rootContext, result *classPHPDocParseResult, part *phpdoc.RawCommentPart) {
Expand Down
19 changes: 0 additions & 19 deletions src/linter/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -743,25 +743,6 @@ f();`,
*/
function f() {}

g();`,
},

{
Name: "deprecatedUntagged",
Default: false,
Quickfix: false,
Comment: "Report usages of deprecated symbols if the `@deprecated` tag has no description (see `deprecated` check).",
Before: `/**
* @deprecated
*/
function f() {}

f();`,
After: `/**
* @deprecated
*/
function f() {}

g();`,
},

Expand Down
Loading