Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support @psalm-private-mutate annotation #2729

Closed
christian-kolb opened this issue Jan 31, 2020 · 8 comments
Closed

Support @psalm-private-mutate annotation #2729

christian-kolb opened this issue Jan 31, 2020 · 8 comments

Comments

@christian-kolb
Copy link
Contributor

With PHP 7.4 using public properties in a type safe way is finally possible. In some languages you have the concept of marking a property to be able to be read from outside the class, but not modified. Basically public get, but private set.
Psalm already supports @psalm-readonly which prevents the property by being modified anywhere. It would be awesome to have a similar annotation which allows to modify the property with class methods. With this the public get, private set paradigm would be available to PHP users 🙂
Please let me know when there is already concept within psalm with which I could get the same result, I haven't found one yet.

@psalm-github-bot
Copy link

Hey @christian-kolb, can you reproduce the issue on https://psalm.dev ?

@muglug
Copy link
Collaborator

muglug commented Jan 31, 2020

@christian-kolb
Copy link
Contributor Author

christian-kolb commented Feb 1, 2020

@muglug Yes, but thanks for the reminder (was a while ago). This might be a good example to help me explain what I want.

<?php

class Counter {
  /** @psalm-new-annotation */
  public int $count = 0;
  
  public function increment() : void {
    $this->count++;
  }
}

function makeCounter() : Counter {
  $a = new Counter();
  $a->increment(); // this is fine
  return $a;
}

function canNotUpdateDirectly(Counter $a) : Counter {
  $a->count = 10; // This is not allowed
}

function transformCount(Counter $a): array {
  return [
    'count' => $a->count, // Access without getter
  ]
}

So basically I can use a public property as getter, not as setter, but modify it through its class methods.

As far as I'm aware this behaviour can only made available with getter methods but not with psalm annotations. Basically I want to get rid of getters, because I have many instances where I only have them to get this result. And at the moment this means I have "clean" classes without getters and ones cluttered with them. It would be amazing if I could solve this issue with psalm 🙂

@muglug
Copy link
Collaborator

muglug commented Feb 1, 2020

I think you're asking for /** @psalm-external-mutation-free */ – does its use in the article line up with what you want?

@christian-kolb
Copy link
Contributor Author

@muglug Kind of, but this only applies to methods, doesn't it? I would need it to be applied for classes and properties. I tried with psalm.dev, but it doesn't raise any issues:

https://psalm.dev/r/69691fb410

It would describe the behaviour I want 🙂

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/69691fb410
<?php

/** @psalm-external-mutation-free */
class Test
{
  /** @psalm-external-mutation-free */
  public int $count;
  
  public function __construct() {
    $this->count = 0;
  }
}
  
function foo() : void {
  $test = new Test();
  $test->count = 10; // Should raise an issue here
  echo $test->count;
}
Psalm output (using commit f234730):

No issues!

@muglug muglug changed the title Public get, private set annotation Support @psalm-readonly-public annotation Feb 1, 2020
@muglug muglug changed the title Support @psalm-readonly-public annotation Support @psalm-private-set annotation Feb 1, 2020
@muglug
Copy link
Collaborator

muglug commented Feb 1, 2020

OK, I understand now – if you contribute an implementation and/or documentation, I'll do whatever's left.

I suggest a per-property annotation of @psalm-private-set

@christian-kolb
Copy link
Contributor Author

Awesome, I have no idea how I would start an implementation for it. But I'm sure I can write documentation for it. @psalm-private-set sounds great. I'll start working on it tomorrow 🙂

@christian-kolb christian-kolb changed the title Support @psalm-private-set annotation Support @psalm-private-mutate annotation Feb 2, 2020
@muglug muglug closed this as completed in 93fc1b1 Feb 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants